You need to enable JavaScript to run this app. Windows Form用户控件使用Simple Injector属性注入的问题与解决方案
优惠活动
大模型
产品
解决方案
定价
更多

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获取用户控件实例,该做法属于反模式,同时也会导致窗体设计器无法正常工作。

解决方案

可通过静态服务工厂的方式解决该问题,实现步骤如下:

  1. 创建包含GetService方法的静态类
public static class ServiceFactory
{
    public static Container container;

    public static TService GetService<TService>() where TService: class
    {
        return container.GetInstance<TService>();
    }

}
  1. 在程序初始化阶段为静态类的容器赋值
private static Container Bootstrap()
{
    var container = new Container();

    ServiceFactory.container = container;

    ConfigureServices(container);

    AutoRegisterWindowsForms<Form>(container);
    AutoRegisterWindowsForms<UserControl>(container);

    container.Verify();

    return container;
}
  1. 在用户控件构造函数中获取依赖
private readonly IDatabaseService _databaseService;

public CustomUserControl()
{
    InitializeComponent();
    _databaseService = ServiceFactory.GetService<IDatabaseService>();
}

内容的提问来源于stack exchange,提问作者Minh Giang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 00:09:01