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

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

虽然我熟悉一般的依赖注入概念并知道如何使用这些框架来构建对象图,但我很难在动态应用程序行为中应用IoC。

考虑这个例子:

  • 当应用程序启动时,主窗口将显示。
  • 当用户点击主面板时,会打开一个上下文菜单。
  • 根据用户的选择,将创建一个新的用户控件并显示在鼠标位置。
  • 如果用户最终决定关闭应用程序,将会显示一个确认框,并且在确认后 - 主窗口将被关闭。
  • 虽然很容易将主窗口的View连接到Presenter / ViewModel,然后将其绑定到域逻辑,但我不明白如何干净地(在IoC意义上)实现以下任务:

  • 不使用任何类型的服务定位器模式(例如,再次请求IoC) 动态实例化具体的UI控件(例如IGreenBoxViewIRedImageView < - JConcreteGreenBoxViewJConcreteRedImageView
  • 根据这一点,创建一个新模型,演示者和视图实例
  • 相似,实例化一个新的具体对话框,例如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

    下一篇: Using OAuth with OData