gpt4 book ai didi

c# - 在 Silverlight 和 MVVM 的组合根中保持 DI 容器的使用

转载 作者:可可西里 更新时间:2023-11-01 08:11:25 25 4
gpt4 key购买 nike

我不太清楚如何设计,所以我在 Silverlight + MVVM 应用程序的组合根中保留对 DI 容器的引用。

我有以下简单的使用场景:有一个主视图(可能是一个项目列表)和一个为单个项目打开编辑 View 的操作。因此主视图必须在用户执行操作(例如单击某个按钮)时创建并显示编辑 View 。

为此,我有以下代码:

public interface IView
{
IViewModel ViewModel {get; set;}
}

然后,对于我需要能够创建的每个 View ,我都有一个抽象工厂,就像这样

public interface ISomeViewFactory
{
IView CreateView();
}

此工厂随后被声明为“父” View 模型的依赖项,如下所示:

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 = ????
}
}

“????”部分是我的问题,因为 View 的 View 模型需要从 DI 容器中解析,因此它会注入(inject)其依赖项。我不知道如何在不依赖 DI 容器的情况下做到这一点,除了组合根之外。

一个可能的解决方案是依赖注入(inject)到工厂中的 View 模型,如下所示:

public class SomeViewFactory : ISomeViewFactory
{
public SomeViewFactory(ISomeViewModel viewModel)
{
// store it
}

public IView CreateView()
{
IView view = new SomeView();
view.ViewModel = viewModel;
}
}

虽然这可行,但它有一个问题,因为整个对象图是“静态”连接的(即“父” View 模型将获得 SomeViewFactory 的实例,它将获得 SomeViewModel 的实例,并且这些将存在只要“父” View 模型存在),注入(inject)的 View 模型实现是有状态的,如果用户打开 subview 两次,第二次 View 模型将是同一个实例并具有之前的状态。我想我可以使用“初始化”方法或类似方法来解决这个问题,但它闻起来不太对劲。

另一种解决方案可能是包装 DI 容器并让工厂依赖于包装器,但它仍然是一个“伪装”的 DI 容器:)

ps:我目前的解决方案是工厂知道 DI 容器,只有它们和组合根具有这种依赖性。

最佳答案

为了尽可能接近您的示例代码,您可以以 IViewPopulator 的形式引入另一个间接级别:

public interface IViewPopulator
{
void Populate(IView view);
}

您现在可以像这样实现您的 SomeViewFactory:

public class SomeViewFactory : ISomeViewFactory
{
private readonly IViewPopulator populator;

public SomeViewFactory(IViewPopulator populator)
{
if (populator == null)
{
throw new ArgumentNullException("populator");
}

this.populator = populator;
}

public IView CreateView()
{
IView view = new SomeView();
this.populator.Populate(view);
return view;
}
}

这将 View 的创建和 View 模型的填充分开,遵守 Single Responsibility Principle .一定程度上也是Service Aggregation的一个例子.

您现在可以将 IViewPopulator 实现为采用正常依赖项的具体类型:

public class SomeViewPopulator : IViewPopulator
{
private readonly IDependency dep;

public SomeViewPopulator(IDependency dep)
{
if (dep == null)
{
throw new ArgumentNullException("dep");
}

this.dep = dep;
}

public void Populate(IView view)
{
var vm = // Perhaps use this.dep to create an instance of IViewModel...
view.ViewModel = vm;
}
}

可能还有其他方法可以对 IView 和 IViewModel 之间的关系进行建模,但以上只是一种可能的解决方案。

关键是不断提取抽象,直到每个抽象都有明确定义的职责。这个练习实际上根本不是让代码与容器无关,而是最终要遵守 SOLID 原则。

关于c# - 在 Silverlight 和 MVVM 的组合根中保持 DI 容器的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2190676/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com