|
BestPractices
Suggestions for using Autofac effectively.
Autofac2 The best place to get advice on using Autofac is the discussion group. The suggestions below may help in some applications. Always Resolve Dependencies from Nested LifetimesAutofac is designed to track and dispose of resources for you. To ensure this happens, make sure that long-running applications are partitioned into units of work (requests or transactions) that each resolve instances through their own lifetime scope. The RequestLifetime in the ASP.NET Integration is an example of this technique. Structure Configuration using ModulesModules give structure to container configuration and allow deployment-time settings to be injected. See this page for details. Use As() instead of Casting in Delegate RegistrationsAutofac infers implementation type from the expressions you use to register components: builder.Register(c => new Foo()).As<IFoo>(); ...makes the type Foo the LimitType of the component, where it can be inspected and used by extensions, while the equivalent: // Works, but avoid this builder.Register(c => (IFoo)new Foo()); or: // Works, but avoid this builder.Register<IFoo>(c => new Foo()); ...do not. Use Constructor Injection whenever PossibleThe concept of using constructor injection for required dependencies and property injection for optional dependencies is quite well known. An alternative, however, is to use the 'Null Object' or 'Special Case' pattern to provide default, do-nothing implementations for the optional service. This prevents the possibility of special-case code in the implementation of the component (e.g. if (Logger != null) Logger.Log("yuck");) Use Relationship Types instead of Service LocatorsGiving components access to the container, storing it in a public static property, or making functions like Resolve() available on a global 'IoC' class defeats the purpose of using dependency injection. Such designs have more in common with the Service Locator pattern. If components have a dependency on the container, look at how they're using the container to retrieve services, and add those services to the component's (dependency injected) constructor arguments instead. Use relationship types for components that need to instantiate other components or interact with the container in more advanced ways. Register Components from Least to Most SpecificAutofac overrides component registrations by default. This means that an application can register all of its default components, then read an associated .config file to override any that have been customised for the deployment environment. | |
Though it might go against best practices, I kind of like to register my components like this:
builder.Register(c => new Foo() as IFoo);
simply because it's lot more readable than this:
builder.Register(c => new Foo()).As<IFoo>();
Here are the five noisy characters you save: .<>()
Readabilty in the setup is important when trying with a glance to figure out how components are wired up. And if you build your app to rely on abstractions instead of implementations then you won't care about the ability to resolve Foo directly.
You actually need to do:
if you want both IFoo and Foo to be resolvable.
The suggestion isn't to do with resolving Foo directly - components have a LimitType property that extensions such as the DynamicProxy2 integration can use to find out details of the implementation type. The suggestion ensures that Autofac can use the concrete type as the limit, instead of an interface. Cheers!
Jim, As have a few overloads you can use to register more than one service type: