IoC / DI容器、工厂和运行时类型创建

7

我最近了解了DI框架Guice和Ninject,并希望在一些新项目中使用它们。

虽然我熟悉通用的依赖注入概念,也知道如何使用这些框架构建对象图,但是当涉及到动态应用程序行为时,我很难应用IoC。

考虑以下示例:

  • 应用程序启动时,将显示主窗口。
  • 当用户单击主面板时,会打开上下文菜单。
  • 根据用户的选择,在鼠标位置处创建并显示新的用户控件。
  • 如果用户最终决定关闭应用程序,则会显示确认框,并在确认后关闭主窗口。

虽然很容易将主窗口的视图连接到Presenter / ViewModel,然后将其绑定到域逻辑,但我不明白如何以干净(从IoC的角度)的方式实现以下任务:

  • 动态实例化具体的UI控件(例如IGreenBoxViewIRedImageView <-- JConcreteGreenBoxViewJConcreteRedImageView),而不使用任何服务定位器模式(例如从IoC再次请求)
    • 根据此创建新的模型、Presenter和视图实例
  • 类似地,在运行时实例化一个新的具体对话框,例如JOptionPane

我看到了一些使用抽象工厂的解决方案,但老实说我没有完全理解它们。这种解决方案似乎会导致将某些(视图域的、Presenter域的等)内部类型暴露给构造根,并由此暴露给整个世界。

那么,我该怎么做才能做到正确呢?


1
有没有一种模式来初始化通过 DI 容器创建的对象? - Mark Seemann
现在变得更清晰了。非常感谢! - sunside
2个回答

4
如果您可以重用控件,则可以在使用它们的地方进行构造函数注入。否则,您需要注入一个工厂:
public interface IControlFactory 
{
     IGreenBoxView CreateGreenBoxView();
     IRedImageView CreateRedImageView();
}

并将其注入到您需要创建此控件的位置。

实现部分写在容器配置中。在那里,您可以将容器注入到实现中。有些容器会自动提供实现该工厂的功能。例如,在Ninject中:

Bind<IControlFactory>().ToFactory();

请查看https://github.com/ninject/ninject.extensions.factory/wiki

0

对于那些想要使用 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 帖子中找到答案)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接