初始配置后在IoC容器中注册

时间:2010-12-17 11:23:46

标签: dependency-injection singleton inversion-of-control containers

我有一个场景,我想在容器中注册一个组件的单个实例,但遗憾的是它无法在应用程序启动时创建。 该组件只能被实例化传递一些对象,其仅可位在后面应用程序生命周期(它们不是其他的IoC注册的服务,但是) [参见下面的注释]

  • 在初始配置(在应用启动时运行)中注册IoC容器中的组件是一种不好的做法吗?
  • 如何在不直接引用容器的情况下完成它?我应该抽象注册服务吗?
  • 有更好的方法来支持这种情况吗?

关于实际情况的说明
我想要放入容器的组件使用UI控件的特定实例(它基本上是一个适配器)进行初始化,因此我必须手动创建组件实例并将其注册到容器中。
我会在应用程序启动时完成此操作,但遗憾的是我还没有可用的UI控件实例(也不能自己创建)。
即使在以后的时间,我也无法在不知道具体类的情况下从其他组件的表面到达UI控件实例 出于这个原因,我认为我可以将适配器注册的责任放入拥有UI控件的类中。

我最初的情景:

public interface IDockManager { ... }
public class AcmeDockManagerAdapter : IDockManager  {
    public AcmeDockManager(DockControl control) { ... }
    ...
}

public class ShellViewModel { ... }
public class ShellView : Window { 
    internal DockControl theDockControl;
} 

public class AnotherViewModel {
     AnotherViewModel(IDockManager dockManager) { ... }
}

我不满意的解决方案:

public class ShellView : Window { 
    internal DockControl theDockControl;
    public ShellView () {
        InitializeComponents();
        var dockManager = new AcmeDockManagerAdapter(theDockControl);
        //registration in the container
    }
} 

2 个答案:

答案 0 :(得分:1)

您可以注册“懒惰包装”。这样的包装器实现了相同的接口,可以立即实例化,但会在内部推迟创建工作的实际组件。看看ploeh的LazyOrderShipperLazyOrderShipper2

示例

编辑:如果我理解正确,您只是尝试将视图连接到视图模型,MVVM风格。我更喜欢让容器处理viewmodel构造,而是自己做视图构造和viewmodel布线。我的启动代码看起来像这样:

var mainViewModel = container.Get<MainViewModel>();
var mainView = new MainView(mainViewModel);
Application.Run(mainView);

MainView构造函数中,我会处理需要自己的viewmodel的子控件:

   public MainView(MainViewModel viewModel)
   {
       // link "subviews" to "subviewmodels"
       this.SomeChildControl.ViewModel = viewModel.SomeChildViewModel;

       // normal MVVM property wiring
       viewModel.TitleChanged += delegate { this.Text = viewModel.Title; };
       ...
   }

如果您严格遵循MVVM方法,那么您不必在容器中注册任何视图。 “需要与视图对话”的任何内容都需要与底层视图模型进行对话。 (当您希望在选项卡式界面或停靠窗口GUI中允许可插入视图时,事情变得更有趣,但这是另一个故事。)

答案 1 :(得分:1)

我理解问题的解决方案相对简单 - 从外部提供theDockControl。我知道这会搞乱自动生成的WinForms / WPF /无论你使用什么废话,但我担心这里没有漂亮的解决方案。