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!