JSON/XML Configuration — Autofac 7.0.0 documentation (original) (raw)

Autofac

Most IoC containers provide a programmatic interface as well as JSON/XML file-based configuration support, and Autofac is no exception.

Autofac encourages programmatic configuration through the ContainerBuilder class. Using the programmatic interface is central to the design of the container. JSON or XML is recommended when concrete classes cannot be chosen or configured at compile-time.

Before diving too deeply into JSON/XML configuration, be sure to read Modules - this explains how to handle more complex scenarios than the basic JSON/XML component registration will allow. Configuration in JSON/XML is not a feature-for-feature replacement for programmatic configuration, so complex scenarios may require a combination of JSON/XML and modules.

Configuring With Microsoft Configuration (4.0+)

Note

Microsoft Configuration applies to the 4.0+ version of Autofac.Configuration. It does not work with previous versions of the configuration package.

With the release of Microsoft.Extensions.Configuration, and Autofac.Configuration 4.0.0, Autofac takes advantage of the more flexible configuration model not previously available when limited to application configuration files. If you were using the app.config or web.config based configuration available before, you will need to migrate your configuration to the new format and update the way you set configuration with your application container.

Quick Start

The basic steps to getting configuration set up with your application are:

  1. Set up your configuration in JSON or XML files that can be read by Microsoft.Extensions.Configuration.
    • JSON configuration uses Microsoft.Extensions.Configuration.Json
    • XML configuration uses Microsoft.Extensions.Configuration.Xml
  2. Build the configuration using the Microsoft.Extensions.Configuration.ConfigurationBuilder.
  3. Create a new Autofac.Configuration.ConfigurationModule and pass the built Microsoft.Extensions.Configuration.IConfiguration into it.
  4. Register the Autofac.Configuration.ConfigurationModule with your container.

A configuration file with some simple registrations looks like this:

{ "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 is cleaner and easier to read, but if you prefer XML, the same configuration looks like this:

Autofac.Example.Calculator.Addition.Add, Autofac.Example.Calculator.Addition true Autofac.Example.Calculator.Division.Divide, Autofac.Example.Calculator.Division true 4

Note the ordinal “naming” of components and services in XML - this is due to the way Microsoft.Extensions.Configuration handles ordinal collections (arrays).

Build up your configuration and register it with the Autofac ContainerBuilder like this:

// Add the configuration to the ConfigurationBuilder. var config = new ConfigurationBuilder(); // config.AddJsonFile comes from Microsoft.Extensions.Configuration.Json // config.AddXmlFile comes from Microsoft.Extensions.Configuration.Xml config.AddJsonFile("autofac.json");

// Register the ConfigurationModule with Autofac. var module = new ConfigurationModule(config.Build()); var builder = new ContainerBuilder(); builder.RegisterModule(module);

Default Assembly

You can specify a “default assembly” option in the configuration to help write types in a shorter fashion. If you don’t specify an assembly-qualified type name in a type or interface reference, it will be assumed to be in the default assembly.

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

Components

Components are the most common thing that you’ll register. You can specify several things on each component from lifetime scope to parameters.

Components are added to a top-level components element in configuration. Inside that is an array of the components you want to register.

This example shows one component that has all of the options on it, just for syntax illustration purposes. You wouldn’t actually use every one of these in every component registration.

{ "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] } }] }

Element Name Description Valid Values
type The only required thing. The concrete class of the component (assembly-qualified if in an assembly other than the default). Any .NET type name that can be created through reflection.
services An array of services exposed by the component. Each service must have a type and may optionally specify a key. Any .NET type name that can be created through reflection.
autoActivate A Boolean indicating if the component should auto-activate. true, false
injectProperties A Boolean indicating whether property (setter) injection for the component should be enabled. true, false
instanceScope Instance scope for the component. singleinstance, perlifetimescope, perdependency, perrequest
metadata An array of metadata values to associate with the component. Each item specifies the name, type, and value. Any metadata values.
ownership Allows you to control whether the lifetime scope disposes the component or your code does. lifetimescope, external
parameters A name/value dictionary where the name of each element is the name of a constructor parameter and the value is the value to inject. Any parameter in the constructor of the component type.
properties A name/value dictionary where the name of each element is the name of a property and the value is the value to inject. Any settable property on the component type.

Note that both parameters and properties support dictionary and enumerable values. You can see an example of how to specify those in the JSON structure, above.

Modules

When using modules with Autofac, you can register those modules along with components when using configuration.

Modules are added to a top-level modules element in configuration. Inside that is an array of the modules you want to register.

This example shows one module that has all of the options on it, just for syntax illustration purposes. You wouldn’t actually use every one of these in every module registration.

{ "modules": [{ "type": "Autofac.Example.Calculator.OperationModule, Autofac.Example.Calculator", "parameters": { "places": 4 }, "properties": { "DictionaryProp": { "key": "value" }, "ListProp": [1, 2, 3, 4, 5] } }] }

Element Name Description Valid Values
type The only required thing. The concrete class of the module (assembly-qualified if in an assembly other than the default). Any .NET type name that derives from Autofac.Module that can be created through reflection.
parameters A name/value dictionary where the name of each element is the name of a constructor parameter and the value is the value to inject. Any parameter in the constructor of the module type.
properties A name/value dictionary where the name of each element is the name of a property and the value is the value to inject. Any settable property on the module type.

Note that both parameters and properties support dictionary and enumerable values. You can see an example of how to specify those in the JSON structure, above.

You are allowed to register the same module multiple times using different parameter/property sets if you so choose.

Type Names

In all cases where you see a type name (component type, service types, module type) it is expected to be the standard, assembly qualified type name that you would normally be able to pass to Type.GetType(string typename). If the type is in the defaultAssembly you can leave the assembly name off, but it doesn’t hurt to put it there regardless.

Assembly qualified type names have the full type with namespace, a comma, and the name of the assembly, like Autofac.Example.Calculator.OperationModule, Autofac.Example.Calculator. In that case, Autofac.Example.Calculator.OperationModule is the type and it’s in the Autofac.Example.Calculator assembly.

Generics are a little more complicated. Configuration does not support open generics so you have to specify the fully qualified name of each of the generic parameters, too.

For example, say you have a repository IRepository<T> in a ConfigWithGenericsDemo assembly. Let’s also say you have a class StringRepository that implements IRepository<string>. To register that in configuration, it would look like this:

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

If you’re having a difficult time figuring out what your type name is, you can always do something like this in code:

// Write the type name to the Debug output window and // copy/paste it out of there into your config. System.Diagnostics.Debug.WriteLine(typeof(IRepository).AssemblyQualifiedName);

Differences from Legacy Configuration

When migrating from the legacy (pre 4.0 version) app.config based format to the new format, there are some key changes to be aware of:

Additional Tips

The new Microsoft.Extensions.Configuration mechanism adds a lot of flexibility. Things you may want to take advantage of:

Configuring With Application Configuration (Legacy Pre-4.0)

Note

Legacy application configuration as described below applies to the 3.x and earlier versions of Autofac.Configuration. It does not work with the 4.0+ version of the package.

Prior to the release of Microsoft.Extensions.Configuration and the updated configuration model, Autofac tied into standard .NET application configuration files. (app.config / web.config). In the 3.x series of the Autofac.Configuration package, this was the way to configure things.

Setup

Using the legacy configuration mechanism, you need to declare a section handler somewhere near the top of your config file:

Then, provide a section describing your components:

    <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>

The defaultAssembly attribute is optional, allowing namespace-qualified rather than fully-qualified type names to be used. This can save some clutter and typing, especially if you use one configuration file per assembly (see Additional Config Files below.)

Components

Components are the most common thing that you’ll register. You can specify several things on each component from lifetime scope to parameters.

Component Attributes

The following can be used as attributes on the component element (defaults are the same as for the programmatic API):

Attribute Name Description Valid Values
type The only required attribute. The concrete class of the component (assembly-qualified if in an assembly other than the default.) Any .NET type name that can be created through reflection.
service A service exposed by the component. For more than one service, use the nested services element. As for type.
instance-scope Instance scope - see Instance Scope. per-dependency, single-instance or per-lifetime-scope
instance-ownership Container’s ownership over the instances - see the InstanceOwnership enumeration. lifetime-scope or external
name A string name for the component. Any non-empty string value.
inject-properties Enable property (setter) injection for the component. yes, no.

Component Child Elements

Element Description
services A list of service elements, whose element content contains the names of types exposed as services by the component (see the service attribute.)
parameters A list of explicit constructor parameters to set on the instances (see example above.)
properties A list of explicit property values to set (syntax as for parameters.)
metadata A list of item nodes with name, value and type attributes.

There are some features missing from the XML configuration syntax that are available through the programmatic API - for example registration of generics. Using modules is recommended in these cases.

Modules

Configuring the container using components is very fine-grained and can get verbose quickly. Autofac has support for packaging components into Modules in order to encapsulate implementation while providing flexible configuration.

Modules are registered by type:

You can add nested parameters and properties to a module registration in the same manner as for components above.

Additional Config Files

You can include additional config files using:

Configuring the Container

First, you must reference Autofac.Configuration.dll in from your project.

To configure the container use a ConfigurationSettingsReader initialized with the name you gave to your XML configuration section:

var builder = new ContainerBuilder(); builder.RegisterModule(new ConfigurationSettingsReader("mycomponents")); // Register other components and call Build() to create the container.

The container settings reader will override default components already registered; you can write your application so that it will run with sensible defaults and then override only those component registrations necessary for a particular deployment.

Multiple Files or Sections

You can use multiple settings readers in the same container, to read different sections or even different config files if the filename is supplied to the ConfigurationSettingsReader constructor.