Search code examples
mef

Is it possible to register open generics in MEF 2 using conventions?


I'm exploring the new attributeless registering capabilities of MEF2/.Net4.5 (aka. Conventions). More specifically I'm trying to register open generics:

public interface IRepository<T>
{
    T Fetch();
}

public class Repository<T> : IRepository<T>
{
    public T Fetch()
    {
        return default(T);
    }
}

public class Quotation
{

}

class Program
{
    static void Main(string[] args)
    {
       var registrationBuilder = new RegistrationBuilder();

       registrationBuilder
            .ForType<Repository<Quotation>>()
            .Export();

        registrationBuilder
            .ForTypesMatching(t => t.Name.EndsWith("ory"))
            .Export();

        registrationBuilder
            .ForType<Quotation>()
            .Export<Quotation>();

        var catalog = new AssemblyCatalog(typeof (Program).Assembly, registrationBuilder);

        foreach (var part in catalog.Parts)
        {
            Console.WriteLine(part.ToString());
        }
     }
 }

No matter the method I'm using to register the repository (see code), only the Quotation class is contained in the catalog. Am I missing something, or is there no support for open generics in the registration API?

Best regards,

K.Korselis


Solution

  • It is possible. All combinations are possible as far as I have seen.

    Attribute export - Convention import Convention export - Attributed import Convention expot - Convention import

    To make you sample work replace:

    registrationBuilder
                .ForTypesMatching(t => t.Name.EndsWith("ory"))
                .Export();
    

    with:

    registrationBuilder
                    .ForTypesMatching(t => t.GetInterface(typeof(IRepository<>).Name) != null)                    
                    .ExportInterfaces();
    

    Of course there other ways to implelemt the ForTypesMatching predicate. Note that you can also filter the exported interfaces.

    Curiously the following doesn't work:

    registrationBuilder
                    .ForTypesDerivedFrom(typeof(IRepository<>))
                    .ExportInterfaces();
    

    I don't have the time at the moment to check out MEF's source but when I do I will let you know.