Windows Form用户控件使用Simple Injector属性注入的问题与解决方案
Windows Forms结合Simple Injector实现用户控件依赖注入的问题及解决方案
问题背景
我需要开发一款基于Windows Forms的小型应用,计划使用Simple Injector作为IoC容器。
Simple Injector官方文档说明:
用户控件(User Control)必须提供默认构造函数,无法使用构造函数注入,需改用属性注入(Property Injection)的方式为用户控件传递依赖。
按照文档指引完成的初始程序配置如下:
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>(); }
内容的提问来源于stack exchange,提问作者Minh Giang
相关产品推荐
相关产品推荐

