项目
版本

Autofac 使用 JSON 或 XML 配置

大多数 IoC 容器都提供了程序接口以及基于 JSON 或 XML 的配置支持,Autofac 也不例外。

Autofac 通过 ContainerBuilder 类鼓励使用程序化配置。通过程序化接口是容器设计的核心。当在编译时无法选择或配置具体类时,推荐使用 JSON 或 XML。

深入研究 JSON 或 XML 配置之前,请务必阅读 模块 部分,它解释了 JSON 或 XML 组件注册无法处理的复杂场景。JSON 或 XML 配置并不是程序化配置功能对功能的替代,因此复杂的场景可能需要结合 JSON 和模块一起使用。

使用 Microsoft 配置 (4.0+)

注意 Microsoft 配置适用于 Autofac.Configuration 4.0 及更高版本。它不适用于该包的早期版本。

随着 Microsoft.Extensions.Configuration 的发布,以及 Autofac.Configuration 4.0.0,Autofac 利用了过去受限于应用程序配置文件(如 app.config 或 web.config)时无法获得的更灵活的配置模型。如果您之前使用过这些配置文件,您需要将配置迁移到新格式,并更新与应用程序容器设置配置的方式。

快速入门

设置应用程序配置的基本步骤如下:

  1. 设置可以在 Microsoft.Extensions.Configuration 中读取的 JSON 或 XML 文件。
    • JSON 配置使用 Microsoft.Extensions.Configuration.Json
    • XML 配置使用 Microsoft.Extensions.Configuration.Xml
  2. 使用 Microsoft.Extensions.Configuration.ConfigurationBuilder 构建配置。
  3. 创建一个 Autofac.Configuration.ConfigurationModule,并将构建好的 Microsoft.Extensions.Configuration.IConfiguration 传递给它。
  4. 将 Autofac.Configuration.ConfigurationModule 注册到您的容器中。

包含一些简单注册的配置文件看起来像这样:

{
  "defaultAssembly": "Autofac.Example.Calculator",
  "components": [
    {
      "type": "Autofac.Example.Calculator.Addition.Add, Autofac.Example.Calculator.Addition",
      "services": [
        {
          "type": "Autofac.Example.Calculator.Api.IOperation"
        }
      ],
      "injectProperties": true
    },
    {
      "type": "Autofac.Example.Calculator.Division.Divide, Autofac.Example.Calculator.Division",
      "services": [
        {
          "type": "Autofac.Example.Calculator.Api.IOperation"
        }
      ],
      "parameters": {
        "places": 4
      }
    }
  ]
}

JSON 更干净、易读,但如果您更喜欢 XML,同样的配置会看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<autofac defaultAssembly="Autofac.Example.Calculator">
    <components name="0">
        <type>Autofac.Example.Calculator.Addition.Add, Autofac.Example.Calculator.Addition</type>
        <services name="0" type="Autofac.Example.Calculator.Api.IOperation" />
        <injectProperties>true</injectProperties>
    </components>
    <components name="1">
        <type>Autofac.Example.Calculator.Division.Divide, Autofac.Example.Calculator.Division</type>
        <services name="0" type="Autofac.Example.Calculator.Api.IOperation" />
        <injectProperties>true</injectProperties>
        <parameters>
            <places>4</places>
        </parameters>
    </components>
</autofac>

请注意 XML 中组件和服务的序号命名——这是由于 Microsoft.Extensions.Configuration 处理有序集合(数组)的方式造成的。

按照以下方式将配置构建并注册到 Autofac ContainerBuilder:

// 将配置添加到 ConfigurationBuilder。
var config = new ConfigurationBuilder();
// config.AddJsonFile 来自 Microsoft.Extensions.Configuration.Json
// config.AddXmlFile 来自 Microsoft.Extensions.Configuration.Xml
config.AddJsonFile("autofac.json");

// 将 ConfigurationModule 注册到 Autofac。
var module = new ConfigurationModule(config.Build());
var builder = new ContainerBuilder();
builder.RegisterModule(module);

默认程序集

您可以在配置中指定一个“默认程序集”选项,以帮助您以更短的形式写类型。如果在类型或接口引用中未指定完整的程序集限定类型名称,将假设其位于默认程序集中。

{
  "defaultAssembly": "Autofac.Example.Calculator"
}

组件

组件是最常见的注册项。您可以为每个组件指定从生命周期范围到参数的各种内容。

组件在配置中的顶级 components 元素中添加。其中包含要注册的所有组件。

这个示例显示了一个组件,它包含了所有选项,只是为了说明语法。在实际组件注册中,您不会在每个注册中使用所有这些选项。

{
  "components": [
    {
      "type": "Autofac.Example.Calculator.Addition.Add, Autofac.Example.Calculator.Addition",
      "services": [
        {
          "type": "Autofac.Example.Calculator.Api.IOperation"
        },
        {
          "type": "Autofac.Example.Calculator.Api.IAddOperation",
          "key": "add"
        }
      ],
      "autoActivate": true,
      "injectProperties": true,
      "instanceScope": "per-dependency",
      "metadata": [
        {
          "key": "answer",
          "value": 42,
          "type": "System.Int32, mscorlib"
        }
      ],
      "ownership": "external",
      "parameters": {
        "places": 4
      },
      "properties": {
        "DictionaryProp": {
          "key": "value"
        },
        "ListProp": [1, 2, 3, 4, 5]
      }
    }
  ]
}
元素名称 描述 有效值
type 唯一必需的。组件的 concrete 类(如果在非默认程序集中的话,需要指定完整的程序集限定类型名称)。 可以通过反射创建的任何 .NET 类型名称。
services 组件公开的服务的数组。每个服务必须有 type,可选地指定 key。 可以通过反射创建的任何 .NET 类型名称。
autoActivate 一个布尔值,指示组件是否应该 自动激活 。 true, false
injectProperties 一个布尔值,指示是否应 为组件启用属性注入 。 true, false
instanceScope 组件的 实例范围 。 singleinstance, perlifetimescope, perdependency, perrequest
metadata 一个 元数据值数组 ,用于关联组件。每个条目指定 name、type 和 value。 任何 元数据值 。
ownership 允许您控制 组件的生命周期范围是否负责释放组件,还是由您的代码负责 。 lifetimescope, external
parameters 一个名值字典,其中每个元素的名称是构造函数参数的名称,值是要注入的值。 组件类型的构造函数中的任意参数。
properties 一个名值字典,其中每个元素的名称是属性的名称,值是要注入的值。 组件类型上的任何可设置属性。

注意,parameters 和 properties 都支持字典和枚举值。您可以在 JSON 结构的示例中看到如何指定这些内容。

模块

在使用 Autofac 时,可以将模块与组件一起使用配置来注册。模块作为配置中的顶级 modules 元素内的一个数组添加。

以下示例显示了一个具有所有选项的模块,只是为了说明语法。实际上,在每个模块注册时,您不会使用所有这些选项。

{
  "modules": [
    {
      "type": "Autofac.Example.Calculator.OperationModule, Autofac.Example.Calculator",
      "parameters": {
        "places": 4
      },
      "properties": {
        "DictionaryProp": {
          "key": "value"
        },
        "ListProp": [1, 2, 3, 4, 5]
      }
    }
  ]
}
元素名称 描述 有效值
type 必须填写。模块的具体类(如果在默认以外的其他程序集中,需要提供完整的类型名)。 任何从 Autofac.Module 派生且可以通过反射创建的.NET 类型。
parameters 名值字典,其中每个元素的名称是构造函数参数的名称,值是要注入的值。 模块类型构造函数中的任何参数。
properties 名值字典,其中每个元素的名称是属性的名称,值是要注入的值。 模块类型的任何可设置属性。

请注意,parameters 和 properties 都支持字典和枚举值。上面的 JSON 结构中已经展示了如何指定这些。

如果愿意,您可以根据不同的参数/属性集多次注册同一个模块。

类型名称

在所有情况下,只要看到类型名称(组件类型、服务类型、模块类型),预期它将是标准的、完整类型名(MSDN 文档),通常可以传递给 Type.GetType(string typename)。如果类型在 defaultAssembly 中,您可以省略 assembly 名称,但无论如何添加它都没有坏处。

完整的类型名包含命名空间、逗号和 assembly 名称,例如 Autofac.Example.Calculator.OperationModule, Autofac.Example.Calculator。在这种情况下,Autofac.Example.Calculator.OperationModule 是类型,它位于 Autofac.Example.Calculator assembly 中。

泛型稍微复杂一些。配置不支持开放泛型,因此也需要指定每个泛型参数的完全限定名称。

例如,假设在 ConfigWithGenericsDemo assembly 中有一个泛型接口 IRepository<T>,并且有一个名为 StringRepository 的类实现了 IRepository<string>。要在配置中注册它,如下所示:

{
  "components": [
    {
      "type": "ConfigWithGenericsDemo.StringRepository, ConfigWithGenericsDemo",
      "services": [
        {
          "type": "ConfigWithGenericsDemo.IRepository`1[[System.String, mscorlib]], ConfigWithGenericsDemo"
        }
      ]
    }
  ]
}

如果您难以确定类型名称,可以在代码中使用类似的方法:

// 将类型名称写入调试输出窗口,并从中复制粘贴到配置中。
System.Diagnostics.Debug.WriteLine(typeof(IRepository<string>).AssemblyQualifiedName);

与旧版配置的差异

从基于 app.config 的旧版(版本 4.0 之前)配置迁移到新格式时,需要注意以下几点:

  • 没有 ConfigurationSettingsReader。 Microsoft.Extensions.Configuration 完全取代了旧的 XML 格式配置。旧版配置文档不适用于 4.0 及更高版本的配置包。
  • 多个配置文件处理方式不同。 旧版配置有一个 files 元素,可以自动同时加载几个文件进行配置。现在使用 Microsoft.Extensions.Configuration.ConfigurationBuilder 来实现这一点。
  • 自动激活已支持。 现在可以指定 自动激活组件,这是以前配置中不可用的功能。
  • XML 使用子元素而非属性。 这有助于保持 XML 和 JSON 解析器的兼容性,以便正确组合 XML 和 JSON 配置源。
  • 使用 XML 需要为组件和服务命名并使用数字。 Microsoft.Extensions.Configuration 要求每个配置项都有名称和值。它支持有序集合(数组)的方式是为集合中的无名元素自动分配数字名称(如 "0"、"1" 等)。如果您不使用 JSON,需要留意这个要求,否则可能无法得到预期结果。
  • 支持按请求生命周期范围。 以前无法配置元素以具有 每个请求生命周期范围。现在可以。
  • 名称/值中的破折号已移除。 XML 元素名称以前包含破折号,如 inject-properties,现在为了与 JSON 配置格式兼容,它们使用驼峰命名法,如 injectProperties。
  • 服务在子元素中指定。 旧版配置允许直接在组件顶部声明服务。新系统要求所有服务都在 services 集合中。

更多提示

新的 Microsoft.Extensions.Configuration 机制提供了很多灵活性。您可以利用以下功能:

  • 环境变量支持。 可以使用 Microsoft.Extensions.Configuration.EnvironmentVariables 来根据环境进行配置更改。快速调试、修补或修复代码而无需更改代码的一个方法是根据环境切换 Autofac 注册。
  • 易于配置合并。 ConfigurationBuilder 允许您从多个来源创建配置并合并它们。如果有很多配置,考虑扫描您的配置文件并动态构建配置,而不是硬编码路径。
  • 自定义配置源。 您可以实现自己的 Microsoft.Extensions.Configuration.ConfigurationProvider,它背后不仅仅依赖于文件。如果您想集中配置,可以考虑使用数据库或 REST API 支持的配置源。

使用应用程序配置(旧版预 4.0)

注意 下面描述的旧版应用程序配置适用于 3.x 版本及更早的 Autofac.Configuration。它不适用于 4.0 及更高版本的包。

在 Microsoft.Extensions.Configuration 和更新的配置模型发布之前,Autofac 与标准 .NET 应用程序配置文件(app.config / web.config)集成。在 3.x 版本的 Autofac.Configuration 包中,这是配置的主要方式。

设置

使用旧版配置机制,您需要在配置文件的顶部附近声明一个节处理器:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/>
    </configSections>

然后,提供一个描述组件的节:

<autofac defaultAssembly="Autofac.Example.Calculator.Api">
    <components>
        <component
            type="Autofac.Example.Calculator.Addition.Add, Autofac.Example.Calculator.Addition"
            service="Autofac.Example.Calculator.Api.IOperation" />

        <component
            type="Autofac.Example.Calculator.Division.Divide, Autofac.Example.Calculator.Division"
            service="Autofac.Example.Calculator.Api.IOperation" >
            <parameters>
                <parameter name="places" value="4" />
            </parameters>
        </component>
    </components>
</autofac>

defaultAssembly 属性是可选的,允许使用命名空间限定而非完全限定的类型名称,这可以节省一些混乱和打字,特别是如果您使用一个配置文件对应一个程序集(参见下面的附加配置文件)。

组件

组件是最常见的注册项。您可以为每个组件指定许多内容,从生命周期范围到参数。

组件属性

以下属性可用于 component 元素(默认值与程序化 API 相同):

属性名称 描述 有效值
type 必需属性。组件的实现类(如果在非默认命名空间的程序集中,则使用完全限定名)。 可以通过反射创建的任何 .NET 类型名称。
service 组件公开的服务。对于多个服务,请使用嵌套的 services 元素。 类似于 type 。
instance-scope 实例作用域 - 参见 实例作用域。 per-dependency、single-instance 或 per-lifetime-scope
instance-ownership 容器对实例的所有权 - 参见 InstanceOwnership 枚举。 lifetime-scope 或 external
name 组件的字符串名称。 任何非空字符串值。
inject-properties 启用组件的属性(设置器)注入。 yes、no

组件子元素

元素 描述
services 包含组件公开服务类型的列表(参见 service 属性)的 service 元素。
parameters 显式构造参数列表,用于设置实例(如上所示的示例)。
properties 显式属性值列表(与 parameters 语法相同)。
metadata 包含 name、value 和 type 属性的 item 节点列表。

XML 配置语法中缺少了一些可通过编程 API 提供的功能,例如注册泛型。在这种情况下,建议使用模块。

模块

使用组件精细配置容器可能会变得繁琐。Autofac 支持将组件封装到 模块 中,以封装实现并提供灵活的配置。

通过类型注册模块:

    <modules>
        <module type="MyModule" />

与上述组件类似,您可以在模块注册中添加嵌套的 parameters 和 properties 。

额外配置文件

您可以使用以下方式包含其他配置文件:

    <files>
        <file name="Controllers.config" section="controllers" />

配置容器

首先,您的项目必须引用 Autofac.Configuration.dll。

使用 ConfigurationSettingsReader 初始化容器配置,其中包含您给 XML 配置节的名称:

var builder = new ContainerBuilder();
builder.RegisterModule(new ConfigurationSettingsReader("mycomponents"));
// 注册其他组件并调用Build()创建容器。

容器设置读取器会覆盖已注册的默认组件;您可以编写应用程序,使其在默认情况下运行良好,然后只针对特定部署重写必要的组件注册。

多个文件或节

在同一个容器中可以使用多个设置读取器,以读取不同的节,甚至如果提供了文件名给 ConfigurationSettingsReader 构造函数,还可以读取不同的配置文件。

在本文档中