项目
版本

Autofac 将参数注册到组件

当你使用 注册组件 时,你可以为基于该组件的 服务解决方案 提供一组参数。如果你更愿意在解决服务时提供参数,也可以 这样做

可用的参数类型

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

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

NamedParameterTypedParameter 只能提供常量值。

ResolvedParameter 可以用来动态地从容器中获取值,例如通过按名称解析服务。

使用反射组件的参数

当你注册一个基于反射的组件时,组件类型的构造函数可能需要一个无法从容器中解析的参数。你可以在注册时使用参数提供这个值。

假设你有一个需要传递配置节名称的配置读取器:

public class ConfigReader : IConfigReader
{
    public ConfigReader(string configSectionName)
    {
        // 存储配置节名称
    }

    // ...根据节名称读取配置。
}

你可以使用 lambda 表达式组件来实现:

builder.Register(c => new ConfigReader("sectionName")).As<IConfigReader>();

或者为反射组件注册提供参数:

// 使用NAMED参数:
builder.RegisterType<ConfigReader>()
       .As<IConfigReader>()
       .WithParameter("configSectionName", "sectionName");

// 使用TYPED参数:
builder.RegisterType<ConfigReader>()
       .As<IConfigReader>()
       .WithParameter(TypedParameter.From("sectionName"));

// 使用RESOLVED参数:
builder.RegisterType<ConfigReader>()
       .As<IConfigReader>()
       .WithParameter(
         new ResolvedParameter(
           (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "configSectionName",
           (pi, ctx) => "sectionName"));

使用 lambda 表达式组件的参数

对于 lambda 表达式组件注册,你不是在注册时传递参数值,而是启用在服务解决时传递参数值的能力。( 更多关于带有参数的解决服务的信息

在组件注册表达式中,你可以利用传入的参数,使用泛型 lambda Register 方法:

builder.Register((MyConfig config) => new Worker(config));

如果你需要访问完整的参数列表,可以通过更改注册委托的签名来实现。不要将参数作为 lambda 的参数,而是接受一个 IComponentContext 和一个 IEnumerable<Parameter>

// 使用两个参数注册委托:
// c = 当前的 IComponentContext,用于动态解析依赖项
// p = 包含传入参数集的 IEnumerable<Parameter>
builder.Register((c, p) =>
                 new Worker(p.Named<MyConfig>("config")));

使用参数解析 时,你的 lambda 会使用传递的参数:

var customConfig = new MyConfig
{
    SomeValue = "../"
};

var worker = scope.Resolve<Worker>(new NamedParameter("config", customConfig));
在本文档中