如何在MEF中获取所有方法 [英] How to get all methods in 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屋!