如何在MEF中获取所有方法

问题描述 投票:2回答:1

我有属性类

[AttributeUsage(AttributeTargets.Method)]
public class MethodGetterAttribute : ExportAttribute
{

}

我在几个名称空间的方法中使用它:

namespace Model.First
{
    public class PersonBL
    {
        [MethodGetter]
        public void GetName(Person person)
        {

        }
    }
}

namespace Model.First.Second
{
    public class PersonBL
    {
        [MethodGetter]
        public void GetName(Person person)
        {

        }
    }
}

namespace Model.First.Second.Third
{
    public class WorkerBL
    {
        [MethodGetter]
        public void GetName(Worker worker)
        {

        }
    }
}

我想订购所有方法并逐个运行。要获得方法,我正在这样做:

Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(assemblies.FirstOrDefault(a => a.GetName().Name.Contains("Model"))));
var container = new CompositionContainer(catalog);
var importedMethods = container.GetExports<Action<Worker>>() as IEnumerable<Lazy<Action<Worker>>>;
var result = importedMethods.Select(a => a.Value.Target).ToList();// Here i'm getting only worker's method

但它只返回工人的方法。如何从工人那里获得所有三种方法?

c# mef
1个回答
1
投票

好吧......让我们创建4个类库

Zero.dll与其他程序集中使用的所有类

using System;
using System.ComponentModel.Composition;
using System.Diagnostics;

namespace Zero
{
    [AttributeUsage(AttributeTargets.Method)]
    public class MethodGetterAttribute : ExportAttribute { }

    public class Person { }

    public class Worker : Person { }

    public static class MethodHelper
    {
        public static string GetMethod()
        {
            var method = new StackTrace().GetFrame(1).GetMethod();
            return $"{method.DeclaringType.FullName} {method}";
        }
    }

    public static class Discovery
    {
        public static TDelegate[] GetDelegates<TAttribure, TDelegate>()
            where TAttribure : Attribute
            where TDelegate : Delegate
        {
            return Directory.GetFiles(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "*.dll")
                            .Select(file => { try { return Assembly.LoadFrom(file); } catch { return null; } })
                            .OfType<Assembly>()
                            .Append(Assembly.GetEntryAssembly())
                            .SelectMany(assembly => assembly.GetTypes())
                            .SelectMany(type => type.GetMethods())
                            .Where(method => method.GetCustomAttributes(typeof(TAttribure)).Any())
                            .Select(method => Delegate.CreateDelegate(typeof(TDelegate), null, method, false))
                            .OfType<TDelegate>()
                            .ToArray();
        }
    }
}

Model.First.dll引用Zero.dll

using System;
using Zero;

namespace Model.First
{
    public class PersonBL
    {
        [MethodGetter]
        public void GetName(Person person)
        {
            Console.WriteLine(MethodHelper.GetMethod());
        }
    }
}

Model.First.Second.dll引用Zero.dll

using System;
using Zero;

namespace Model.First.Second
{
    public class PersonBL
    {
        [MethodGetter]
        public void GetName(Person person)
        {
            Console.WriteLine(MethodHelper.GetMethod());
        }

        [MethodGetter]
        public void Incompatible(string s)
        {
            Console.WriteLine(MethodHelper.GetMethod());
        }
    }
}

Model.First.Second.Third.dll引用Zero.dll

using System;
using Zero;

namespace Model.First.Second.Third
{
    public class WorkerBL
    {
        [MethodGetter]
        public void GetName(Worker worker)
        {
            Console.WriteLine(MethodHelper.GetMethod());
        }

        public void NoAttribute(Worker worker)
        {
            Console.WriteLine(MethodHelper.GetMethod());
        }
    }
}

然后让我们创建控制台应用程序ConsoleApp.exe,引用Zero.dll,Model.First.dll,Model.First.Second.dll和Model.First.Second.Third.dll

using System;
using Zero;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var worker = new Worker();
            foreach (var d in Discovery.GetDelegates<MethodGetterAttribute, Action<Worker>>())
                d.Invoke(worker);
        }        
    }

    public class WorkerBL
    {
        [MethodGetter]
        public void GetName(Worker worker)
        {
            Console.WriteLine(MethodHelper.GetMethod());
        }
    }
}

让我们创建Junk.txt,将一些废话如bd%E56#EVwD放入其中,将文件重命名为Junk.dll并将其添加到.exe文件目录中,然后启动应用程序。

输出是:

Model.First.PersonBL Void GetName(Zero.Person)
Model.First.Second.PersonBL Void GetName(Zero.Person)
Model.First.Second.Third.WorkerBL Void GetName(Zero.Worker)
ConsoleApp.WorkerBL Void GetName(Zero.Worker)

正如所料。它找到具有指定属性的所有兼容方法,并为它们返回委托。

© www.soinside.com 2019 - 2024. All rights reserved.