项目
版本

Autofac 参数解析

当需要 解析服务 时,你可能会发现需要将参数传递给解析。如果你知道注册时的值,可以使用 在注册时提供这些参数

Resolve() 方法接受与注册时相同的参数类型,使用可变长度参数列表。另外,委托工厂Func<T> 暗示关系类型也允许在解析期间传递参数。

可用的参数类型

Autofac 提供了几种不同的参数匹配策略:

  • NamedParameter:通过名称匹配目标参数
  • TypedParameter:按类型匹配目标参数(要求精确类型匹配)
  • ResolvedParameter:灵活参数匹配

NamedParameterTypedParameter 只能提供常量值。

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 支持两种功能,可以自动生成服务 “工厂” ,这些工厂接受强类型参数列表,在解析时使用这些参数。这是一种稍微更干净的方式来创建需要参数的组件实例。

关于使用这些方法根据参数选择实现的示例,请参阅 注册页面上的示例

在本文档中