how can i mimic the inheritedexport feature in mef2

272 Views Asked by At

I'm using MEF2 and read a couple of tutorials on MEF 1 and MEF 2.

The best one i've found so far is this one: http://www.codeproject.com/Articles/366583/MEF-Preview-Beginners-Guide

While i did get exports to work just fine, i really want to do it using the attribute style, because using InheritedExport on interfaces just seems so much more convenient than going back and forth between the interface i'm declaring and my container convention.

This is a snippet of my code:

var convention = new ConventionBuilder();
convention.ForTypesDerivedFrom<IMainTabsControl>().Export<IMainTabsControl>();
convention.ForTypesDerivedFrom<IShell>().Export<IShell>().Shared();
// here is where i am struggeling.
convention.ForTypesMatching(type => typeof (ICrawlerKeyProvider).IsAssignableFrom(type)).Export(builder => builder.AsContractType(typeof(bool)));

var configuration = new ContainerConfiguration();
MefContainer = configuration.WithAssemblies(new []{ Assembly.GetExecutingAssembly(),  }, convention).CreateContainer();

So there's 3 Options really:

  • i can't find the renamed feature in MEF 2
  • i'm not using the right method
  • i'm missing something obvious

As far as i can tell it should be pretty easy to:

  • check a type for a (custom) attribute,
  • extract desired export type for the type which contains the desired attribute
  • finish export

But with the ForTypesMatching i can't seem to do what i want, because there is no type info available for the builder variable.

Am i trying to do something which is oddly enough not possible in MEF 2, but was possible in MEF 1?

Updates:

Interesting read: http://blog.slaks.net/2014-11-16/mef2-roslyn-visual-studio-compatibility/

1

There are 1 best solutions below

1
On

Attribute:

public class ExportAsAttribute : Attribute
{
    public Type ContractType { get; set; }

    public string ContactName { get; set; }

    public ExportAsAttribute(Type contractType)
    {
        ContractType = contractType;
    }

    public ExportAsAttribute(Type contractType, string contactName)
    {
        ContactName = contactName;
        ContractType = contractType;
    }
}

Convention Code:

var allTypes = GetAllAssemblies().SelectMany(d => d.ExportedTypes);
foreach (var type in allTypes)
{
    var attr = type.GetCustomAttribute<ExportAsAttribute>(true);
    if (attr != null)
    {
        foreach (var derivedType in allTypes.Where(d => !d.IsAbstract && !d.IsInterface && type.IsAssignableFrom(d)))
        {
            if (string.IsNullOrEmpty(attr.ContactName))
            {
                convention.ForType(derivedType).Export(config => config.AsContractType(attr.ContractType));
            }
            else
            {
                convention.ForType(derivedType).Export(config => config.AsContractType(attr.ContractType).AsContractName(attr.ContactName));
            }
        }
    }
}