我有属性类
[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
但是它仅返回Worker的方法。如何从工作人员那里获得所有三种方法?
答案 0 :(得分: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();
}
}
}
引用Zero.dll的Model.First.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
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
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
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)
符合预期。它会找到具有指定属性的所有兼容方法,并为其返回委托。