Hlavní menu

Nástroje

UvodDoKomponent / MEFExample

View (print) - Edit page | Recent changes - Page history

Updated 28 January 2015, 15:05 by Eduard Chromik

UvodDoKomponent.MEFExample History

Hide minor edits - Show changes to output

28 January 2015, 15:05 by Eduard Chromik -
Added lines 14-15:
-> %width=500px%Attach:mef.png
28 January 2015, 13:47 by Eduard Chromik -
Changed lines 1-2 from:
Original site of this example [[more -> http://www.codeproject.com/Articles/188054/An-Introduction-to-Managed-Extensibility-Framework]].
to:
Original site of this [[example -> http://www.codeproject.com/Articles/188054/An-Introduction-to-Managed-Extensibility-Framework]].
28 January 2015, 13:47 by Eduard Chromik -
Changed line 362 from:
So in this first part of the MEF series, we learnt about the basics of MEF, its applicability, importance of *Export*, *Import*, *ImportMany* attributes, *Assembly* and *Directory catalogs*, *dynamic component discovery*, etc. But there is a lot more stuff to learn about MEF.
to:
So in this first part of the MEF series, we learnt about the basics of MEF, its applicability, importance of *Export*, *Import*, *[=ImportMany=]* attributes, *Assembly* and *Directory catalogs*, *dynamic component discovery*, etc. But there is a lot more stuff to learn about MEF ;)
28 January 2015, 13:36 by Eduard Chromik -
Changed lines 155-156 from:
Well by this time, we have learnt something about MEF, how it works and also we have successfully added one component in our application. Now let us enhance our application so that it can handle all the other components like Subtraction, Multiplication and Division.
to:
Well by this time, we have learnt something about MEF, how it works and also we have successfully added one component in our application. Now let us enhance our application so that it can handle all the other components like *Subtraction*, *Multiplication* and *Division*.
28 January 2015, 13:32 by Eduard Chromik -
Added lines 43-46:
First of all, we need to add reference to *[=System.ComponentModel.Composition=]* assembly into the project.

Also a reference of the ''[=CalculatorContract.dll=]'' is added.
Deleted lines 67-70:
First of all, we need to add reference to *[=System.ComponentModel.Composition=]* assembly into the project.

Also a reference of the ''[=CalculatorContract.dll=]'' is added.
28 January 2015, 13:29 by Eduard Chromik -
Changed lines 15-16 from:
Let us create a simple calculator for the demonstration. Our sample application will have four basic arithmetic operations, viz. Add, Subtract, Multiply and Division. With that in mind, let us create our project structure as under:
to:
Let us create a simple calculator for the demonstration. Our sample application will have four basic arithmetic operations, viz. *Add*, *Subtract*, *Multiply* and *Division*. With that in mind, let us create our project structure as under:
28 January 2015, 13:28 by Eduard Chromik -
Changed lines 4-5 from:
Let's repeat terminologie again :)
to:
Let's repeat terminology again :)
28 January 2015, 13:27 by Eduard Chromik -
Added lines 1-2:
Original site of this example [[more -> http://www.codeproject.com/Articles/188054/An-Introduction-to-Managed-Extensibility-Framework]].
Added lines 17-18:
%width=300px%Attach:mefexample1.jpg
Added lines 152-153:
%width=400px%Attach:mefexample3.jpg
Added lines 159-160:
%width=300px%Attach:mefexample4.jpg
Changed lines 259-260 from:
5.jpg
to:
%width=900px%Attach:mefexample5.jpg
Changed lines 263-264 from:
Correspondingly, the ''GetResult'' function has been changed a little bit. It now accepts a third parameter which specifies the operation type and based on that, the Exported parts will be invoked.
to:
Correspondingly, the ''[=GetResult=]'' function has been changed a little bit. It now accepts a third parameter which specifies the operation type and based on that, the Exported parts will be invoked.
Changed lines 276-277 from:
6.jpg
to:
%width=400px%Attach:mefexample6.jpg
Changed lines 287-288 from:
7.jpg
to:
%width=300px%Attach:mefexample7.jpg
Changed lines 291-292 from:
We have added only two DLLs there, viz., Add and Subtraction and removed the ''Add.cs'' and ''Subtract.cs'' files from *[=CompositionHelper project=]*.
to:
We have added only two [=DLLs=] there, viz., Add and Subtraction and removed the ''Add.cs'' and ''Subtract.cs'' files from *[=CompositionHelper project=]*.
Changed lines 340-345 from:
8.jpg

And the *AssemblyCatalog has two parts (Divide and Multiply)*:

9.jpg
to:
%width=900px%Attach:mefexample8.jpg

And the *[=AssemblyCatalog=] has two parts (Divide and Multiply)*:

%width=900px%Attach:mefexample9.jpg
Changed lines 350-351 from:
10.jpg
to:
%width=400px%Attach:mefexample10.jpg
Changed lines 355-360 from:
MEF breaks the tightly coupled dependencies across the application but respects the type checking of the loosely coupled parts.
Applications can be extended.
Components can be added at runtime.
Dynamic discovery of the components.
Great piece of reusability.
to:
*MEF breaks the tightly coupled dependencies across the application but respects the type checking of the loosely coupled parts.
*Applications can be extended.
*Components can be added at runtime.
*Dynamic discovery of the components.
*Great piece of reusability.
Changed lines 362-367 from:
So in this first part of the MEF series, we learnt about the basics of MEF, its applicability, importance of Export, Import, ImportMany attributes, Assembly and Directory catalogs, dynamic component discovery, etc. But there is a lot more stuff to learn about MEF. In the next part or subsequent parts, we will look into some attributes, catalogs, more practical examples with different kind of applications using MEF. Thanks for reading.


Longer version of this example [[more -> http://www.codeproject.com/Articles/188054/An-Introduction-to-Managed-Extensibility-Framework]].

to:
So in this first part of the MEF series, we learnt about the basics of MEF, its applicability, importance of *Export*, *Import*, *ImportMany* attributes, *Assembly* and *Directory catalogs*, *dynamic component discovery*, etc. But there is a lot more stuff to learn about MEF.
28 January 2015, 13:09 by Eduard Chromik -
Changed lines 1-61 from:
h2. Evil Wizard Example

This is a very simple example, nevertheless eligible to understand the basis of MEF.

%width=150px%Attach:Evil-wizard.png

h3. Step 1. Add MEF to our Visual Studio solution

Adding MEF to your VS solution could not be easier. MEF is part of the .NET 4 Framework, so you can just Add a Reference as you would do with any .NET assembly: Into class *[=EvilWizard=]* add a reference to *[=System.ComponentModel.Composition=]*

h3. Step 2. Define the [=EvilWizard=] as an Import Part
The next step is to tell MEF that our *[=EvilWizard=]* class is a ''part''. Furthermore, it is an ''import'' that is going to consume a series of services, that is, is going to use a ''''Hat service'''', a ''''Robe service'''' and a collection of ''''[=ISpell services=]''''.

In order to do this, we will use MEF attribute based programming model, and we will decorate the *[=EvilWizard=]* components with the *[Import]* and * [=[ImportMany]=]* attributes as shown below:

%width=600px%Attach:theevilwizard.png

If you have not guessed it yet, we use the *[Import]* attribute to represent a single service and *[=[ImportMany]=]* to represent a multiplicity of services. These attributes also represent ''default contracts'', but we will deal with contracts in upcoming articles so do not worry for now.

h3. Step 3. Define the Hat, Robe and Spells as Export Parts

We continue by defining the Hat, Robe and Spells as parts that provide services:

%width=600px%Attach:wizardarsenal.PNG

Notice how we used the *[Export]* attribute to decorate a class that provides a service and the *[=[InheritedExport]=]* attribute to decorate an interface and ensure that ''anything that implements that interface'' becomes a part.

h3. Step 4. Discover The Parts and Setup The Container

Now that we have all the parts of our system ready, the next step consists in instantiating a catalog that will discover all parts within our assembly:

%width=600px%Attach:setcatalog.PNG

And passing this catalog to our MEF container so it will know which parts are available in our system:

%width=600px%Attach:setcontainer.PNG

h3. Step 5. Let the magic happen

Finally, composing our evil wizard with other parts (hat, robe and spells) is as easy as:

%width=600px%Attach:tadaaaa.PNG

And there we have our evil wizard kicking ass:

%width=600px%Attach:tadaresult.png

h3. Step 6. Extending our RPG

Extending our RPG at this moment (for instance, adding new spells) would be as easy as adding new parts in a new assembly. We can use a *[=[DirectoryCatalog ]=]* instead of a *[=[AssemblyCatalog ]=]* to point to a path where we can drop all these new assemblies packed with new spells of destruction and mayhem.

Author of this example
[[(original site)-> http://www.barbarianmeetscoding.com/blog/2012/08/14/barbarian-meets-mef-managed-extensiblity-framework/]] [[Jaime González García-> http://www.barbarianmeetscoding.com/about/]].

As a final note, you can find the code sample at [[GitHub-> https://github.com/Vintharas/Barbarian-Meets-MEF]].





to:
h2. MEF Related Terminologies
Let's repeat terminologie again :)

* *Part*: A Part is an object (e.g. a class, a method or a property) that can be imported or exported to the application.
* *Catalog*: An object that helps in discovering the available composable parts from an assembly or a directory.
* *Contract*: The import and exported parts need to talk between themselves via some contract (e.g. an Interface or predefined data type like string)
* *Import Attribute*: It defines the need that a part has. It is applicable only for single Export Attribute.
* *ImportMany Attribute* : It is similar to Import Attribute but supports for multiple Export Attributes.
* *Export Attribute* : The import attribute creates the needs. The Export attribute fulfills that. It exposes those parts that will participate in the composition.
* *Compose*: In MEF jargon, Compose is that area where the Exported parts will be assembled with the imported ones.

h2. A Simple Working Example with Only a Single Export Part in Current Assembly
Let us create a simple calculator for the demonstration. Our sample application will have four basic arithmetic operations, viz. Add, Subtract, Multiply and Division. With that in mind, let us create our project structure as under:

The solution file *[=CalculatorDemoUsingMEF=]* has three projects:

* ''[=CalculatorContract=]''
* ''[=CalculatorUI=]''
* ''[=CompositionHelper=]''

h3. a) Description of [@CalculatorContract@] Project

Here, we basically define the contract or interface that the concrete components of Calculator say ''Add'', ''Subtract'', etc. must implement. The *[=ICalculator=]* interface is very simple as described below:

[@
namespace CalculatorContract
{
public interface ICalculator
{
int GetNumber(int num1, int num2);
}
}
@]

h3. b) Description of [@CompositionHelper@] Project

In this project, we will create the various components needed for the Calculator like Addition, subtraction, etc. The ''Add.cs'' file is the component used for Addition operation.

Let us look into the ''Add.cs'' file:

[@
using System.ComponentModel.Composition;
using CalculatorContract;

namespace CompositionHelper
{
[Export(typeof(ICalculator))]
public class Add:ICalculator
{
#region Interface members
public int GetNumber(int num1, int num2)
{
return num1 + num2;
}
#endregion
}
}
@]

First of all, we need to add reference to *[=System.ComponentModel.Composition=]* assembly into the project.

Also a reference of the ''[=CalculatorContract.dll=]'' is added.

The class is decorated by the *Export* attribute which indicates that this class will be exported to the composition model and it respects only of the ''[=ICalculator=]'' contract/ interface type.

The ''[=CalcliComposition.cs=]'' file is the part where the Composition happens.

[@
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using CalculatorContract;

namespace CompositionHelper
{
public class CalciCompositionHelper
{
[Import(typeof(ICalculator))]
public ICalculator CalciPlugin { get; set; }

/// <summary>
/// Assembles the calculator components
/// </summary>
public void AssembleCalculatorComponents()
{
try
{
//Step 1: Initializes a new instance of the
// System.ComponentModel.Composition.Hosting.AssemblyCatalog
// class with the current executing assembly.
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());

//Step 2: The assemblies obtained in step 1 are added to the
//CompositionContainer
var container = new CompositionContainer(catalog);

//Step 3: Composable parts are created here i.e.
//the Import and Export components
// assembles here
container.ComposeParts(this);
}
catch (Exception ex)
{
throw ex;
}
}

/// <summary>
/// Sends the result back to the client
/// </summary>
/// <param name="num1"></param>
/// <param name="num2"></param>
/// <returns></returns>
public int GetResult(int num1, int num2)
{
return CalciPlugin.GetNumber(num1, num2);
}
}
}
@]

The *[=AssembleCalculatorComponent=]* function needs some attention. In this function, we are first looking for the catalogs from where the parts are coming. Once identified, the catalogs are held in a container and lastly the parts are composed.

h3. c) Description of [@CalculatorUI@] Project

In this project, the UI is displayed. It adds a reference to the ''[=CalculatorComponentComposition.dll=]'' .

Let us look into the Add button click event code:

[@
objCompHelper = new CalciCompositionHelper();

//Assembles the calculator components that will participate in composition
objCompHelper.AssembleCalculatorComponents();

//Gets the result
var result = objCompHelper.GetResult(Convert.ToInt32(txtFirstNumber.Text), Convert.ToInt32(txtSecondNumber.Text));

//Display the result
txtResult.Text = result.ToString();
@]

First, we are assembling the calculator components that will participate in the composition. Then calling the Addition component for the needed operation.

The final output is as shown below:

h2. A Simple Working Example with Multiple Export Part in Current Assembly
Well by this time, we have learnt something about MEF, how it works and also we have successfully added one component in our application. Now let us enhance our application so that it can handle all the other components like Subtraction, Multiplication and Division.

So let us add the various component parts in the application. The project structure will now become:

As can be figured out, there is not much change expected, we have added three new parts which are highlighted.

Let us now visit the ''Add.cs'' file again:

[@
using System.ComponentModel.Composition;
using CalculatorContract;

namespace CompositionHelper
{
[Export(typeof(ICalculator))]
[ExportMetadata("CalciMetaData", "Add")]
public class Add:ICalculator
{
#region Interface members
public int GetNumber(int num1, int num2)
{
return num1 + num2;
}
#endregion
}
}
@]

We have found that there is a new attribute call *[=ExportMetadata=]*. This new attribute will help us to determine at runtime which implementation to use. It is a form of name value pair. The first parameter of this attribute is the name of the metadata. It's type is *string*. The next one which is an object holds the value of the metadata. It is by which we will decide which operation will be called. A similar implementation has been followed for the rest of the Exportable parts.

Next, let us have a look at the ''[=CalciCompositionHelper.cs=]'' file:

[@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using CalculatorContract;

namespace CompositionHelper
{
public class CalciCompositionHelper
{
[ImportMany]
public System.Lazy<ICalculator,
IDictionary<string, object>>[] CalciPlugins { get; set; }

/// <summary>
/// Assembles the calculator components
/// </summary>
public void AssembleCalculatorComponents()
{
try
{
//Step 1: Initializes a new instance of the
// System.ComponentModel.Composition.Hosting.AssemblyCatalog
// class with the current executing assembly.
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());

//Step 2: The assemblies obtained in step 1 are added to the
//CompositionContainer
var container = new CompositionContainer(catalog);

//Step 3: Composable parts are created here i.e.
//the Import and Export components
// assemble here
container.ComposeParts(this);
}
catch (Exception ex)
{
throw ex;
}
}

/// <summary>
/// Sends the result back to the client
/// </summary>
/// <param name="num1"></param>
/// <param name="num2"></param>
/// <returns></returns>
public int GetResult(int num1, int num2, string operationType)
{
int result = 0;
foreach (var CalciPlugin in CalciPlugins)
{
if ((string)CalciPlugin.Metadata["CalciMetaData"] == operationType)
{
result = CalciPlugin.Value.GetNumber(num1, num2);
break;
}
}
return result;
}
}
}
@]

The first change that we observe is that now we have *[=ImportMany=]* attribute instead of *[=Import=]* attribute. The *[=Import=]* attribute is filled always by a single *[=Export=]* attribute while *[=ImportMany=]* attribute can be filled by any number of *[=Export=]* attribute.

When we run the application, we can figure out the various parts that participate in composition.

5.jpg

One more noticeable point is the *[=Lazy<T>=]* class basically defers the creation of large objects till the time we need that. In the sample code, the second parameter is the metadata that will be handled by MEF at runtime.

Correspondingly, the ''GetResult'' function has been changed a little bit. It now accepts a third parameter which specifies the operation type and based on that, the Exported parts will be invoked.

Finally, on the Concrete operations click event, we are passing the Operation types as:

[@
private void btnAdd_Click(object sender, RoutedEventArgs e)
{
DoCalciOperation("Add");
}
@]

Once we run the application, the output will be as under (output shown only for multiplication operation):

6.jpg

Hope this is equally helpful as the previous one. In the next part, we will explore some new catalog types and more features of MEF.

h2. A Simple Working Example with Multiple Export Part using Aggregate Catalog and Directory Catalog
Until now, we have seen that our Composable parts were residing in the current assembly. But what if they reside in different assemblies or in different location?

Well, we have a solution for this too. We will see how Aggregate and Directory Catalog help us in such situations.

Let us see the project structure now.

7.jpg

We can figure out that one new project has been added to the solution file, i.e., Export Components. In that, we have a folder called Components where our export parts in the form of assemblies are stored (.dll files).

We have added only two DLLs there, viz., Add and Subtraction and removed the ''Add.cs'' and ''Subtract.cs'' files from *[=CompositionHelper project=]*.

Now let us visit the *[=AssembleCalculatorComponent=]* function again.

[@
public void AssembleCalculatorComponents()
{
try
{
//Creating an instance of aggregate catalog. It aggregates other catalogs
var aggregateCatalog = new AggregateCatalog();

//Build the directory path where the parts will be available
var directoryPath =
string.Concat(Path.GetDirectoryName
(Assembly.GetExecutingAssembly().Location)
.Split('\\').Reverse().Skip(3).Reverse().Aggregate
((a, b) => a + "\\" + b)
, "\\", "ExportComponents\\Components");

//Load parts from the available DLLs in the specified path
//using the directory catalog
var directoryCatalog = new DirectoryCatalog(directoryPath, "*.dll");

//Load parts from the current assembly if available
var asmCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());

//Add to the aggregate catalog
aggregateCatalog.Catalogs.Add(directoryCatalog);
aggregateCatalog.Catalogs.Add(asmCatalog);

//Crete the composition container
var container = new CompositionContainer(aggregateCatalog);

// Composable parts are created here i.e.
// the Import and Export components assembles here
container.ComposeParts(this);
}
catch (Exception ex)
{
throw ex;
}
}
@]

As can be seen, initially we have created an *[=AggregateCatalog=]* that will aggregate other catalogs. Then we are picking up the Exportable Components from the Components directory.

If we run the application, we can find that the *Directory Catalog has two parts (Add and Subtract)*.

8.jpg

And the *AssemblyCatalog has two parts (Divide and Multiply)*:

9.jpg

After the parts have been discovered, they are then added to the *[=AggragateCatalog=]* which is being added to the *[=CompositionContainer=]*. And finally, the parts gets composed.

Running the application brings out the desired output (output shown only for Addition operation).

10.jpg

h2. Advantages
MEF has many advantages as we have seen by this time. However, some of the common advantages are listed below:

MEF breaks the tightly coupled dependencies across the application but respects the type checking of the loosely coupled parts.
Applications can be extended.
Components can be added at runtime.
Dynamic discovery of the components.
Great piece of reusability.

h2. Conclusion
So in this first part of the MEF series, we learnt about the basics of MEF, its applicability, importance of Export, Import, ImportMany attributes, Assembly and Directory catalogs, dynamic component discovery, etc. But there is a lot more stuff to learn about MEF. In the next part or subsequent parts, we will look into some attributes, catalogs, more practical examples with different kind of applications using MEF. Thanks for reading.

Changed lines 359-361 from:
Another "Hello World!" [[example-> http://www.codeproject.com/Articles/56635/Managed-Extensibility-Framework]]

[[10 reasons why to use MEF -> http://csharperimage.jeremylikness.com/2010/04/ten-reasons-to-use-managed.html]]
to:
28 January 2015, 11:21 by Eduard Chromik -
Changed lines 50-58 from:
Extending our RPG at this moment (for instance, adding new spells) would be as easy as adding new parts in a new assembly. We can use a DirectoryCatalog instead of a AssemblyCatalog to point to a path where we can drop all these new assemblies packed with new spells of destruction and mayhem.

As a final note, you can find the code sample at GitHub.

Original example site here.



to:
Extending our RPG at this moment (for instance, adding new spells) would be as easy as adding new parts in a new assembly. We can use a *[=[DirectoryCatalog ]=]* instead of a *[=[AssemblyCatalog ]=]* to point to a path where we can drop all these new assemblies packed with new spells of destruction and mayhem.

Author of this example
[[(original site)-> http://www.barbarianmeetscoding.com/blog/2012/08/14/barbarian-meets-mef-managed-extensiblity-framework/]] [[Jaime González García-> http://www.barbarianmeetscoding.com/about/]].

As a final note, you can find the code sample at [[GitHub-> https://github.com/Vintharas/Barbarian-Meets-MEF]].





28 January 2015, 11:14 by Eduard Chromik -
Changed lines 5-6 from:
Attach:Evil-wizard.png
to:
%width=150px%Attach:Evil-wizard.png
Changed lines 16-19 from:
If you have not guessed it yet, we use the *[Import]* attribute to represent a single service and *[=[ImportMany]=]* to represent a multiplicity of services. These attributes also represent default contracts, but we will deal with contracts in upcoming articles so do not worry for now.

In order to do this, we will use MEF attribute based programming model, and we will decorate the *[=EvilWizard=]* components with the *[Import]* and *[=[ImportMany]=]* attributes as shown below:
to:
%width=600px%Attach:theevilwizard.png

If you have not guessed it yet, we use the *[Import]* attribute to represent a single service and *[=[ImportMany]=]* to represent a multiplicity of services. These attributes also represent ''default contracts'', but we will deal with contracts in upcoming articles so do not worry for now.
Changed lines 24-25 from:
Notice how we used the [Export] attribute to decorate a class that provides a service and the [InheritedExport] attribute to decorate an interface and ensure that anything that implements that interface becomes a part.
to:
%width=600px%Attach:wizardarsenal.PNG

Notice how we used the *[Export]* attribute to decorate a class that provides a service and the *[=[InheritedExport]=]* attribute to decorate an interface and ensure that ''anything that implements that interface'' becomes a part.
Added lines 32-33:
%width=600px%Attach:setcatalog.PNG
Added lines 36-37:
%width=600px%Attach:setcontainer.PNG
Added lines 42-43:
%width=600px%Attach:tadaaaa.PNG
Added lines 46-47:
%width=600px%Attach:tadaresult.png
28 January 2015, 10:54 by Eduard Chromik -
Added lines 2-6:

This is a very simple example, nevertheless eligible to understand the basis of MEF.

Attach:Evil-wizard.png
Changed lines 16-19 from:
If you have not guessed it yet, we use the *[Import]* attribute to represent a single service and * [=[ImportMany]=]* to represent a multiplicity of services. These attributes also represent default contracts, but we will deal with contracts in upcoming articles so do not worry for now.

In order to do this, we will use MEF attribute based programming model, and we will decorate the EvilWizard components with the [Import] and [ImportMany] attributes as shown below:
to:
If you have not guessed it yet, we use the *[Import]* attribute to represent a single service and *[=[ImportMany]=]* to represent a multiplicity of services. These attributes also represent default contracts, but we will deal with contracts in upcoming articles so do not worry for now.

In order to do this, we will use MEF attribute based programming model, and we will decorate the *[=EvilWizard=]* components with the *[Import]* and *[=[ImportMany]=]* attributes as shown below:
28 January 2015, 10:47 by Eduard Chromik -
Added lines 1-43:
h2. Evil Wizard Example
h3. Step 1. Add MEF to our Visual Studio solution

Adding MEF to your VS solution could not be easier. MEF is part of the .NET 4 Framework, so you can just Add a Reference as you would do with any .NET assembly: Into class *[=EvilWizard=]* add a reference to *[=System.ComponentModel.Composition=]*

h3. Step 2. Define the [=EvilWizard=] as an Import Part
The next step is to tell MEF that our *[=EvilWizard=]* class is a ''part''. Furthermore, it is an ''import'' that is going to consume a series of services, that is, is going to use a ''''Hat service'''', a ''''Robe service'''' and a collection of ''''[=ISpell services=]''''.

In order to do this, we will use MEF attribute based programming model, and we will decorate the *[=EvilWizard=]* components with the *[Import]* and * [=[ImportMany]=]* attributes as shown below:

If you have not guessed it yet, we use the *[Import]* attribute to represent a single service and * [=[ImportMany]=]* to represent a multiplicity of services. These attributes also represent default contracts, but we will deal with contracts in upcoming articles so do not worry for now.

In order to do this, we will use MEF attribute based programming model, and we will decorate the EvilWizard components with the [Import] and [ImportMany] attributes as shown below:

h3. Step 3. Define the Hat, Robe and Spells as Export Parts

We continue by defining the Hat, Robe and Spells as parts that provide services:

Notice how we used the [Export] attribute to decorate a class that provides a service and the [InheritedExport] attribute to decorate an interface and ensure that anything that implements that interface becomes a part.

h3. Step 4. Discover The Parts and Setup The Container

Now that we have all the parts of our system ready, the next step consists in instantiating a catalog that will discover all parts within our assembly:

And passing this catalog to our MEF container so it will know which parts are available in our system:

h3. Step 5. Let the magic happen

Finally, composing our evil wizard with other parts (hat, robe and spells) is as easy as:

And there we have our evil wizard kicking ass:

h3. Step 6. Extending our RPG

Extending our RPG at this moment (for instance, adding new spells) would be as easy as adding new parts in a new assembly. We can use a DirectoryCatalog instead of a AssemblyCatalog to point to a path where we can drop all these new assemblies packed with new spells of destruction and mayhem.

As a final note, you can find the code sample at GitHub.

Original example site here.



04 January 2015, 22:06 by Eduard Chromik -
Added lines 1-5:
Longer version of this example [[more -> http://www.codeproject.com/Articles/188054/An-Introduction-to-Managed-Extensibility-Framework]].

Another "Hello World!" [[example-> http://www.codeproject.com/Articles/56635/Managed-Extensibility-Framework]]

[[10 reasons why to use MEF -> http://csharperimage.jeremylikness.com/2010/04/ten-reasons-to-use-managed.html]]