1

我有一个场景,我想在容器中注册一个组件的单个实例,但不幸的是它不能在应用程序启动时创建。 该组件只能被实例化,传递一些对象,这些对象仅在应用程序生命周期中稍后提供(但它们不是其他IoC注册服务,但是)[请参见下面的注释]在初始配置后在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) { ... } 
} 

我unconfortable与解决方案:

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

回答

1

你可以注册一个 “懒包装” 来代替。这样的包装器实现相同的接口并可以立即实例化,但会在内部推迟创建实际工作的实际组件。看看ploeh的例子LazyOrderShipperLazyOrderShipper2

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

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

而且MainView构造函数中我会照顾好它需要自己的视图模型子控件:

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中允许插入视图时,事情会变得更有趣,但那是另一回事。)

+0

这是一个非常优雅的解决方案。然而,我的问题与组件实例的成本无关,而是与某些构造器参数的可用性有关。推迟实际的实例化要求至少懒惰的包装器知道如何检索所需的参数,当它最终到达创建实例时。 我应该更详细地解释我的情况,也许(我将要这样做)。谢谢你的帮助。 – 2010-12-18 09:29:01

+0

对不起,但问题与视图和虚拟机之间的连线没有关系(这已经到位)。我只是添加了实际的类,希望能够澄清上下文。 我的意图是抽象对接部分并将其接口从ShellVM中分离出来,确切目的是允许动态添加。 我希望将对接服务放在容器中以简化依赖注入,但我可以肯定从ShellVM(它已经在容器中注册为单例)访问它。 – 2010-12-18 19:27:19

1

解决方案我明白这个问题,相对简单 - 从外面提供theDockControl。我知道这是与自动生成的WinForms/WPF /无论你使用废话混乱,但我恐怕没有漂亮的解决方案在这里。

+0

我想你有点不安。从设计的角度来看,从外部向适配器和窗口提供相同的控件实例是最好的选择 - 而且非常简单!由于其他原因可能会很尴尬,但这是另一个问题。 我想延期登记是无可争议的,虽然... 非常感谢您的帮助。 – 2010-12-19 10:03:58

+0

不用担心。下次你会得到徽章:) – 2010-12-19 23:59:03