[Export]Here you can see a fragment of an Account class implementation which has an ILogger instance injected in lazy manner. As long as the Deposit method is not invoked with a value less than 0, the logger instance is not used, thus, it is actually not created at all! Lazy instantiation is particularly usefull when you are dealing with objects which are expensive to create.
public class Account
{
[Import]
public Lazy<ILogger> Logger { get; set; }
public void Deposit(decimal amount)
{
if (amount < 0)
{
Logger.Value.Log("Amount is less than 0.");
}
}
}
There are some IoC containers which support Lazy<T> out of the box, namely Autofac 2, or Managed Extensibility Framework to name a few (I don't like calling MEF an IoC container, it's rather a composition engine since it is not constrained to inject types, but methods, fields and properties as well - sorry for that). Unfortunately, Unity IoC (even the latest Unity 2.0) is not on that list. Yes, I know. Unity 2.0 has a support for a concept known as automatic factories (you can read more on that here). Basically speaking, automatic factories allow to pull Func<T> - which is a delegate to a function which returns the concrete instance of the requested component when called. The idea is to fire this delegate when the instance is really needed. So you can say this serves the same purpose as Lazy<T>. Yeah, but it is not Lazy<T> ;) Besides, having the ability to pull Lazy<T> enables even better usage of the Unity+MEF integration layer, which is a part of MEF Contrib initiative. You can always find lates sources hosted on github.
OK. How to leverage the Lazy<T> and IEnumerable<Lazy<T>> ? This is a piece of cake. There are three ways of using the extension. If you want to pull a single component, here's how to do that:
unityContainer.RegisterType<IComponent, Component1>();If you want to pull all components registered under a common type, you can do the following:
var lazyComponent = unityContainer.Resolve<Lazy<IComponent>>();
unityContainer.RegisterType<IComponent, Component1>("component1");
unityContainer.RegisterType<IComponent, Component2>("component2");
unityContainer.RegisterType<IComponent, Component3>();
// A collection of non-lazy components
var collectionOComponents = unityContainer.Resolve<IEnumerable<IComponent>>();
// Lazy collection of components, once resolved, all the components get resolved
var lazyCollectionOfComponents = unityContainer.Resolve<Lazy<IEnumerable<IComponent>>>();
// Concrete collection of lazy loaded components
var collectionOfLazyComponents = unityContainer.Resolve<IEnumerable<Lazy<IComponent>>>();;
One thing to note. Resolving an IEnumerable is not the same as calling ResolveAll! ResolveAll returns only named types, whereas IEnumerable returns everything!
Either way, before you can use anything presented so far, you have to add the extension the the container. It is as simple as calling:
An important, and nice thing as well, is that the presented stuff is already the part of MEF Contrib. If you use MEF+Unity integration layer, you automatically get this behavior out of the box!
unityContainer.AddNewExtension<LazySupportExtension>();
An important, and nice thing as well, is that the presented stuff is already the part of MEF Contrib. If you use MEF+Unity integration layer, you automatically get this behavior out of the box!
The code sample can be downloaded, as always, from my code gallery here. Enjoy!