mercredi 20 mai 2020

How do I use *attributeless* MEF 2.0 to export methods that match a specific signature?

I'm interested in using external assemblies as plugins. Instead of basing import/export on interfaces, I want to be able to export methods from random assemblies in cases where the method meets a certain signature and import them as method proxies. I have done this previously via custom reflection code but I would rather use Microsoft's built in functionality. Unfortunately, the documentation for MEF v2 is quite lacking.

So how can I change this to successfully create method proxies:

[Test()]
public void ProxyTest()
{
    var builder   = new ConventionBuilder();
    var filter    = new MemberFilter((info, obj) => info.DeclaringType != typeof(object) && info.MemberType == MemberTypes.Method && ((MethodInfo)info).IsBoolTask());
    builder.ForTypesMatching((classType) => classType.FindMembers(MemberTypes.Method, ReflectionExtensions.Everything, filter, null).Any()).Export<Func<Task<bool>>>();
    var host      = new ContainerConfiguration().WithAssembly(this.GetType().Assembly, builder).CreateContainer();
    var container = new ProxyContainer();
    host.SatisfyImports(container);
}

public class ProxyContainer
{
    [ImportMany]
    public IEnumerable<Lazy<Func<Task<bool>>>> LazyProxyMethod
    {
        get;
        set;
    }

    [ImportMany]
    public IEnumerable<Func<Task<bool>>> ProxyMethods
    {
        get;
        set;
    }
}
public static class StaticThing
{
    public static Task<bool> MyStaticMethod() =>
        Task.FromResult(true);
}

public class InstanceThing
{
    public Task<bool> MyInstanceMethod() =>
        Task.FromResult(true);
}

public class InstanceWithStaticThing
{
    public static Task<bool> MyStaticMethod() =>
        Task.FromResult(true);
}

public static class ReflectionExtensions
{
    public const BindingFlags Everything = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy;

    public static bool IsBoolTask(this MethodInfo method) =>
        null != method &&
        typeof(Task<bool>) == method.ReturnType;
}




Aucun commentaire:

Enregistrer un commentaire