StructureMap для создания объекта конфигурации в c # winforms

#c# #.net #structuremap

#c# #.net #structuremap

Вопрос:

Используя structuremap и c # 4.0, в основном, у меня есть вот что:

 interface IBoard
{
    void Setup();
}

class Board : IBoard
{
    IConfig _config;

    Board(IConfig config)
    {
        _config = config;
    }

    void Setup()
    {
        //use the _config object here 
    }
}

class Game
{
    IBoard _board;

    Game(IBoard board)
    {
        _board = board;
    }
}

partial class Form1
{
    Form1()
    {
        InitializeForm();
    }

    //in here we need to do some work to setup the IConfig object 
    //via form controls
}

partial class Form2
{
    Game _game;

    Form1(Game game)
    {
        InitializeForm();
        _game = game;
    }
}
  

теперь при обычном использовании идентификатора просто скажите

 For<Type>().Use<Class>() 
  

или что-то в этом роде для всех моих зависимостей. Однако мне нужен наилучший шаблон для установки значений объекта конфигурации в form1, а затем вызова form2 со значениями конфигурации, установленными в памяти и поддерживаемыми во всем приложении? я думал об использовании синглтона, однако синглтон должен быть поддающимся имитации или, по крайней мере, статически создаваться и не принимать конфигурацию на основе параметров… так что же делать? в настоящее время я создаю form1 в программе запуска winform через

 ObjectFactory.Get<Form1>();
  

Ответ №1:

Я не думаю, что IConfig подходит для создания с использованием контейнера, поскольку вы не знаете значений параметров, пока не придет время создать его экземпляр. Я думаю, вам нужно предоставить экземпляр конфигурации коду, который вызывает контейнер, чтобы получить форму.

Вы можете предоставить аргументы контейнеру, используя метод With:

 ObjectFactory.With<IConfig>(theConfig).GetInstance<Form2>();
  

Вы хотите свести к минимуму вызовы контейнера, предпочтительно только в одном месте вашего приложения, которое подключает остальную его часть во время начальной загрузки. Альтернативой является регистрация функции, разрешение этого во время начальной загрузки и использование этого для создания экземпляра Form2.

Регистрация:

 var formFactory = config => new Form2(config);
x.For<Func<IConfig, Form2>>().Use( () => formFactory);
  

Использование:

 //Get the Func somehow, preferably as a ctor dependency in Form1
var form2Creator = ... 
var config = new Config({some parameters from Form1 here});
var form2 = form2Creator(config);
  

Комментарии:

1. звучит неплохо, это в значительной степени то, что я искал… я проверю это и отправлю обратно

2. я немного отредактировал ваш ответ, чтобы соответствовать, но проблема по-прежнему заключается в том, что игровой объект должен быть передан через form1 ctor (который я считал ненужным — пожалуйста, расскажите мне свои мысли по этому поводу), а игровой объект, у которого есть объект IConfig, выдает исключение, потому что он не создается должным образом SM (когда я удаляю его, все работает так)

3. @AaronHS — пожалуйста, обновите вопрос необходимыми зависимостями для каждого класса и укажите, почему и когда Form1 нужен класс Game. Также, если вы попробовали мое предложение, пожалуйста, расскажите, как вы его реализовали.

4. я сделал, и кто-то отредактировал его. я обновил ваш ответ, потому что он был правильным, но в нем отсутствовал код, и кто-то его стер. потрясающая работа @andomar. @PHeigerg я принял ваш ответ, но я не переписываю недостающий код. (там было совсем немного, но в целом ваш ответ направил меня на правильный путь, поэтому я принимаю)

Ответ №2:

Если вы зарегистрируете свой Config таким образом:

 For(Of IConfig).Singleton.Use(Of Config)
  

Он будет одноэлементным, а StructureMap позаботится обо всем остальном.

Другой подход заключается:

запускаете единицу работы и устанавливаете свои значения, выполняете свою работу и утилизируете UoW, но это немного сложно, и я понятия не имею, нужен ли вам UoW или нет.

Комментарии:

1. Проблема с этим подходом, если я правильно понимаю OP, заключается в том, что конфигурация создается на основе аргументов, известных только при создании (не во время регистрации типов).

2. Он создается при первом запросе из ObjectFactory. Кстати, вам действительно нужно создавать его, когда ваши типы зарегистрированы? Если да, оставьте комментарий, и я обновлю свой пост.

3. Для создания конфигурации вам нужны некоторые данные, которые недоступны до тех пор, пока пользователь не введет их в Form1 (что происходит после завершения регистрации). Это мой взгляд на вопрос OP.

4. исправьте Фейдберга. если данные конфигурации были статическими, я просто указываю, что мои контейнеры используются для некоторого конкретного класса, который либо загружает, либо содержит данные. что мне нужно, так это значения, которые будут установлены после того, как контейнер DI зарегистрирует все свои сопоставления