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

Dependency injection 初始配置后在IoC容器中注册,dependency-injection,singleton,inversion-of-control,containers,Dependency Injection,Singleton,Inversion Of Control,Containers,我有一个场景,我想在容器中注册组件的单个实例,但不幸的是,它无法在应用程序启动时创建。 该组件只能通过一些对象进行实例化,这些对象只在应用程序生命周期的稍后一段时间才可用(但它们不是其他IoC注册的服务)[请参见下面的注释] 在初始配置(在应用程序启动中运行)之后在IoC容器中注册组件是否是一种错误做法 如何在不直接引用容器的情况下完成它?我应该申请注册服务吗 有更好的方法来支持该场景吗 关于实际场景的注释 我想放在容器中的组件是用UI控件的特定实例初始化的(它基本上是一个适配器),因此我

我有一个场景,我想在容器中注册组件的单个实例,但不幸的是,它无法在应用程序启动时创建。 该组件只能通过一些对象进行实例化,这些对象只在应用程序生命周期的稍后一段时间才可用(但它们不是其他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
    }
} 
您可以注册一个“惰性包装器”。这样的包装器实现了相同的接口,可以立即实例化,但会在内部推迟创建实际的组件。请看ploeh的or示例

编辑:如果我理解正确,您只是试图将视图连接到视图模型,MVVM样式。我更喜欢让容器处理viewmodel构造,但我自己负责视图构造和viewmodel连接。我的启动代码如下所示:

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

如果严格遵循MVVM方法,则不必向容器注册任何视图。任何“需要与视图对话”的内容实际上都需要与底层viewmodel对话。(当您想在选项卡式界面或停靠窗口GUI中允许可插拔视图时,事情会变得更有趣,但这是另一回事。)

我理解这个问题的方法是相对简单的-从外部提供
锁定控件。我知道这会弄乱自动生成的WinForms/WPF/不管你在用什么废话,但恐怕这里没有漂亮的解决方案。

这是一个非常优雅的解决方案。然而,我的问题与组件实例化的成本无关,而是与一些构造函数参数的可用性有关。推迟实际的实例化需要至少惰性包装器知道在创建实例的最后时刻如何检索所需的参数。我应该更详细地解释我的场景,也许(我会这么做)。感谢您的帮助。很抱歉,这个问题与视图和虚拟机之间的连接无关(已经就绪)。我只是添加了实际涉及的类,希望澄清上下文。我的意愿是抽象对接部件,并将其接口与ShellVM分离,以便实现动态添加。我本想将对接服务放在容器中以简化依赖注入,但我肯定可以从ShellVM(容器中已注册为单例)访问它。我想你明白我的不安之处。从设计的角度来看,从外部向适配器和窗口提供相同的控件实例是一个好办法——而且非常简单!;这可能因为其他原因而尴尬,但这是另一个问题。我想推迟注册是无可争议的,不过。。。非常感谢你的帮助,不用担心。下次您将获得徽章:)
   public MainView(MainViewModel viewModel)
   {
       // link "subviews" to "subviewmodels"
       this.SomeChildControl.ViewModel = viewModel.SomeChildViewModel;

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