c# - 用户控件 Windows 窗体中的简单注入器属性注入
问题描述
我必须创建一个使用 Windows 窗体的小应用程序。我想使用 Simple Injector 作为 IoC 容器。
Simple Injector 的文档写道:
不能在用户控件中使用构造函数注入。用户控件需要有一个默认构造函数。相反,使用属性注入将依赖项传递给您的用户控件。
我已按照说明进行操作,我的程序如下所示:
internal static class Program
{
[STAThread]
private static void Main()
{
App.EnableVisualStyles();
App.SetCompatibleTextRenderingDefault(false);
App.Run(Bootstrap().GetInstance<FormMain>());
}
private static Container Bootstrap()
{
var container = new Container();
container.Options.PropertySelectionBehavior =
new ImportPropertySelectionBehavior();
ConfigureServices(container);
AutoRegisterWindowsForms<Form>(container);
AutoRegisterWindowsForms<UserControl>(container);
container.Verify();
return container;
}
private static void ConfigureServices(Container container)
{
container.RegisterSingleton<IFormOpener, FormOpener>();
container.RegisterSingleton<IUserService, UserService>();
container.RegisterSingleton<IDatabaseService, DatabaseService>();
}
private static void AutoRegisterWindowsForms<T>(Container container)
where T: ContainerControl
{
var types = container.GetTypesToRegister<T>(typeof(Program).Assembly);
foreach (var type in types)
{
var registration =
Lifestyle.Transient.CreateRegistration(type, container);
registration.SuppressDiagnosticWarning(
DiagnosticType.DisposableTransientComponent,
"Forms should be disposed by app code; not by the container.");
container.AddRegistration(type, registration);
}
}
我的问题是在使用拖放设计UI时,使用new
操作符自动生成用户控件,并且属性注入不起作用。我不想将容器直接注入到用户控件的GetInstance的表单中,因为它是一种反模式,表单设计也不起作用。有没有办法解决这个问题?谢谢大家
编辑 我以我的方式解决了这个问题。我创建了一个包含 GetService 方法的静态类,如下所示:
public static class ServiceFactory
{
public static Container container;
public static TService GetService<TService>() where TService: class
{
return container.GetInstance<TService>();
}
}
容器需要在程序初始化时被赋值:
private static Container Bootstrap()
{
var container = new Container();
ServiceFactory.container = container;
ConfigureServices(container);
AutoRegisterWindowsForms<Form>(container);
AutoRegisterWindowsForms<UserControl>(container);
container.Verify();
return container;
}
我将服务注入到用户控件中,如下所示:
private readonly IDatabaseService _databaseService;
public CustomUserControl()
{
InitializeComponent();
_databaseService = ServiceFactory.GetService<IDatabaseService>();
}
解决方案
我的问题是在使用拖放设计UI时,使用new操作符自动生成用户控件,并且属性注入不起作用。
这正是文档提到属性注入的原因。属性注入允许应用于外部创建的实例(因为用户控件是由 UI 框架创建的,而不是 DI 容器)。
然而,文档没有提到的是如何使用依赖项初始化创建的实例。Simple Injector 包含一个InitializeInstance
用于此的。以下代码允许初始化使用显式属性注入的用户控件:
private static Container container;
public static void InitializeControl(UserControl control)
{
var producer = container.GetRegistration(control.GetType(), true);
producer.Registration.InitializeInstance(control);
}
不幸的是,这远非完美,因为它需要表单和用户控件依赖于 DI 容器。为了防止这种情况,您可以通过方法注入将依赖项从包含表单传递给用户控件,但这样做的缺点是您很容易必须传递许多依赖项,从而导致使用表单的构造函数爆炸。
或者,与文档所述相反,可以从 DI 容器解析用户控件并规避使用Ron在此处所述的设计器。但是,这可能会产生其自身的后果,而我对此没有经验。
推荐阅读
- javascript - React Redux - TypeError:无法读取未定义的属性“道具”
- mysql - Magento 2 - 从数据库更改图像角色
- django - 具有多个值的 Django 模型字段
- c++ - fstream 无法打开文件
- django - VSCode 用换行符打破 Django 模板标签
- java - 使用 Angular 客户端访问 REST 端点时出现 CORS 问题 - 允许跨源
- javascript - How to download file from deployed server?
- terraform - Move/combine state between Terraform modules?
- jquery - Problem with AOS.js not working when Slick.js is on the same page
- python - how to assign returned values into a variable using for loop