Click here to Skip to main content
15,918,003 members
Articles / Programming Languages / C# 4.0

MEF Logger – Creating plug-ins using MEF

Rate me:
Please Sign up or sign in to vote.
4.92/5 (12 votes)
5 Apr 2011CPOL6 min read 59.7K   1.9K   53   20
In this article, I will show how to build a pluggable component using MEF.


The goal is to learn how to use MEF in a very simple way. Let's build a component for recording logs, which is so important in applications, and this component should record logs in different ways. For example, log into a database, Windows event log, file server, etc. The big advantage of a pluggable component is that you can add other loggers without having to modify the application, and it's quite simple thanks to the MEF team..


MEF allows us to work with the concept of plug-ins. It provides a framework that allows us to specify the points where the application may be extended, exposing modules that can be plugged by external components. Rather than explicitly reference the components in the application, MEF allows our application to find components at runtime, through the composition of parts, managing what it takes to keep these extensions. Thus, our application does not depend on an implementation, but an abstraction, and can add new features to a program without the need to recompile, or even, without interrupting its execution.

MEF architecture (quite simple...)

To build a pluggable application using MEF, we must follow these steps:

  1. Define extension points
  2. The extension points are the "parts" of our application where we want to allow extensions. In our example, the extension point is the log writing.

  3. Define an MEF Contract for each extension point
  4. For each extension point set, we need to define an MEF contract that can be a delegate or an interface. In our example, we will create a DLL containing the interface that defines our MEF Contract.

  5. Define a class to manage the extension point
  6. To inform MEF how to manage our plug-ins, we use the Import attribute. In our example, the PluginHandler class will manage the extensions.

  7. Create the plug-in
  8. To create an extension, we should first implement the MEF Contract to the desired extension point. This extension is known as an MEF Composable Part. To define a class as a Composable Part, we use the attribute Export.

  9. Define a Catalog
  10. The catalog holds, at runtime, a list of all imported Composable Parts. The catalogs can be of type AssemblyCatalog, DirectoryCatalog, TypeCatalog, and DeploymentCatalog. In our example, we use the DirectoryCatalog, which discovers plug-ins in a certain directory.

Using the code

Our solution will consist of five projects.

Project name

Project type




Class Library

Main DLL, to be used by your application



Class Library

DLLl to be used by plug-ins



Class Library

Plug-in to register log in text files



Class Library

Plug-in to register log in the Windows Event Log




Test application


The solution is based on the following concept:

In order to create a pluggable system, we must export an interface that must be implemented by plug-ins. For this, I created a separate project to define the interface MefLogger.Interface.

The MefLogger project is our component that will use MEF to export and import the plug-in interface, and manage and fire commands to the plug-ins. The interesting thing is that the MefLogger project does not know how to register logs; it's the plugins who need to know how to do this. This project is a DLL that will find and manage plug-ins; this way, we don't need to bother implementing extension points in every application we want to implement logging. Just reference the MefLogger DLL in our application.

The MefFileLoggerPlugin and MefEventLoggerPlugin projects are our plug-ins. The SampleApp project is a very simple console application that demonstrates the use of the MefLogger DLL. Well, let's move to the example.

Create a new blank solution and give it the name MefLoggerSolution, as in Figure 1.


Figure 1

Add a new Class Library project by clicking the right mouse button (for righties) on the solution. Name this project MefLogger.Interface. This project will contain the contracts of our plug-in.


Figure 2


Figure 3

Rename Class1 to IMefLogger. It is a good practice to use the letter "I" at the beginning of the name to identify the class as an interface..


Figure 4


Figure 5

By renaming the class, we will receive the following message:


Figure 6

Clicking the Yes button, Visual Studio will replace all references to Class1 with IMefLogger.

Modify the content of the class for it to be an interface. The code should like below::

using System;
namespace MefLogger.Interface
    public interface IMefLogger
        void Log(string message);

Add a new Class Library project to our solution. Name this project MefLogger. This project will be our main DLL.


Figure 7


Figure 8

Change the Class 1 name for the Logger.

Add a new class to the MefLogger project called PluginHandler. This class will be responsible for loading and firing commands to the plug-ins.


Figure 9


Figure 10

Now let's add the necessary references. As I haven't registered MEF in the GAC, I will add references to the MEF DLLs located in a folder..


Figure 11

Add a reference to the MefLogger.Interface project..


Figure 12

Also add an Application Configuration File and name it MefLogger.dll.config.

Using the configuration files in the DLL is not trivial. To achieve this, we must follow these steps:

  1. Add a New Application Configuration File and name it MefLogger.dll.config.
  2. Change the BuildAction property to Content.
  3. Change the Copy to Output property to Copy Always.


Figure 13

Modify the MefLogger.dll.config file as below:

<?xml version="1.0" encoding="utf-8" ?>
    <add key ="PluginPath" value="D:\Artigos\MefLoggerSolution\Plugins"/>

Now we can write the code needed to use MEF and manage the plug-ins.

Modify the PluginHandler class to the code below:

using System;
using System.Collections.Generic;
// Referências ao MEF
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.ComponentModel.Composition.ReflectionModel;
using System.ComponentModel.Composition.AttributedModel;
using MefLogger.Interface;
using System.Reflection;
using System.ConFiguretion;

namespace MefLogger
    internal class PluginHandler : IDisposable
        // O atributo ImportMany permite que importemos várias classes que 
        // implementam a mesma interface
        // AddinList armazenará todos os plugins carregados
        public List<IMefLogger> AddinList
        { get; set; }

        // AggregateCatalog armazena os catálogos do MEF 
        AggregateCatalog catalog = new AggregateCatalog();

        public void InitializePlugins()
            // cria a instância da nossa lista de plugins
            AddinList = new List<IMefLogger>();
            // cria um DirectoryCatalog e adiciona ao nosso AggregateCatalog
            catalog.Catalogs.Add(new DirectoryCatalog(GetConFiguretionPath(), "*.dll"));
            // cria o CompositionContainer
            CompositionContainer cc = new CompositionContainer(catalog);
            // Efetua a mágica.... É neste momento que o MEF 
            // carrega os plugins e os adiciona ao nosso AddinList

        public void WriteLog(string message)
            // para cada plugin carregado em AddinList
            foreach (IMefLogger l in AddinList)
                // chama o método Log de cada plugin

        private string GetConFiguretionPath()
            /* Utilizar arquivos de conFigureção em DLL não é trivial. 
             * Para conseguir isso devemos seguire os seguintes passos:
             * - Adicionar o arquivo App.Config
             * - Mudar a propriedade BuildAction para Content
             * - Mudar a propriedade Copy to Output para Copy Always
             * - Alterar o nome de App.Config para MefLogger.dll.config
            // Abre o arquivo de conFigureção a partir da pasta onde a DLL está
            ConFiguretion PluginConfig = 
            // Recupera a seção appSettings
            AppSettingsSection PluginConfigAppSettings = 
            // retorna o valor da chave PluginPath
            return PluginConfigAppSettings.Settings["PluginPath"].Value; 

        public void Dispose()
            catalog = null;
            AddinList = null;

Now, modify the Logger class to the code below:

singusing System;

namespace MefLogger
    public class Logger : IDisposable
        // Vamos utilizar o padrão Singleton, 
        // para evitar carregar os plugins várias vezes.
        static Logger singletonLogger;
        PluginHandler h;
        private Logger()
            h = new PluginHandler();


        // Implementação do padrão Singleton
        public static Logger GetLogger()
            // se a instância da classe Logger não foi criada, então cria.
            if (singletonLogger == null)
                singletonLogger = new Logger();

            return singletonLogger;

        public void Log(string message)

        public void Dispose()
            h = null;
            singletonLogger = null;

Just to organize our solution, add a solution folder called Plugins. This folder is only logical, so if you look in Windows Explorer, you will not see this folder. We will use this folder to create the plug-in projects.



Figure 14 and Figure 15

Add into the Plugins folder a new Class Library project named TextLoggerPlugin. In this project, we'll create a plug-in to write the log into a text file. Add references to the MefLogger.Interface project and the System.ComponentModel.Composition.CodePlex.Dll MEF DLL. For plug-ins, this is the only required MEF DLL we need to reference.

usingusing System;
using System.ComponentModel.Composition;
using MefLogger.Interface;
using System.IO;

namespace TextLoggerPlugin
    public class TextLogger : IMefLogger
        public void Log(string message)
            // o arquivo será criado na pasta onde a aplicação SampleApp estará rodando.
            StreamWriter sw = File.AppendText("addinlog.txt");


Figure 16

Let's now create a new project in another plug-in, EventLoggerPlugin, which will record our log in the Windows Event Log.

usingusing System;
using System.ComponentModel.Composition;
using MefLogger.Interface;
using System.Diagnostics;

namespace EventLoggerPlugin
    public class EventLogger : IMefLogger
        string sSource = "";
        string sLog = "";
        string sEvent = "";

        public void Log(string message)
            sSource = "EventLoggerAddin";
            sLog = "Application";
            sEvent = message;

                if (!EventLog.SourceExists(sSource))
                    EventLog.CreateEventSource(sSource, sLog);

                EventLog.WriteEntry(sSource, sEvent);
                EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.Information, 234);
                // Ocorrerá erro caso não esteja rodando o programa com 
                // permissões de administrador

We now need to add a project to test our DLL. Let's add a new Console Application project named SampleApp.


Figure 17

To test our application, we'll just add a reference to the MefLogger project.


Figure 18

Make our SampeApp project the "StartUp Project"..


Figure 19

Modify the Program class to:

usingusing System;
using MefLogger;

namespace SampleApp
    class Program
        static void Main(string[] args)
            Logger _logger = Logger.GetLogger();
            _logger.Log("Log Teste 1");
            _logger.Log("Log Teste 2");
            _logger.Log("Log Teste 3");

Finally, our solution will look like this:


Figure 20

To run the application, we must create the folder defined in the MefLogger.dll.config file and copy the DLLs created in the plug-in projects there..

You are done..

You can modify this simple example and tailor it to meet your needs..


We have seen that MEF is very simple to use and greatly simplifies the development of pluggable systems..

Points of Interest

Here is the MEF site on CodePlex:


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Written By
Team Leader ActionPoint
Ireland Ireland
I'm Brazilian currently living in in Limerick, Ireland. I've been working with software development since 1996.

Comments and Discussions

QuestionExcellent article Pin
Mike Hankey18-Apr-18 4:40
mveMike Hankey18-Apr-18 4:40 
QuestionGood Article; Pin
David James Tuke24-Nov-16 19:10
professionalDavid James Tuke24-Nov-16 19:10 
AnswerRe: Good Article; Pin
fmsalmeida24-Nov-16 23:30
professionalfmsalmeida24-Nov-16 23:30 
QuestionGood Article But.. Pin
Ankit Sarkar25-Jul-14 20:37
Ankit Sarkar25-Jul-14 20:37 
AnswerRe: Good Article But.. Pin
fmsalmeida12-Nov-14 3:47
professionalfmsalmeida12-Nov-14 3:47 
QuestionStraightforward Pin
Matthew Cuba15-Nov-11 6:51
Matthew Cuba15-Nov-11 6:51 
AnswerRe: Straightforward Pin
fmsalmeida12-Nov-14 3:52
professionalfmsalmeida12-Nov-14 3:52 
GeneralI like it (doesn't matter if it's an article or not) Pin
meraydin23-Sep-11 7:16
meraydin23-Sep-11 7:16 
GeneralRe: I like it (doesn't matter if it's an article or not) Pin
fmsalmeida12-Nov-14 3:53
professionalfmsalmeida12-Nov-14 3:53 
GeneralNice Pin
andreasekeresova6-Aug-11 1:41
andreasekeresova6-Aug-11 1:41 
GeneralRe: Nice Pin
fmsalmeida8-Aug-11 3:35
professionalfmsalmeida8-Aug-11 3:35 
GeneralMy vote of 5 Pin
IAbstract10-Jul-11 3:45
IAbstract10-Jul-11 3:45 
GeneralRe: My vote of 5 Pin
fmsalmeida18-Jul-11 4:24
professionalfmsalmeida18-Jul-11 4:24 
QuestionMEF Logger Pin
Olinzer25-May-11 10:45
Olinzer25-May-11 10:45 
AnswerRe: MEF Logger Pin
fmsalmeida26-May-11 2:57
professionalfmsalmeida26-May-11 2:57 
QuestionWhy logging as an example? Pin
Stephen Brannan11-Apr-11 13:11
Stephen Brannan11-Apr-11 13:11 
AnswerRe: Why logging as an example? Pin
fmsalmeida12-Apr-11 1:29
professionalfmsalmeida12-Apr-11 1:29 
GeneralNot an Article Pin
#realJSOP5-Apr-11 5:50
professional#realJSOP5-Apr-11 5:50 
GeneralRe: Not an Article Pin
fmsalmeida5-Apr-11 7:46
professionalfmsalmeida5-Apr-11 7:46 
GeneralRe: Not an Article Pin
IAbstract10-Jul-11 3:49
IAbstract10-Jul-11 3:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.