Overview
The objective of this post is to brief how you can leverage the lazy initialization support available in MEF. We’ll examine MEF and Lazy, and then we’ll see how to use them together.
Preface About MEF
I hope you are already using Managed Extensibility Framework to build beautiful software. If you are not yet there, that is a crime, and I highly recommend you to read my introductory post on MEF. Let us start with another very basic MEF example. Let us get back our Zoo.
We are composing our Zoo with a couple of Animals here.
//Abstract animal interface
interface IAnimal { void Eat(); }
//Concrete animal 1
[Export(typeof(IAnimal))]
class Lion : IAnimal
{
public Lion() { Console.WriteLine("Grr.. Lion got created"); }
public void Eat() { Console.WriteLine("Grr.. Lion eating meat"); }
}
//Concrete animal 2
[Export(typeof(IAnimal))]
class Rabbit : IAnimal
{
public Rabbit() { Console.WriteLine("Crrr.. Rabbit got created"); }
public void Eat() { Console.WriteLine("Crrr.. Rabbit eating carrot"); }
}
//Our Zoo. MEF will inject animals to this zoo later, at the time of composition
class Zoo
{
[ImportMany(typeof(IAnimal))]
public IEnumerable<IAnimal> Animals { get; set; }
}
//Let us construct our zoo and animals
class Program
{
static void Main(string[] args)
{
//Let us create a catalog and a container
var catalog = new AssemblyCatalog(typeof(Program).Assembly);
var container = new CompositionContainer(catalog);
//Compose the zoo.
var zoo = new Zoo();
container.ComposeParts(zoo);
//Let's feed our animals
foreach (var animal in zoo.Animals)
animal.Eat();
}
}
As you remember, a catalog is a sack full of types (cookies) to export. The container will fetch these exported types from the catalog, to instantiate and import them where ever applicable - based on the matching contracts specified in the Export and Import attributes. (Note to self - Shh!! don’t mention anything about ExportProvider and ExportDefinition now). In this case, we are using a type as the contract (IAnimal) for our Export and Import. And if you run that app, you’ll see.. hm.. a cute black screen. More importantly, you’ll see that MEF has created an instance of Lion and Rabbit at the time of composition – i.e, when we call container.ComposeParts. See the messages we are writing from the constructor.
Note – If you want to be more realistic or if you hate animals in general, my advice is to think about your Business class instead of the Zoo, and think about some validation rules instead of those Animals. So that, you can plug in new validation rules with out affecting your entire system.
Preface About Lazy<T>
Oh yea, though MEF is seductive, let us stop thinking about that for a moment. Let us be a bit Lazy. You might have already heard about the Lazy<T> class in .NET 4.0. Lazy class allow you to support for lazy initialization. I.e, you can use Lazy<T> to defer the creation of a large or resource-intensive object, till you really need that.
Here is a quick example.
//Let us be lazy about creating a lion
Lazy<Lion> lazyLion = new Lazy<Lion>();
//Do something else..
//Actual object will be created here
var lion = lazyLion.Value;
The interesting point to note is, you can defer the creation of your lion, till you really need it in your flow, probably inside an if block or so. Another interesting aspect of Lazy<T> is, you can specify your own factory method to create your object, via the Lazy<T> constructor. See this example.
//Let us be lazy about creating our animal
Lazy<IAnimal> lazyAnimal = new Lazy<IAnimal>(()=>new Lion());
//Actual object will be created here
var animal = lazyAnimal.Value;
Being Lazy with MEF
Now, let us see how to combine MEF and Lazy together. All right, you don’t really need to do anything special there – MEF already has some great support for Lazy. MEF can wire up your exports directly to a Lazy
//Our zoo
class Zoo
{
//** MODIFICATION 1 -You need to directly import to Lazy<IAnimal>
[ImportMany(typeof(IAnimal))]
public IEnumerable<Lazy<IAnimal>> Animals { get; set; }
}
//Abstract animal interface
interface IAnimal { void Eat(); }
//Concrete animal 1
[Export(typeof(IAnimal))]
class Lion : IAnimal
{
public Lion() { Console.WriteLine("Grr.. Lion got created"); }
public void Eat() { Console.WriteLine("Grr.. Lion eating meat"); }
}
//Concrete animal 2
[Export(typeof(IAnimal))]
class Rabbit : IAnimal
{
public Rabbit() { Console.WriteLine("Crrr.. Rabbit got created"); }
public void Eat() { Console.WriteLine("Crrr.. Rabbit eating carrot"); }
}
//Let us construct our zoo and animals
class Program
{
static void Main(string[] args)
{
//Let us create a catalog and a container
var catalog = new AssemblyCatalog(typeof(Program).Assembly);
var container = new CompositionContainer(catalog);
//Compose the zoo.
var zoo = new Zoo();
container.ComposeParts(zoo);
//** MODIFICATION 2 - An instance will be created only when you access it
//Use the Value property of the Lazy object to initialize and access the actual value
foreach (var animal in zoo.Animals)
animal.Value.Eat();
}
}
And now, to understand how this changed the flow, let us run the application.
You’ll see that our animals are getting created only when we consume them – and not at the time of composing the zoo as we did earlier.
Dealing with Metadata when MEF goes Lazy
MEF allows you to export Metadata along with the types you export. For example, assume that you want to specify whether your exported animals eat meat or not, so that some one can decide what to give them as food. One way is to use the ExportMetaData attribute with your exported types, as shown below.
//Concrete animal 1
[Export(typeof(IAnimal))]
[ExportMetadata("EatMeat",true)]
class Lion : IAnimal
{
public Lion() { Console.WriteLine("Grr.. Lion got created"); }
public void Eat() { Console.WriteLine("Grr.. Lion eating meat"); }
}
//Concrete animal 2
[Export(typeof(IAnimal))]
[ExportMetadata("EatMeat", false)]
class Rabbit : IAnimal
{
public Rabbit() { Console.WriteLine("Crrr.. Rabbit got created"); }
public void Eat() { Console.WriteLine("Crrr.. Rabbit eating carrot"); }
}
That looks a bit clumsy, because of those strings. Right? A better way is to create your own custom Export attribute that includes the metadata information as well. That is pretty simple. The code below is equivalent to what we have just done above. You see that we are creating a custom export attribute named ExportAnimal.
//Our custom metadata attribute to exp animals
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
class ExportAnimal : ExportAttribute
{
//Pass the contract type to the base
public ExportAnimal() : base(typeof(IAnimal)) { }
//Additional metadata info
public bool EatMeat { get; set; }
}
//Concrete animal 1
[ExportAnimal(EatMeat=true)]
class Lion : IAnimal
{
public Lion() { Console.WriteLine("Grr.. Lion got created"); }
public void Eat() { Console.WriteLine("Grr.. Lion eating meat"); }
}
//Concrete animal 2
[ExportAnimal(EatMeat = false)]
class Rabbit : IAnimal
{
public Rabbit() { Console.WriteLine("Crrr.. Rabbit got created"); }
public void Eat() { Console.WriteLine("Crrr.. Rabbit eating carrot"); }
}
Now let us come to the real question. How to import the metadata information in a Lazy way? Fortunately, MEF has an overload of Lazy, Lazy //An interface to import animal metadata
//This should match the metadata we've in our custom export definition
public interface IAnimalMetadata
{
bool EatMeat { get; }
}
//Our zoo
class Zoo
{
//Directly import to Lazy<IAnimal,IAnimalMetadata>
[ImportMany(typeof(IAnimal))]
public IEnumerable<Lazy<IAnimal, IAnimalMetadata>> Animals { get; set; }
}
So, here is the final piece that includes the above fragments. You can see that we are exporting our animals using a custom export attribute, and importing them in a lazy way along with the metadata. Then, Have a look at the Main method. You'll find that we are using the metadata to feed only the animals that eat meat.
In other words, the Lazy implementation provides you the luxury of initializing only the animals that you want to feed, at the time of feeding them - and not all the animals.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
namespace MefLazy
{
#region Contracts
//Abstract animal interface
interface IAnimal { void Eat(); }
#endregion
#region Export Related
//Our custom metadata attribute to exp animals
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
class ExportAnimal : ExportAttribute
{
//Pass the contract type to the base
public ExportAnimal() : base(typeof(IAnimal)) { }
//Additional metadata info
public bool EatMeat { get; set; }
}
//Concrete animal 1
[ExportAnimal(EatMeat = true)]
class Lion : IAnimal
{
public Lion() { Console.WriteLine("Grr.. Lion got created"); }
public void Eat() { Console.WriteLine("Grr.. Lion eating meat"); }
}
//Concrete animal 2
[ExportAnimal(EatMeat = false)]
class Rabbit : IAnimal
{
public Rabbit() { Console.WriteLine("Crrr.. Rabbit got created"); }
public void Eat() { Console.WriteLine("Crrr.. Rabbit eating carrot"); }
}
#endregion
#region Import Related
//An interface to import animal metadata
public interface IAnimalMetadata
{
bool EatMeat { get; }
}
//Our zoo
class Zoo
{
//Directly import to Lazy<IAnimal,IAnimalMetadata>
[ImportMany(typeof(IAnimal))]
public IEnumerable<Lazy<IAnimal, IAnimalMetadata>> Animals { get; set; }
}
#endregion
#region Main
//Let us construct our zoo and animals
class Program
{
static void Main(string[] args)
{
//Let us create a catalog and a container
var catalog = new AssemblyCatalog(typeof(Program).Assembly);
var container = new CompositionContainer(catalog);
//Compose the zoo.
var zoo = new Zoo();
container.ComposeParts(zoo);
//An instance will be created only when you access it
//Use the Value property of the Lazy object to initialize and access the actual value
//Let us feed only animals eating meat
foreach (var animal in zoo.Animals)
if (animal.Metadata.EatMeat)
animal.Value.Eat();
}
}
#endregion
}
Conclusion
I encourage you to apply these concepts to more practical scenarios. Like, instead of a Zoo, think about a RuleProcessor that runs a set of rules on a business object - and instead of an Animal, think about a Rule that can validate or process the business object. I’ll give some more practical examples pretty soon :). For now, the objective was to introduce Lazy concepts and MEF, and I hope you enjoyed the read. And you can download the final version of the code from the above link. Keep in touch, Follow me on twitter
Also, read my last post 4 .NET 4.0 Libraries You should know about
Happy Coding!!

