.NET手记-Autofac进阶(传递注册参数 Passing Parameters to Register)

Changwei | 1/12/2016 11:15:00 AM


当你注册组件时,可以为组件服务传入一系列参数,用于服务解析时使用。

 

可使用的参数类型 Available Parameter Types

 

Autofac提供了集中参数匹配类别:

  • NamedParameter - 直接通过名称匹配目标参数
  • TypedParameter - 通过类型来匹配目标参数
  • ResolvedParameter - 灵活的参数匹配

NamedParameter 和 TypedParameter只支持常量。

ResolvedParameter 能够使用从容器中动态解析的值作为参数, 例如通过名字解析出的服务。

 

反射组件的参数 Parameters with Reflection Components

 

当你注册基于反射的组件时,类型构造函数可能要求一些无法从容器中解析的参数。你可以通过直接提供此参数来完成组件注册。

假设你有一个配置阅读器(configuration reader),同时需要为它传入配置块命名(configuration section name):

 

public class ConfigReader : IConfigReader
{
  public ConfigReader(string configSectionName)
  {
    // Store config section name
  }

  // ...read configuration based on the section name.
}

 

你可能会使用Lambda表达式来实现:

 

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

 

或者为反射组件注册时传入参数:

 

// Using a NAMED parameter:
builder.RegisterType<ConfigReader>()
       .As<IConfigReader>()
       .WithParameter("configSectionName", "sectionName");

// Using a TYPED parameter:
builder.RegisterType<ConfigReader>()
       .As<IConfigReader>()
       .WithParameter(new TypedParameter(typeof(string), "sectionName"));

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

 

Lambda表达式组件的参数 Parameters with Lambda Expression Components

 

使用Lambda表达式,而不是在组件注册时直接传入参数能够保证动态参数在服务被调用时被传入。

在组件注册表达式中,你可以通过改变用语注册组件的委托签名来使用传入的参数。可以使用具有一个IComponentContext参数和一个IEnumerable<Parameter>参数的委托来替代只使用单个IComponentContext参数的委托。

 

// Use TWO parameters to the registration delegate:
// c = The current IComponentContext to dynamically resolve dependencies
// p = An IEnumerable<Parameter> with the incoming parameter set
builder.Register((c, p) =>
                 new ConfigReader(p.Named<string>("configSectionName")))
       .As<IConfigReader>();

 

当通过使用参数解析组件时,你的Lambda表达式将会使用传入的参数:

 

reader = scope.Resolve<IConfigReader>(new NamedParameter("configSectionName", "sectionName"));