如何在MEF中获取所有方法 [英] How to get all methods in MEF

查看:43
本文介绍了如何在MEF中获取所有方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有属性类

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

}

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

I'm using it in method of several namespaces:

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)
        {

        }
    }
}

我想订购所有方法并逐一运行.要获取方法,我正在这样做:

I want to order all methods and run it one by one. To get methods I'm doing this:

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

但是它仅返回Worker的方法.如何从工作人员那里获得所有三种方法?

But it returns only Worker's method. How can I get all three methods from worker?

推荐答案

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

Well... Let's create 4 class libraries

Zero.dll以及在其他程序集中使用的所有类

Zero.dll with all classes used in other assemblies

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();
        }
    }
}

引用Zero.dll的Model.First.dll

Model.First.dll referencing Zero.dll

using System;
using Zero;

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

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

Model.First.Second.dll referencing 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());
        }
    }
}

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

Model.First.Second.Third.dll referencing 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());
        }
    }
}

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

Then let's create console application ConsoleApp.exe referencing Zero.dll, Model.First.dll, Model.First.Second.dll and 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文件目录中,然后启动应用程序.

Let's create Junk.txt, put some nonsense like bd%E56#EVwD into it, rename the file to Junk.dll and add it into .exe file directory and then start the application.

输出为:

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)

符合预期.它会找到具有指定属性的所有兼容方法,并为其返回委托.

As expected. It finds all compatible methods with specified attribute and returns delegates for them.

这篇关于如何在MEF中获取所有方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆