我在.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>()
创建的每个表单都应该(应该)注入一个组合根。
所以,因为我是一个学习缓慢的人 - 现在的问题是'这个作文根本应该去做什么'?
答案 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 Almeida和Kellabyte我发现了一种或多或少令人满意的方法:
IInjectionHeuristic
的实现,该实现可识别此属性; ViewModelLocator
将模块加载到ninject内核中。