Autofac supports automatically resolving particular types implicitly to support special relationships between components and services. To take advantage of these relationships, simply register your components as normal, but change the constructor parameter in the consuming component or the type being resolved in the Resolve() call so it takes in the specified relationship type.

For example, when Autofac is injecting a constructor parameter of type IEnumerable<ITask> it will not look for a component that supplies IEnumerable<ITask>. Instead, the container will find all implementations of ITask and inject all of them.

(Don’t worry - there are examples below showing the usage of the various types and what they mean.)

Note: To override this default behavior it is still possible to register explicit implementations of these types.

The table below summarizes each of the supported relationship types in Autofac and shows the .NET type you can use to consume them. Each relationship type has a more detailed description and use case after that.

A lazy dependency is not instantiated until its first use. This appears where the dependency is infrequently used, or expensive to construct. To take advantage of this, use a Lazy<B> in the constructor of A:

publicclassA{Lazy<B>_b;publicA(Lazy<B>b){_b=b}publicvoidM(){// The component implementing B is created the// first time M() is called_b.Value.DoSomething();}}

If you have a lazy dependency for which you also need metadata, you can use Lazy<B,M> instead of the longer Meta<Lazy<B>,M>.

An owned dependency can be released by the owner when it is no longer required. Owned dependencies usually correspond to some unit of work performed by the dependent component.

This type of relationship is interesting particularly when working with components that implement IDisposable. Autofac automatically disposes of disposable components at the end of a lifetime scope, but that may mean a component is held onto for too long; or you may just want to take control of disposing the object yourself. In this case, you’d use an owned dependency.

publicclassA{Owned<B>_b;publicA(Owned<B>b){_b=b;}publicvoidM(){// _b is used for some task_b.Value.DoSomething();// Here _b is no longer needed, so// it is released_b.Dispose();}}

Internally, Autofac creates a tiny lifetime scope in which the B service is resolved, and when you call Dispose() on it, the lifetime scope is disposed. What that means is that disposing of B will also dispose of its dependencies unless those dependencies are shared (e.g., singletons).

This also means that if you have InstancePerLifetimeScope() registrations and you resolve one as Owned<B> then you may not get the same instance as being used elsewhere in the same lifetime scope. This example shows the gotcha:

varbuilder=newContainerBuilder();builder.RegisterType<A>().InstancePerLifetimeScope();builder.RegisterType<B>().InstancePerLifetimeScope();varcontainer=builder.Build();using(varscope=container.BeginLifetimeScope()){// Here we resolve a B that is InstancePerLifetimeScope();varb1=scope.Resolve<B>();b1.DoSomething();// This will be the same as b1 from above.varb2=scope.Resolve<B>();b2.DoSomething();// The B used in A will NOT be the same as the others.vara=scope.Resolve<A>();a.M();}

This is by design because you wouldn’t want one component to dispose the B out from under everything else. However, it may lead to some confusion if you’re not aware.

Using an auto-generated factory can let you effectively call Resolve<T>() without tying your component to Autofac. Use this relationship type if you need to create more than one instance of a given service, or if you’re not sure if you’re going to need a service and want to make the decision at runtime. This relationship is also useful in cases like WCF integration where you need to create a new service proxy after faulting the channel.

Lifetime scopes are respected using this relationship type. If you register an object as InstancePerDependency() and call the Func<B> multiple times, you’ll get a new instance each time. However, if you register an object as SingleInstance() and call the Func<B> to resolve the object more than once, you will get the same object instance every time.

Internally, Autofac treats these as typed parameters. What that means is that auto-generated function factories cannot have duplicate types in the input parameter list. For example, say you have a type like this:

In a loosely coupled scenario where the parameters are matched on type, you shouldn’t really know about the order of the parameters for a specific object’s constructor. If you need to do something like this, you should use a custom delegate type instead:

Should you decide to use the built-in auto-generated factory behavior (Func<X,Y,B>) and only resolve a factory with one of each type, it will work but you’ll get the same input for all constructor parameters of the same type.

varfunc=container.Resolve<Func<int,string,DuplicateTypes>>();// This works and is the same as calling// new DuplicateTypes(1, 1, "three")varobj=func(1,"three");

Lifetime scopes are respected using this relationship type as well as when using delegate factories. If you register an object as InstancePerDependency() and call the Func<X,Y,B> multiple times, you’ll get a new instance each time. However, if you register an object as SingleInstance() and call the Func<X,Y,B> to resolve the object more than once, you will get the same object instance every time regardless of the different parameters you pass in. Just passing different parameters will not break the respect for the lifetime scope.

Dependencies of an enumerable type provide multiple implementations of the same service (interface). This is helpful in cases like message handlers, where a message comes in and more than one handler is registered to process the message.

Let’s say you have a dependency interface defined like this:

publicinterfaceIMessageHandler{voidHandleMessage(Messagem);}

Further, you have a consumer of dependencies like that where you need to have more than one registered and the consumer needs all of the registered dependencies:

You can easily accomplish this using the implicit enumerable relationship type. Just register all of the dependencies and the consumer, and when you resolve the consumer the set of all matching dependencies will be resolved as an enumeration.

varbuilder=newContainerBuilder();builder.RegisterType<FirstHandler>().As<IMessageHandler>();builder.RegisterType<SecondHandler>().As<IMessageHandler>();builder.RegisterType<ThirdHandler>().As<IMessageHandler>();builder.RegisterType<MessageProcessor>();varcontainer=builder.Build();using(varscope=container.BeginLifetimeScope()){// When processor is resolved, it'll have all of the// registered handlers passed in to the constructor.varprocessor=scope.Resolve<MessageProcessor>();processor.ProcessMessage(m);}

The enumerable support will return an empty set if no matching items are registered in the container. That is, using the above example, if you don’t register any IMessageHandler implementations, this will break:

// This throws an exception - none are registered!scope.Resolve<IMessageHandler>();

However, this works:

// This returns an empty list, NOT an exception:scope.Resolve<IEnumerable<IMessageHandler>>();

This can create a bit of a “gotcha” where you might think you’ll get a null value if you inject something using this relationship. Instead, you’ll get an empty list.

The Autofac metadata feature lets you associate arbitrary data with services that you can use to make decisions when resolving. If you want to make those decisions in the consuming component, use the Meta<B> relationship, which will provide you with a string/object dictionary of all the object metadata:

In the case where you have many of a particular item (like the IEnumerable<B> relationship) but you want to pick one based on service key, you can use the IIndex<X,B> relationship. First, register your services with keys:

The custom relationship types in Autofac based on standard .NET types don’t force you to bind your application more tightly to Autofac. They give you a programming model for container configuration that is consistent with the way you write other components (vs. having to know a lot of specific container extension points and APIs that also potentially centralize your configuration).

For example, you can still create a custom ITaskFactory in your core model, but provide an AutofacTaskFactory implementation based on Func<Owned<ITask>> if that is desirable.

Note that some relationships are based on types that are in Autofac (e.g., IIndex<X,B>). Using those relationship types do tie you to at least having a reference to Autofac, even if you choose to use a different IoC container for the actual resolution of services.