Wednesday, November 27, 2013

MEF Simple Application in C#

I believe the best way to learn something new is to learn by simple and easy to understand example. Once you got the principles you can always proceed to more complex stuff. So today I'll show a simple example of MEF that will give you the basics.

Managed Extensibility Framework (MEF) is a component of .NET 4 and it allows to developer to build extensible applications. Imagine situation when you have some application and you know that in the future you will want to add more features to it, but you don't know exactly what and when they will be added, or may be you want another developer to develop new feature and integrate it seamlessly into the main application. So it looks like we need some module structured application here, right? And this is exactly what MEF provides.
Now to our sample application. When user starts it he asked to enter a string and a command (name of operation) he want to apply on that string. Once it's done the program will print the result string. So every operation we want to be a separate module. Enough bla bla! Let's see the code! :)

First, the Core class which is a part of the main application. Core class concentrates and launches all available extensions:
public interface ICore
{
    String PerformOperations(string data, string command);
}

[Export(typeof(ICore))]
public class Core : ICore
{
    [ImportMany]
    private IEnumerable<Lazy<IOperation, IOperationCommand>> _operations;

    public string PerformOperations(string data, string command)
    {
        foreach (Lazy<IOperation, IOperationCommand> i in _operations)
        {
            if (i.Metadata.Command.Equals(command))
                return i.Value.Operate(data);
        }
        return "Unrecognized operation";
    }
}

IOperation interface describes the operation itself and IOperationCommand describes the command name of operation:
public interface IOperation
{
    string Operate(string data);
}

public interface IOperationCommand
{
    String Command { get; }
}
Now look how simple is to write new operations. First one turn the input string into upper case, second one turns all the characters to lower case and the third one reverses the string:
[Export(typeof(MEF_Example.IOperation))]
[ExportMetadata("Command", "upper")]
public class UpperCase : MEF_Example.IOperation
{
    public string Operate(string data)
    {
        return data.ToUpper();
    }
}

[Export(typeof(MEF_Example.IOperation))]
[ExportMetadata("Command", "lower")]
public class LowerCase : MEF_Example.IOperation
{
    public string Operate(string data)
    {
        return data.ToLower();
    }
}

[Export(typeof(MEF_Example.IOperation))]
[ExportMetadata("Command", "reverse")]
public class Reverse : MEF_Example.IOperation
{
    public string Operate(string data)
    {
        return new string(data.ToCharArray().Reverse().ToArray());
    }
}
Now all we need is to initialize our application, here how we do it:
internal class Program
{
    private CompositionContainer _compositionContainer;

    [Import(typeof(ICore))]
    public ICore core;

    private Program()
    {
        var agregateCatalog = new AggregateCatalog();
        agregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
        agregateCatalog.Catalogs.Add(new DirectoryCatalog("Extensions"));

        _compositionContainer = new CompositionContainer(agregateCatalog);

        try
        {
            this._compositionContainer.ComposeParts(this);
        }
        catch (CompositionException compositionException)
        {
            Console.WriteLine(compositionException.ToString());
        }
    }

    private static void Main(string[] args)
    {
        Program program = new Program();
        string data, command;
        while (true)
        {
            Console.Clear();
            Console.Write("Please enter data:    ");
            data = Console.ReadLine();
            Console.Write("Please enter command: ");
            command = Console.ReadLine();
            Console.Write("Result: " + program.core.PerformOperations(data, command));
            Console.ReadLine();
        }
    }
}
This is it! As you see the code is pretty simple. This is how looks the application output:
MEF Simple Application Output

Download the source code (Visual Studio 2013 project).

3 comments:

  1. That's funny

    just yesterday I was looking for an easy example in MEF.

    Same with the singleton design pattern just one day before I was looking for an example.

    ReplyDelete
    Replies
    1. We are all connected, my friend :)
      Everything has its reason and purpose...

      Delete
  2. Is this line uneccessary?
    //agregateCatalog.Catalogs.Add(new DirectoryCatalog("Extensions"));

    ReplyDelete