Autofac 参数解析
当需要 解析服务 时,你可能会发现需要将参数传递给解析。如果你知道注册时的值,可以使用 在注册时提供这些参数 。
Resolve()
方法接受与注册时相同的参数类型,使用可变长度参数列表。另外,委托工厂 和 Func<T>
暗示关系类型也允许在解析期间传递参数。
可用的参数类型
Autofac 提供了几种不同的参数匹配策略:
NamedParameter
:通过名称匹配目标参数TypedParameter
:按类型匹配目标参数(要求精确类型匹配)ResolvedParameter
:灵活参数匹配
NamedParameter
和 TypedParameter
只能提供常量值。
ResolvedParameter
可以用于动态从容器中获取值的方式提供值,例如根据名称解析服务。
使用反射组件时的参数
当你解析基于反射的组件时,类型的构造函数可能需要一个依赖于运行时值的参数,这在注册时是不可用的。可以在 Resolve()
调用中使用参数来提供该值。
假设你有一个配置读取器,它需要传入配置节的名称:
public class ConfigReader : IConfigReader
{
public ConfigReader(string configSectionName)
{
// 存储配置节名称
}
// ...根据节名称读取配置。
}
你可以这样向 Resolve()
调用传递参数:
var reader = scope.Resolve<ConfigReader>(new NamedParameter("configSectionName", "sectionName"));
与注册时的参数类似 ,如果 ConfigReader
组件是 通过反射 ,那么 NamedParameter
将映射到相应的命名构造函数参数。
如果有多个参数,只需通过 Resolve()
方法一起传递它们:
var service = scope.Resolve<AnotherService>(
new NamedParameter("id", "service-identifier"),
new TypedParameter(typeof(Guid), Guid.NewGuid()),
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(ILog) && pi.Name == "logger",
(pi, ctx) => LogManager.GetLogger("service")));
使用 lambda 表达式组件时的参数
对于 lambda 表达式组件注册,你需要在 lambda 表达式内部处理参数,以便在 Resolve()
调用中传递它们时,可以利用这些参数。
在组件注册表达式中,可以通过更改注册委托的签名来利用传入的参数。除了接收一个 IComponentContext
参数外,还需要接收一个 IComponentContext
和一个 IEnumerable<Parameter>
:
// 在注册委托中使用 2 个参数:
// c = 当前的 IComponentContext 来动态解析依赖项
// p = 一个 IEnumerable<Parameter>,其中包含传入的参数集
builder.Register((c, p) =>
new ConfigReader(p.Named<string>("configSectionName")))
.As<IConfigReader>();
现在当你解析 IConfigReader
时,你的 lambda 会使用传递的参数:
var reader = scope.Resolve<IConfigReader>(new NamedParameter("configSectionName", "sectionName"));
不显式调用 Resolve 传递参数
Autofac 支持两种功能,可以自动生成服务 “工厂” ,这些工厂接受强类型参数列表,在解析时使用这些参数。这是一种稍微更干净的方式来创建需要参数的组件实例。
关于使用这些方法根据参数选择实现的示例,请参阅 注册页面上的示例。