Using MEF in .NET Core

Updated on 2018-11-08

Please read this post too

For those who don’t know, the Managed Extensibility Framework (MEF) is alive and well, and has been ported to .NET Core as System.Composition (source here). Not all of MEF has been ported, just MEF 2 (System.Composition), not MEF 1 (System.ComponentModel.Composition), meaning, we don’t have the catalogs, which included, among others, the ability to load types from assemblies in a directory.

Using MEF is straightforward, and this time I will not go into details. What I will show is how we can load types from files in a directory.

First, a sample usage might be:

var conventions = new ConventionBuilder();
conventions
    .ForTypesDerivedFrom<IPlugin>()
    .Export<IPlugin>()
    .Shared();
 
var assemblies = new[] { typeof(MyPlugin).Assembly };
 
var configuration = new ContainerConfiguration()
    .WithAssemblies(assemblies, conventions);
 
using (var container = configuration.CreateContainer())
{
    var plugins = container.GetExports<IPlugin>();
}

Notice that we have to build the assemblies list ourselves.

Now, let’s load assemblies from a folder instead. We’ll create an extension method for that purpose:

public static class ContainerConfigurationExtensions
{
    public static ContainerConfiguration WithAssembliesInPath(this ContainerConfiguration configuration, string path, SearchOption searchOption = SearchOption.TopDirectoryOnly)
    {
        return WithAssembliesInPath(configuration, path, null, searchOption);
    }
 
    public static ContainerConfiguration WithAssembliesInPath(this ContainerConfiguration configuration, string path, AttributedModelProvider conventions, SearchOption searchOption = SearchOption.TopDirectoryOnly)
    {
        var assemblies = Directory
            .GetFiles(path, "*.dll", searchOption)
            .Select(AssemblyLoadContext.Default.LoadFromAssemblyPath);
            
            
 
        configuration = configuration.WithAssemblies(assemblies, conventions);
 
        return configuration;
    }
}

The key here is the AssemblyLoadContext class: this is what allows us to obtain an assembly from a file stream or a byte array. Notice that in .NET Core, things have changed significantly, and now we don’t have AppDomain or Assembly.LoadFrom, and assemblies are now loaded by an assembly loader, in a similar way to what Java does with class loaders.

So, now you can change the code to:

var path = @"c:\some\path";
 
var configuration = new ContainerConfiguration()
    .WithAssembliesInPath(path, conventions);

It even works for loading assemblies in all sub-folders.

Maybe I’ll write another post on MEF in the near future, so stay tuned!

                             

15 Comments

  • Another great post, Ricardo. :) I, too, have been learning MEF2 (guess it's just "System.Composition" now) and have been pleased with it. It is definitely lightweight and easier to work with IMO than the full framework (first) version. I know this might seem unorthodox, but I do not like MEF and do not view it as a IoC container, but rather, a locatable plugin mechanism used to build core components like the IoC container. It provides an easy way to locate (through metadata or otherwise) those elements required to build the application, if that makes sense.

    Finally, I would also like to share my appreciation here in updating everyone about MEF and its new location. The CodePlex site is pretty much dead and the nuget packages haven't been updated in over a year, so one could very easily be given the impression that MEF is dead, when in fact it is very much alive. :)
    https://mef.codeplex.com/discussions/646327

    Anyways, I enjoy your posts. Continue the greatness! :)

  • Hello, I am author of DryIoc container lib. It has DryIoc.MefAttributedModel which does everything except catalogs.
    Dnx is supported too via DryIoc.Dnx.MefAttributedModel package.
    Thanks for interesting post, your WithAssembliesInPath is excellent candidate to add to the lib.
    Hope you don't mind.

  • Thanks Ricardo,

    I was looking for a way to load assemblies from a window universal class library when I came over your post but I am unable to get this working in my solution, I'm getting a "the name 'AssemblyLoadContext' does not exist in the current context"

    Maybe you could provide some guidance on what I need to get this to work?
    My current target version is "10.0;Build 10586" and I am using "Microsoft.NETCore.UniversalWindowsPlatform 5.0.0"

  • Hi, guys! Thanks!
    Jan: You are building a shared class library, from the Windows section, where I am talking about a shared class library, from the Web section! :-)
    AssemblyLoadContext is defined in Nuget package System.Runtime.Loader.

  • dadhi: sure, my code is yours! ;-)

  • "we don’t have the catalogs, which included, among others, the ability to load types from assemblies in a directory."

    Literally the only reason to use MEF. Completely asinine that this isn't in .NET Core. I'm really starting to get angry at how hamgstringed .NET Core is. It is absolutely not ready but Microsoft forced it out the door way too early.

    I see it's easy to add support for it, just like you did with several lines of code. Absolutely inexcusable it's not baked in first party support.

  • Hi, Chris!
    I understand you... you can request that support for MEF 1 be added through this link: http://github.com/dotnet/corefx/issues/new.

  • Hi,

    I'm new with MEF and started playing with ASP.NET Core. Is there a sample (sort of starter kit) application using MEF with ASP.NET Core MVC that i can start with?

  • Hi, Richard!
    Not that I know of... why don't you start one yourself? Let me know if you need any help.

  • I'm trying to use this (and VERY new to .Net core) trying to port some code we have. I'm getting:
    error: Package Microsoft.Composition 1.0.30 is not compatible with netstandard1.5 (.NETStandard,Version=v1.5). Package Microsoft.Composition 1.0.30 supports: portable-net45+win8+wp8+wpa81 (.NETPortable,Version=v0.0,Profile=Profile259)

    Which I believe means that its only available while targeting the full 4.5 framework? I realize that this is very likely a NOOB question but how can this be labeled as being ported to .Net Core if it still requires the entire 4.5 Framework?

  • Ben:
    No... That is related to changes in RC2, I think. I'll have a look when I'm near a PC.

  • Seriously, does this still stand? There's been huge amount of changes in .NET Core for RTM. Please revise your article otherwise it's pretty worthless.

  • Hi, brgrz: what do you mean? All of this is working with .NET Core 2.1 and .NET Standard 2.0...

  • I get frustrated with code samples which don't tell you which namespaces you need to import. For the benefit of other people who come across this, here they are:

    ```
    using System;
    using System.Composition;
    using System.Composition.Convention;
    using System.Composition.Hosting;
    using System.IO;
    using System.Linq;
    using System.Runtime.Loader;
    ```

  • Thanks, Matt! You are right, my bad!

Add a Comment

As it will appear on the website

Not displayed

Your website