Ninject for winforms - моя архитектура делает это бесполезным? - PullRequest
6 голосов
/ 16 декабря 2010

Я пробую Ninject с приложением winforms (в основном, эскиз, я использую его как ката, но ничего более строгого или конкретного) в .net 4.

Чтобы создать основную форму, я делаю что-то вроде:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        [...]
        IKernel kernel = BuildKernel();
        Application.Run(kernel.Get<frmMain>());
    }

    static IKernel BuildKernel()
    {
        var modules = new INinjectModule[] 
        { 
            [..modules]
        };

        return new StandardKernel(modules);
    }
}

Fine. Это создает основную форму и хорошо отображает ее, передавая соответствующие реализации интерфейса инжектированному конструктору.

И что теперь? Мое приложение является MDI и будет иметь несколько дочерних окон для манипулирования моделью приложения. У меня больше нет ссылки на ядро, так как я могу Get() эти формы? Я предполагаю, что очевидный ответ - «передать ядро ​​в форму», но это ужасно грязная стратегия, и я уверен, что она не вписывается в философию DI.

Здесь я укажу, что документация для Ninject 2 отстой . Все, что я могу найти, повторяет основные примеры, без реального объяснения того, как DI, использующий Ninject, облегчает задачу. Стандарт приведенного примера не достаточно сложен, чтобы оправдать необходимость кодирования и создания модулей и привязок.

edit # 1:

Изучив ссылки, любезно предоставленные Сэм Холдер , я пробую подход «составной корень». Моя архитектура теперь заставляет все формы, которые она использует, получить из CompositedForm с семантикой конструктора, таким образом:

    [Inject]
    public CompositingForm(ICompositionRoot CompositionRoot)
    {
        InitializeComponent();
        this.CompositionRoot = CompositionRoot;
    }
    public readonly ICompositionRoot CompositionRoot;

    public CompositingForm() : this(new DummyCompositionRoot()) { }

Второй конструктор предназначен для дизайнера форм, который глуп и не может понять разметку формы, если вы не предоставите пустой конструктор. Теперь каждая форма, созданная с использованием IKernel.Get<AForm>(), будет (должна) иметь корень композиции, вставленный в нее.

Итак, поскольку я медленный ученик - теперь вопрос действительно «Что должно идти в этом корне композиции»?

Ответы [ 3 ]

5 голосов
/ 16 декабря 2010

вы не можете передать фабрику для создания дочерних форм конструктору форм, и форма использует это для их получения, тогда ninject соединит фабричную зависимость, когда форма создается с использованием get?

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

Этот ответ может помочь

2 голосов
/ 19 декабря 2010

Примечание: я не знаю много о Ninject, но я работал с Spring.net, который намного сложнее.Принципы могут быть примерно такими же.

Ответ Сэма Холдера превосходен, если у вас есть несколько объектов одного (внедренного) типа для создания (например, CustomerOrderItem).

Если вы просто хотите подключитьсяВаша основная форма Я бы сказал, что ваш конструктор mdi-frmMain получает параметры для каждого дочернего окна, которое он должен содержать, и позволяет Ninject создавать и вставлять дочерние окна.Таким образом, нет необходимости ссылаться на NInject вне «класса Program».Это называется Constructor-Injection.

В качестве альтернативы вы можете добавить метод в форму, который добавляет вам страницу mdi (MethodInjection).

static void Main()
{
    [...]
    IKernel kernel = BuildKernel();
    var main = kernel.Get<frmMain>();
    main.AddClientForm(kernel.Get<CustomerForm>()) ;
    main.AddClientForm(kernel.Get<InvoiceForm>()) ;
    Application.Run(main);
}
1 голос
/ 26 января 2011

Благодаря Жоао Алмейде и Келлабайт Я нашел метод, который более или менее удовлетворителен:

  • Определите пользовательский атрибут, который раскрывает любой бизнесправила, которые вас интересуют;
  • Определите реализацию IInjectionHeuristic, которая распознает этот атрибут;
  • Используйте ViewModelLocator для загрузки модулей в целое ядро.
...