IoC / DI容器,工厂和运行时类型创建
最近我了解了DI框架Guice和Ninject,并希望在我的一些新项目中使用它们。
虽然我熟悉一般的依赖注入概念并知道如何使用这些框架来构建对象图,但我很难在动态应用程序行为中应用IoC。
考虑这个例子:
虽然很容易将主窗口的View连接到Presenter / ViewModel,然后将其绑定到域逻辑,但我不明白如何干净地(在IoC意义上)实现以下任务:
IGreenBoxView
, IRedImageView
< - JConcreteGreenBoxView
, JConcreteRedImageView
) JOptionPane
在运行时 我已经看到了一些使用抽象工厂的解决方案,但实际上并没有完全理解它们。 看起来,这样的解决方案将会导致一些(视图领域,演示者领域的......)内部类型暴露给构建根,并且与此相关的是整个世界。
所以 - 我该如何做对?
如果你可以重用控件,那么你可以在你使用它们的地方进行构造函数注入。 否则,你必须注入一个工厂:
public interface IControlFactory
{
IGreenBoxView CreateGreenBoxView();
IRedImageView CreateRedImageView();
}
并将其注入需要创建此控件的位置。
实现转到容器配置。 在那里你可以注入容器到实现。 有些容器提供自动实现这个工厂。 例如,在Ninject中:
Bind<IControlFactory>().ToFactory();
请参阅https://github.com/ninject/ninject.extensions.factory/wiki
对于那些希望使用Unity (而不是Ninject)来做类似事情的人,我创建了一个扩展,它允许您创建工厂,而不必声明接口:UnityMappingFactory @ GitHub
您只需在正常引导过程中注册类的地方添加映射......
//make sure to register the output...
container.RegisterType<IImageWidgetViewModel, ImageWidgetViewModel>();
container.RegisterType<ITextWidgetViewModel, TextWidgetViewModel>();
//define the mapping between different class hierarchies...
container.RegisterFactory<IWidget, IWidgetViewModel>()
.AddMap<IImageWidget, IImageWidgetViewModel>()
.AddMap<ITextWidget, ITextWidgetViewModel>();
然后,您只需在CI的构造函数中声明映射工厂接口并使用其Create()方法...
public ImageWidgetViewModel(IImageWidget widget, IAnotherDependency d) { }
public TextWidgetViewModel(ITextWidget widget) { }
public ContainerViewModel(object data, IFactory<IWidget, IWidgetViewModel> factory)
{
IList<IWidgetViewModel> children = new List<IWidgetViewModel>();
foreach (IWidget w in data.Widgets)
children.Add(factory.Create(w));
}
作为额外的好处,映射类的构造函数中的任何附加依赖项也将在对象创建期间得到解决。 (也作为这个Stackoverflow帖子的答案共享)
链接地址: http://www.djcxy.com/p/58089.html上一篇: IoC / DI containers, factories and runtime type creation