【发布时间】:2011-01-12 12:54:15
【问题描述】:
我不太清楚如何设计,所以我在 Silverlight + MVVM 应用程序的组合根中保留了对 DI 容器的引用。
我有以下简单的使用场景:有一个主视图(可能是项目列表)和一个用于打开单个项目的编辑视图的操作。因此,当用户执行操作(例如单击某个按钮)时,主视图必须创建并显示编辑视图。
为此,我有以下代码:
public interface IView
{
IViewModel ViewModel {get; set;}
}
然后,对于我需要能够创建的每个视图,我都有一个抽象工厂,就像这样
public interface ISomeViewFactory
{
IView CreateView();
}
然后这个工厂被声明为“父”视图模型的依赖,像这样:
public class SomeParentViewModel
{
public SomeParentViewModel(ISomeViewFactory viewFactory)
{
// store it
}
private void OnSomeUserAction()
{
IView view = viewFactory.CreateView();
dialogService.ShowDialog(view);
}
}
所以在此之前一切都很好,看不到 DI 容器 :)。现在是 ISomeViewFactory 的实现:
public class SomeViewFactory : ISomeViewFactory
{
public IView CreateView()
{
IView view = new SomeView();
view.ViewModel = ????
}
}
“???”部分是我的问题,因为视图的视图模型需要从 DI 容器中解析,以便注入其依赖项。我不知道的是如何在不依赖组合根以外的任何地方的 DI 容器的情况下做到这一点。
一种可能的解决方案是依赖注入到工厂的视图模型,如下所示:
public class SomeViewFactory : ISomeViewFactory
{
public SomeViewFactory(ISomeViewModel viewModel)
{
// store it
}
public IView CreateView()
{
IView view = new SomeView();
view.ViewModel = viewModel;
}
}
虽然这可行,但它有一个问题,因为整个对象图是“静态”连接的(即“父”视图模型将获得 SomeViewFactory 的实例,它将获得 SomeViewModel 的实例,并且这些将存在只要“父”视图模型存在),注入的视图模型实现是有状态的,如果用户打开子视图两次,第二次视图模型将是同一个实例并具有之前的状态。我想我可以使用“初始化”方法或类似的方法来解决这个问题,但它闻起来不太对。
另一种解决方案可能是包装 DI 容器并让工厂依赖于包装器,但它仍然是一个“伪装”的 DI 容器 :)
ps:我目前的解决方案是工厂知道 DI 容器,只有它们和组合根具有这种依赖关系。
【问题讨论】:
标签: c# silverlight mvvm dependency-injection inversion-of-control