如何解决用户控件 Windows 窗体中的简单 Injector 属性注入
我必须创建一个使用 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
。以下代码允许初始化使用 explicit property injection 的用户控件:
private static Container container;
public static void InitializeControl(UserControl control)
{
var producer = container.GetRegistration(control.GetType(),true);
producer.Registration.InitializeInstance(control);
}
不幸的是,这远非完美,因为它需要表单和用户控件依赖于 DI 容器。为了防止这种情况,您可以通过 Method Injection 将依赖项从包含表单传递给用户控件,但这样做的缺点是您很容易必须传递许多依赖项,从而导致消费表单的构造函数爆炸。
或者,与文档所述相反,可以从 DI 容器解析用户控件并规避使用设计器,如 Ron here 所述。然而,这可能有它自己的 consequences,我没有这方面的经验。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。