Simple Injector显式特性属性注入时 构造函数内依赖属性为null问题
核心原因
Simple Injector 的属性注入有固定的执行顺序:所有属性赋值操作,都是在目标对象的构造函数完全跑完之后才执行的。
完整解析流程的时序是:
- 容器先解析构造函数需要的参数,调用目标类型的构造函数,把原始实例创建出来
- 再按照
Options.PropertySelectionBehavior的规则,筛选出需要注入的属性 - 最后把从容器解析到的依赖,赋值到这些属性上
你现在在System类的构造函数里直接读Logger属性,此时流程才刚走到第一步,容器根本还没开始做属性赋值。不管你怎么调整注册配置、把Import换成自定义特性、把日志服务改成单例注册,这个时机下Logger一定是null。这也能解释为什么你换成构造函数注入就能正常工作——构造函数的参数是容器在调用构造函数之前就解析好的,和属性注入的时序完全不在一个阶段。
现有代码的校验
你写的自定义PropertySelectionBehavior实现本身没有逻辑问题:
- 只要正确引入了
ImportAttribute所在的命名空间、给属性留了公共setter,容器是可以正确识别到需要注入的目标属性的 - 你删掉所有ReactiveUI相关代码后问题依然复现的测试结果也证明,这个问题和ReactiveUI的Splat适配逻辑完全无关
可行的修复方向
- 遵守DI通用的最佳实践,构造函数里只做依赖的临时存储,不要跑任何业务逻辑(包括打日志)。如果需要在对象初始化阶段打日志,实现Simple Injector提供的
IInitializable接口即可,接口的Initialize方法会在所有属性注入完成后才被调用,不会出现属性为null的问题。 - 日志组件这类核心长期依赖,优先用构造函数注入的方式引入,这也是Simple Injector官方更推荐的依赖获取方式,能从根源上避免这类时序导致的偶发问题。
- 后续要把日志组件封装成装饰器的需求,直接用Simple Injector内置的装饰器注册逻辑就能实现,完全不需要依赖基于特性的属性注入流程。
内容的提问来源于stack exchange,提问作者Gusto
相关产品推荐
相关产品推荐

