我有一个场景,我想要n个类来查看相同的数据并决定是否需要完成任何工作。工作由团队完成,多个团队可以同时处理数据。我正在考虑为每个实现CreateWork接口的团队创建一个类。所有CreateWork类都必须有发言权。目前只有少数,但将来会有更多。
我计划的解决方案的Sudo代码
For each CreateWork class in assembly
class.CheckAndCreateWork(dataIn,returnedCollectionOfWorkToBeDone)
Next
是否有一种能够以优雅的方式实现这一目标的设计模式?围绕程序集中的每个类循环似乎有点乱。
干杯
答案 0 :(得分:9)
您可以执行以下操作:
使用Assembly.GetTypes获取程序集中定义的所有类型。要获取运行代码的程序集的参考,请使用Assembly.GetExecutingAssembly。
对于每种类型,请使用Type.IsAssignableFrom检查它是否实现了所需的界面。
对于每种合适的类型,使用Activator.CreateInstance创建实例。
大致会像这样(未经测试):
foreach(var type in Assembly.GetExecutingAssembly().GetTypes()) {
if(typeof(ITheInterface).IsAssignableFrom(type)) {
var theInstance=(ITheInterface)Activator.CreateInstance(type);
//do something with theInstance
}
}
答案 1 :(得分:1)
我认为你应该使用装饰模式。
答案 2 :(得分:0)
这是一个标准的插件任务。那里有很多实现。如果你已经加载了你的assemlby,找到你感兴趣的类型很简单 - 你需要使用方法assemlby.GetExportedTypes()
和Activator.CreateInstance()
(前提是你有无参数构造函数 - 否则你可能希望使用容器注入依赖项并建立你的工人实例)
对于简单的情况,这就足够了:
var workerTypes = assembly.GetExportedTypes()
.Where(t => t.IsClass && !t.IsAbstract && typeof(IWorker).IsAssignableFrom(t));
foreach (var type in workerTypes)
{
var worker = (IWorker)Activator.CreateInstance(type);
worker.CheckAndCreateWork("Work");
}
获取和加载assemlby是另一个主题。您可以使用Assemlby.LoadFrom()
在运行时加载,也可以将它们静态链接到您的应用程序,并使用以下内容:
var assembly = typeof(SomeClassInTargetAssembly).Assembly;
动态加载可以通过枚举特定目录中的所有 * .dll 文件(例如,./plugins
)完成,如下所示:
foreach (var file in Directory.GetFiles(PluginsFolder, "*.dll"))
{
var assembly = Assembly.LoadFrom(file);
var workerTypes = GetWorkerTypes(assembly);
RunWorkers(workerTypes);
}
您可能希望分离加载和运行工作程序的过程,以避免多次加载工作程序类型(如果您需要在应用程序生命周期内多次运行工作程序)