微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

用户控件 Windows 窗体中的简单 Injector 属性注入

如何解决用户控件 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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?