Migrating from MEF1 to MEF2
Tags: mef1, mef2, csharp, netstandard
Published: 2018-08-17 03:21:57

---
title: Migrating from MEF1 to MEF2
published: true
tags: mef1,mef2,csharp,netstandard
canonical_url: 
---

_N.B. I originally wrote the bulk of this text 2017/12/28 and am posting it now since it was useful at the time._

While moving part of our codebase to [.Net Standard 2.0 so everything runs atop .Net Core](https://msdn.microsoft.com/en-us/magazine/mt842506.aspx), we had to deal with moving from [MEF1](https://docs.microsoft.com/en-us/dotnet/framework/mef/) (which is not in .Net Core) to [MEF2](https://www.nuget.org/packages/microsoft.composition) (which is).

[This blog post](http://blog.softwarepotential.com/porting-to-net-standard-2-0-part-2-porting-mef-1-0-to-mef-2-0-on-net-core/) got me started, or at least validated that the move was possible, rather. But, it didn’t really have the details matching our usage.

## Packages

The simplest changes involved is moving from .NetFramework:

```csharp
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;

```

To packages available from nuget:

```csharp
using System.Composition;
using System.Composition.Hosting;

```

It’s worth mentioning that `System.ComponentModel.DataAnnotations` can be used as-is, but the package still has to be downloaded from nuget.

## Code Changes

It seems that several other people are dealing with similar issues, because there were a few StackOverflow questions that were helpful:

- [https://stackoverflow.com/questions/41784393/how-to-emit-a-type-in-net-core](https://stackoverflow.com/questions/41784393/how-to-emit-a-type-in-net-core)
- [https://stackoverflow.com/questions/24935261/mef2-how-to-get-metadata-from-compositionhost-export-with-convention-based-impor](https://stackoverflow.com/questions/24935261/mef2-how-to-get-metadata-from-compositionhost-export-with-convention-based-impor)
- [https://stackoverflow.com/questions/13914256/strongly-typed-metadata-in-mef2-system-composition](https://stackoverflow.com/questions/13914256/strongly-typed-metadata-in-mef2-system-composition)
- [https://stackoverflow.com/questions/10988447/mef-getexportst-tmetadataview-returning-nothing-with-allowmultiple-true](https://stackoverflow.com/questions/10988447/mef-getexportst-tmetadataview-returning-nothing-with-allowmultiple-true)

We had a DynamicLinq.cs:

```csharp
AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);  
// SNIP
Type result = tb.CreateType();

```

That needed to get changed to:

```csharp
AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);  
// SNIP
Type result = tb.CreateTypeInfo();

```

A more complicated case is how we load the assemblies, first via MEF1:

```csharp
CompositionContainer container;  
[ImportMany(typeof(IWorker))]  
IEnumerable<Lazy<IWorker, IWorkerMetadata>> workerPlugins { get; set; }  
public void Init(string path)  
{  
  var files = Directory.EnumerateFiles(path, "*Service.dll", SearchOption.AllDirectories);  
  var catalog = new AggregateCatalog();  
  foreach (var file in files)  
  {  
    try  
    {  
      var asmCat = new AssemblyCatalog(file);  
      if (asmCat.Parts.ToList().Count > 0)  
        catalog.Catalogs.Add(asmCat);  
    }  
    catch (ReflectionTypeLoadException)  
    {  
    }  
    catch (BadImageFormatException)  
    {  
    }  
  }  
  container = new CompositionContainer(catalog);  
  container.ComposeParts(this);  
}  

```

And then with MEF2:

```csharp
CompositionHost container;  
public void Init(string path)  
{  
  var configuration = new ContainerConfiguration();  
  var files = Directory.EnumerateFiles(path, "*Service.dll", SearchOption.AllDirectories);  
  foreach (var file in files)  
  {  
    try  
    {  
       var asm = Assembly.LoadFrom(file);  
       configuration.WithAssembly(asm);  
    }  
    catch (ReflectionTypeLoadException)  
    {  
    }  
    catch (BadImageFormatException)  
    {  
    }  
  }  
  container = configuration.CreateContainer();  
}  

```

Both of these are simplified but should still be illustrative.

## Side-by-Side

In the original post I decribed here how we were loading both MEF1 and MEF2 assemblies in the same application.

I thought that MEF1 was used with .Net Framework assemblies and MEF2 with .Net Standard. Anything that was incompatible with .Net Standard had to go in a Framework assembly- and therefore MEF1. I since realized MEF2 could load assemblies targetting either framework and have removed all our MEF1 code.

In any case, you can load both in an application. Which might be useful if you have a number of existing/legacy modules.

## Todo

One of the tasks that’s been in my backlog for a while is re-visiting how we handle MEF2. In particular:

- Verifying our signed assemblies
- Checking meta-data before loading/initializing

When I do it will certainly result in a follow-up post.