出色地...
让我们创建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());
}
}
}
然后让我们创建引用 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)
正如预期的那样。它查找具有指定属性的所有兼容方法并返回它们的委托。