Skip to content

Using Lazy<T, TMetadata> in Dependency Injection

Last updated on July 7, 2018

We know how to use a Lazy<T> and IEnumerable<T>. Recently, I came across a piece of code that uses these two in combination. However, it doesn’t make sense if we simply inject a dependency of IEnumerable<Lazy<T>>. Therefore, we need some data to decide which one of the registered implementations, returned by the container, shall be instantiated. This data is generally known as the Metadata. In this case, we will now inject a dependency as  IEnumerable<Lazy<T,TMetadata>>.


Lazy<T, TMetadata>

Lazy<T,TMetadata> is a type provided by MEF to hold indirect references to exports. Here, in addition to the exported object itself, you also get export metadata, or information that describes the exported object. Each Lazy<T,TMetadata> contains a T object, representing an actual operation, and  TMetadata object, representing its metadata.


Register & Resolve

Suppose, we have a service  ILogger which has multiple implementations in the system. And, the class  LoggerMetadata provides metadata for the service. Now, the code to register and resolve this service from the container looks like the following:

var builder = new ContainerBuilder();

   .WithMetadata<LoggerMetadata>(config => config.For(lm => lm.LoggerName, "text"));

   .WithMetadata<LoggerMetadata>(config => config.For(lm => lm.LoggerName, "db"));

using (var container = builder.Build())


Using Metadata

Now think of a user class, say  LogWriter, which uses the service  ILogger. The  LogWriter, accepts all the implementations of service, registered with the container. Furthermore, it uses the metadata to decide which implementation should be instantiated. Kindly refer the below code:

public class LogWriter
    private readonly IEnumerable<Lazy<ILogger, LoggerMetadata>> _loggers;
    public LogWriter(IEnumerable<Lazy<ILogger, LoggerMetadata>> loggers)
        _loggers = loggers;

    public void Write(string useLogger, string message)
        var logger = _loggers.First(l => l.Metadata.LoggerName == useLogger);


Of course, the above code can break with a  NullReferenceException, but kindly ignore that for now. Not to mention, instead of passing the information about, which logger shall be used, as a method parameter there are surely better ways to do this. However, this example only intends to give you a gist of how we can use metadata to make run time decisions.

Published inDesign Patterns & Principles