Ninject for winforms - 我的架构是否使这无用?

时间:2010-12-16 11:58:56

标签: winforms dependency-injection ninject

我在.net 4中尝试使用winforms应用程序Ninject(基本上是草图,我使用它有点像kata,但没有那么严格或具体)。

要创建主窗体,我正在执行以下操作:

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);
    }
}

精细。这将创建一个主窗体并很好地显示它,将适当的接口实现传递给注入的构造函数。

现在怎样?我的应用程序是一个MDI,将有几个子窗口用于操作应用程序模型。我不再引用内核,所以我应该如何Get()这些形式?显而易见的答案是“我认为将内核传递给表单”,但这是一个非常混乱的策略,我确信这不符合DI的哲学。

我将在此指出Ninject 2 的文档很糟糕。我能找到的一切都重复了基本的例子,而没有真正解释使用Ninject的DI如何让事情变得更容易。给出的示例标准并不复杂,不足以使编码和创建模块和绑定的麻烦变得有价值。

编辑#1:

在研究了 Sam Holder 提供的链接后,我正在尝试'组合根'方法。我的架构现在强制它使用的所有表单从带有构造函数语义的CompositedForm派生:

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

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

第二个构造函数是为了Forms Designer的好处,除非你提供一个空的构造函数,否则它是愚蠢的并且无法理解表单标记。现在,使用IKernel.Get<AForm>()创建的每个表单都应该(应该)注入一个组合根。

所以,因为我是一个学习缓慢的人 - 现在的问题是'这个作文根本应该去做什么'?

3 个答案:

答案 0 :(得分:5)

你不能将工厂创建子表单传递给表单构造函数,并且表单使用它来获取它们,然后ninject会在使用get创建表单时连接工厂依赖项吗?

我认为您应该使用DI容器配置应用程序根目录中的所有内容,之后不应该使用容器,但我真的没有真正使用DI容器,而不是NInject,所以我要继续我读过的......

This answer可能有所帮助

答案 1 :(得分:2)

注意:我对Ninject了解不多,但我在Spring.net上工作要复杂得多。背后的原则可能类似。

如果您要创建一个(注入)类型的多个对象(例如CustomerOrderItem),那么Sam Holder的答案非常好。

如果你只想连接你的mainform,我会认为你的mdi-frmMain构造函数获取它应该包含的每个子窗口的参数,并让Ninject创建并插入子窗口。这样就没有必要在“类程序”之外引用NInject “。这称为构造函数注入。

或者,您可以在表单中添加一个方法,向您添加页面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);
}

答案 2 :(得分:1)

感谢João AlmeidaKellabyte我发现了一种或多或少令人满意的方法:

  • 定义一个自定义属性,该属性公开您关心的任何业务规则;
  • 定义IInjectionHeuristic的实现,该实现可识别此属性;
  • 使用ViewModelLocator将模块加载到ninject内核中。