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

简单注入器显式属性注入 - 构造函数内的属性为空

如何解决简单注入器显式属性注入 - 构造函数内的属性为空

Simple Injector 的新手,试图让一些部件为原型工作。我正在创建一个使用 Simple Injector 和 ReactiveUI 的 WPF 应用程序,但似乎无法通过属性来触发显式属性注入。我正在处理的具体示例只是测试记录器的注入。计划是将其滚动到装饰器中,但我遇到了对以前的项目/DI 库进行属性注入的需求。只是想验证我是否能够使用它。

自举代码片段:

private Container RegisterDependencies(Container container = null)
{
    container ??= new Container();

    // Container initialization that must precede dependency registration
    // occurs here

    // Enable property injection via the [Import] attribute
    container.Options.PropertySelectionBehavior =
        new ImportPropertySelectionBehavior();

    SimpleInjectorInitializer initializer = new SimpleInjectorInitializer();
    Locator.SetLocator(initializer);

    Locator.CurrentMutable.InitializeSplat();
    Locator.CurrentMutable.InitializeReactiveUI();

    container.UseSimpleInjectorDependencyResolver(initializer);

    container.RegisterConditional(
        typeof(ILogger),c => typeof(NLogLogger<>)
            .MakeGenericType(c.Consumer.ImplementationType),Lifestyle.Singleton,c => true);
        
    container.Register<MainWindow>();

    container.Register<ISystem,System>(Lifestyle.Singleton);
            
    container.Verify();
    return container;
}

System 调用的静态 RunApplication 中的 DI 容器请求 Main 的实例:

var system = container.GetInstance<ISystem>();

这里是系统中的属性注入:

public class System : ISystem
{
    [Import] public ILogger Logger { get; set; }

    public System()
    {
        // Logger is null here. NullReferenceException is thrown
        Logger.LogInfo("Creating System");
    }
}

此时在构造函数中,Logger 属性为 null,尝试记录失败并出现异常。我应该提到 ILogger 是我自己对 NLog 的抽象。如果我改为执行构造函数注入:

public System(ILogger logger)

Simple Injector 注意到这一点并很好地解决了依赖关系。我尝试将 Import 属性更改为不同的自定义 Dependency 属性,但没有任何更改。还尝试将记录器实例化为单例,行为相同。

非常感谢您的任何想法,我在搜索论坛、SimpleInjector/ReactiveUI 文档和 Steven 的 DI 书上都快干掉了。

编辑 - 这里也是 PropertySelectionBehavior 代码

public class PropertySelectionBehavior<T> : IPropertySelectionBehavior
    where T : Attribute
{
    public bool SelectProperty(
        Type implementationType,PropertyInfo propertyInfo) =>
        propertyInfo.GetCustomAttributes(typeof(T)).Any();
}

public class ImportPropertySelectionBehavior : 
    PropertySelectionBehavior<ImportAttribute> { }

第二次编辑 - 我可以删除与 ReactiveUI 相关的所有初始化并仍然重现相同的行为。新示例如下:

private Container RegisterDependencies(Container container = null)
{
    container ??= new Container();

    container.Options.PropertySelectionBehavior =
        new ImportPropertySelectionBehavior();

    // Logger registration
    container.RegisterConditional(
        typeof(ILogger),c => true);

    // UI registration
    container.Register<MainWindow>();
    //container.Register<MainWindowviewmodel>();

    container.Register<ISystem,System>(Lifestyle.Singleton);

    container.Verify();
    return container;
}

解决方法

更新,显式属性注入工作正常。它发生在施工后。我想这有设计原因,尽管不知何故,这与我的心理模型相反,即按需/首次使用时执行属性注入。

计划进行更多试验,以了解对解决属性依赖关系的时间进行哪些控制。如果任何更有经验的人对此有任何建议或可以向我指出其他文档,我会欢迎。装饰器听起来像是确保记录器按预期可用并允许独立延迟加载被装饰者关注点的更优雅的方式。这里有一些讨论:

SimpleInjector - "Lazy" Instantiate a singleton that has dependencies on first use

,

您正在使用 inside Logger 的构造函数中的 System 属性。但是,属性仅在构造函数完成后 初始化。如果您从等式中删除 Simple Injector,并回退到普通的旧 C#,您会看到相同的结果。例如:

var system = new System() // <-- constructor call
{
    Logger = new NLogLogger<System>() // Logger_set is called after the ctor
};

如果您运行此代码,您将看到 NullReferenceException 的构造函数抛出的相同 System

这意味着您不应使用构造函数内部的任何属性。更广泛地说,从 DI 的角度来看,您不应像 Mark Seemann here 所描述的那样在构造函数内(或在构造过程中)使用任何服务。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 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”。这是什么意思?