我目前正在开发一个WinForms系统(我知道),在创建表单时有很多构造函数注入
,但是如果这些表单/视图需要打开另一个表单,我发现DI容器也已被注入,以便我们可以在运行时定位所需视图接口的实现。例如:
public partial class MyView : Form, IMyView
{
private readonly IDIContainer _container;
public MyView(IDIContainer container)
{
InitializeComponent();
_container = container;
}
public OpenDialogClick(object sender, EventArgs e)
{
var dialog = container.Resolve<IDialogView>();
dialog.ShowDialog(this);
}
}
我知道这基本上是将容器用作服务定位器。我一再被告知这被认为是反模式,因此我想避免使用它。
我可能可以像这样在构造函数中注入视图:
public partial class MyView : Form, IMyView
{
private readonly IDialogView _dialog;
public MyView(IDialogView dialog)
{
InitializeComponent();
_dialog = dialog;
}
public OpenDialogClick(object sender, EventArgs e)
{
dialog.ShowDialog(this);
}
}
但是,如果对话框视图实例化成本很高怎么办?
有人建议我们创建某种表单工厂,该工厂内部使用DI容器,但对我来说,这似乎就像是在另一个服务定位器周围创建一个包装器。
我知道,在某个时候,必须要有“某个东西”知道如何创建IDialogView,因此我认为它要么在组合根创建时被解析(如果有许多表单并且某些或所有表单的创建成本高,则可能不理想),要么组合根本身有一种方式来解决依赖关系。这种情况下,组合根必须具有类似于服务定位器的依赖关系?但是子表单如何创建这样的对话框呢?它们会通过事件向上调用组合体以打开这样的对话框吗?
我经常遇到的一个特殊问题是,容器几乎无法轻松地进行模拟。这正是使我考虑表单工厂想法的一部分,即使它只是一个容器的包装器。这是一个明智的理由吗?
我自己琢磨出了一个难题吗?还有没有简单的方法解决这个问题?还是我要剪断这个难题,找到适合我的东西呢?
MyView
的实例,他仍然需要容器来解决依赖关系。相反,工厂应该是一个具体的类,具有可插拔的提供者。MyView
应该直接使用工厂,无需注入它。工厂提供者在组合根中设置。 - Wiktor ZychlaIDialogFactory
已经注册到了SingleFactory
? - Wiktor Zychla