最佳实践与推荐
你总是可以在 StackOverflow 上使用 autofac
标签或在 讨论组 中寻求 Autofac 的使用指导,但这些快速提示能帮助你开始。
总是从嵌套生命周期中解析依赖项
Autofac 设计用于为你 跟踪和释放资源 。为了确保这一点,确保长运行的应用程序被划分为工作单元(请求或事务),并且服务通过工作单元级别的生命周期作用域进行解析。ASP.NET 中的 请求级生命周期作用域支持 就是一个例子。
通过模块结构化配置
Autofac 模块 为容器配置提供了结构,并允许在部署时注入设置。与其单独使用 XML 配置 ,不如考虑使用模块以获得更灵活的方法。模块始终可以与 XML 配置结合使用,以获得两全其美的体验。
在委托注册中使用 As()
Autofac 根据你用来注册组件的表达式推断实现类型:
builder.Register(c => new Component()).As<IComponent>();
...使得 Component
类型成为组件的 LimitType
。以下其他类型转换机制等效,但不提供正确的 LimitType
:
// 可行,但避免这样做
builder.Register(c => (IComponent)new Component());
// 可行,但避免这样做
builder.Register<IComponent>(c => new Component());
使用构造注入
使用构造注入为必需依赖项和属性注入可选依赖项的概念相当知名。然而,另一种方法是使用 "空对象模式" 或 "特殊情况模式" ,为可选服务提供默认的、无操作的实现。这防止了在组件实现中的特殊案例代码(例如 if (Logger != null) Logger.Log("message");
)的可能性。
使用关系类型,而不是服务定位器
让组件访问容器,将其存储在公共静态属性中,或将像 Resolve()
这样的函数添加到全局"IoC"类上,会违背使用依赖注入的目的。此类设计与 服务定位器模式 有更多共同点。
如果组件对容器(或生命周期作用域)有依赖,看看它们是如何使用容器获取服务的,然后将这些服务添加到组件(依赖注入)构造参数中。
对于需要实例化其他组件或以更高级方式与容器交互的组件,请使用 关系类型 。
从最不具体到最具体的顺序注册组件
Autofac 默认情况下会覆盖组件注册。这意味着应用程序可以注册所有默认组件,然后读取一个关联的配置文件来覆盖任何已针对部署环境自定义的组件。
使用性能检查器
在进行任何性能优化或假设潜在内存泄漏之前,始终运行性能检查器,如 SlimTune ,dotTrace 或 ANTS ,查看时间真正花费在哪里。可能并非你想象的那样。
一次注册,多次解析
如果可以避免的话,不要在工作单元期间注册组件;注册组件的成本高于解析一个组件。使用嵌套生命周期作用域和适当的 实例作用域 来保持每个工作单元实例的独立性。
使用 lambda 注册频繁使用的组件
如果你确实需要从 Autofac 中挤出额外的性能,你的最佳选择是找出创建最多的组件,并使用表达式而不是类型进行注册,例如:
builder.RegisterType<Component>();
变成:
builder.Register(c => new Component());
这可以将 Resolve()
调用的速度提高高达 10 倍,但只对出现在许多对象图中的组件有意义。有关 lambda 组件的更多内容,请参阅 注册文档 。
考虑容器为不可变的
从 Autofac 5.x 开始,容器是不可变的。在构建后更新容器可能存在一些潜在风险。例如:
- 已自动启动的组件可能已经运行并使用了你在更新过程中覆盖的注册。这些自动启动的组件不会重新运行。
- 已经解析的服务可能基于添加的内容引用错误的依赖项。
- 已经解析的可丢弃组件可能已经被解决,并且会一直存在,直到拥有其生命周期作用域被释放——即使新的注册暗示应该不使用可丢弃组件。
- 注册订阅生命周期事件的组件可能在更新后订阅了错误的事件——不是所有的事件在更新过程中都会重新初始化。
为了防止这些风险成为问题,不再可以选择在构造后更新容器。
相反,考虑在子生命周期作用域中注册更新或更改。 有关这方面的示例,请 参阅生命周期作用域文档 。
优化或避免诊断
System.Diagnostics.DiagnosticSource
的诊断集成性能相当不错,但附加的追踪器可能会影响整体性能。例如,任何追踪器(如 DefaultDiagnosticTracer
)都会跟踪完整的解析操作链,这会分配内存并使用资源来保留操作数据,直到完整解析操作完成。
如果没有诊断监听器,整体性能会更好,但如果有的话,考虑使用非常快速且低分配的诊断监听器。例如,当操作发生时,不需要额外的内存或跟踪就可以记录一条消息。这可能比在完成前构建健壮的跟踪所需的开销更低。