1

I'm trying to port some code from targeting the .NET Framework to .NET Core, and part of this involves switching from MEF1 to MEF2. There doesn't seem to be a great deal of documentation on using MEF in .NET Core, and I can't find any examples demonstrating how to filter out parts as was possible with MEF1.

In my original code (using MEF1), I wanted to load all parts exported from a set of assemblies except for MockCommunicationService. I implemented this as follows:

// Filter out invalid exports.
Func<ComposablePartDefinition, bool> partFilter = it => !it.ToString().Contains(nameof(MockCommunicationService));

var assemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var catalog = new DirectoryCatalog(assemblyPath).Filter(partFilter);
var container = new CompositionContainer(catalog);

What would the equivalent to this be in MEF2? I imagine that it probably involves using ConventionBuilder, but I don't know if there's a way to define a convention along the lines of "permit everything except x".

Ideally, something like this would be great:

var conventions = new ConventionBuilder();
conventions.ForType<MockCommunicationService>().SuppressExports();

var configuration = new ContainerConfiguration()
    .WithAssemblies(assemblies, conventions);
Tagc
  • 8,736
  • 7
  • 61
  • 114

1 Answers1

1

It's hardly an optimal solution, but this is the workaround I've used for the time being.

Looking at the source for ContainerConfiguration, I see that WithAssemblies is defined as:

public ContainerConfiguration WithAssemblies(IEnumerable<Assembly> assemblies, AttributedModelProvider conventions)
{
    if (assemblies == null) throw new ArgumentNullException(nameof(assemblies));
    return WithParts(assemblies.SelectMany(a => a.DefinedTypes.Select(dt => dt.AsType())), conventions);
}

So instead of using WithAssemblies, I use WithParts as follows:

// Filter out invalid exports.
Predicate<Type> filterParts = part => !part.Equals(typeof(MockCommunicationService));

var parts = from name in DependencyContext.Default.GetDefaultAssemblyNames()
            where name.Name.StartsWith("<<Company>>")
            let assembly = Assembly.Load(name)
            from definedType in assembly.DefinedTypes
            let part = definedType.AsType()
            where filterParts(part)
            select part;

var configuration = new ContainerConfiguration()
    .WithParts(parts);

return configuration.CreateContainer();

Again, this seems more like a hacky workaround than a proper way to go about it, so I'm not going to accept this answer. If no other answers get posted this may be useful to others, though.

Tagc
  • 8,736
  • 7
  • 61
  • 114