Introduction
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 shall be instantiated. This data, in general, is known as the metadata. And so, 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 the 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.
Lazy<T, TMetadata>
Lazy<T,TMetadata> is a type provided by MEF to hold the 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();
- // registering components
- builder.RegisterType<Program>();
- builder.RegisterType<LogWriter>();
- builder.RegisterType<TextLogger>()
- .As<ILogger>()
- .WithMetadata<LoggerMetadata>(config => config.For(lm => lm.LoggerName, "text"));
- builder.RegisterType<DbLogger>()
- .As<ILogger>()
- .WithMetadata<LoggerMetadata>(config => config.For(lm => lm.LoggerName, "db"));
- // resolving the Program class
- using (var container = builder.Build())
- {
- container.Resolve<Program>().Start();
- }

Join the conversation! Your thoughts help the community grow.