Lazy<T> represents a value that is initialised the first time it is accessed.
var lineCount = new Lazy<int>(() => CountLines("bigfile.txt"));
// Count happens when value is accessed
// No counting here either - once the value is initialised it is stored
Lazy<T, TMetadata> works exactly the same way as
Lazy<T>, but adds a
Metadata property that can be used to get information about the value before it is instantiated.
// The filename passed in the constructor is stored in the Metadata property
// of type string
var lineCount = new Lazy<int, string>(() => CountLines(filename), filename);
// Metadata (i.e. the filename) can be accessed without causing the value to be initialised
Metadata becomes very useful when you have more than one lazy item, and need to choose between them before accessing and initialising the value.
Components in an IoC container can use the lazy types to express dependencies, and thus delay the construction of part of the object graph either for functional or performance reasons.
One of the very nice features of the Managed Extensibility Framework (MEF) in .NET 4.0 is the way lazy dependencies are handled. An ‘import’ (MEF terminology) of type
Lazy<T> will be injected automatically so long as
T is registered with the
In Autofac’s latest 2.1 beta, an extension called
LazyDependencyModule gives a similar result.
Autofac 2 still supports .NET 3.5. The only Autofac assembly that requires .NET 4.0 is
Autofac.Integration.Mef.dll, while all others target .NET 3.5.
Simple Lazy<T> Example
Let’s imagine that in our particular ASP.NET application, creating repositories is fairly expensive. In some of the code paths through
ContactsController we don’t use the injected contacts repository, and would like to avoid the cost of instantiating it.
Yes dear reader, you need to use your imagination here rather than a profiler… :)
To communicate this requirement to Autofac, you use
Lazy<IContactRepository> as the type of the controller constructor parameter:
public ContactsController(Lazy<IContactRepository> contacts)
_contacts = contacts;
public ActionResult Show(int contactId)
ViewData.Model = _contacts.Value.Load(contactId);
When configuring your Autofac
ContainerBuilder, add the
// No special configuration for the controller...
// ...or the repository.
And that’s it! Wherever
Lazy<T> is resolved, Autofac will do the right thing.
I’ve included downloadable code for a more complete example Lazy in Autofac 2 demonstrating metadata use.
Log component accepts a list of appenders, each with metadata. Based on the logging request, the logger selects an appender (instantiating if necessary) and writes a message to it.
readonly IEnumerable<Lazy<ILogAppender, ILogAppenderMetadata>> _appenders;
public Log(IEnumerable<Lazy<ILogAppender, ILogAppenderMetadata>> appenders)
_appenders = appenders;
public void Write(string destination, string message)
var appender = _appenders.First(a => a.Metadata.AppenderName == destination);
You can see in this example how Autofac 2’s automatic support for
IEnumerable dependencies works just as well combined with laziness.
The metadata view
ILogAppenderMetadata has a single property
AppenderName. The value of this property will be retrieved from the implementing component’s extended properties.
ILogAppenderMetadata to the underlying dictionary of extended properties is done using the same mechanism as MEF uses, and you can find more information on that via the MEF site.
Under the Hood
If you’re interested to see how easy Autofac 2 makes supporting these ‘context adapters’, check out the implementation handling
Lazy<T, TMetadata>, weighing in at 52 lines including braces,
using statements and whitespace :)