How to find all classes of a particular interface within an assembly in .net
I have a scenario whereby I want n amount of classes to look at the same data and decide if any work needs t开发者_开发问答o be done. Work is done by a team, and multiple teams can work on the data at the same time. I was thinking of creating a class for every team that would implement the CreateWork interface. All CreateWork classes must have their say. At the moment there are only a few but in the future there will be many more.
Sudo code for my planned solution
For each CreateWork class in assembly
class.CheckAndCreateWork(dataIn,returnedCollectionOfWorkToBeDone)
Next
Is there a design pattern that can accomplish this in an elegant way? Seems a bit messy to loop round every class in the assembly.
Cheers
You can do the following:
Get all the types defined in the assembly by using Assembly.GetTypes. To obtain a reference for the asembly your code is running on, use Assembly.GetExecutingAssembly.
For each type, check if it implements the desired interface by using Type.IsAssignableFrom.
For each appropriate type, create a instance by using Activator.CreateInstance.
It would be approximately like this (not tested):
foreach(var type in Assembly.GetExecutingAssembly().GetTypes()) {
if(typeof(ITheInterface).IsAssignableFrom(type)) {
var theInstance=(ITheInterface)Activator.CreateInstance(type);
//do something with theInstance
}
}
I think you should use the decorator pattern.
It's a standard plugin task. There are many implementations out there. If you have already loaded your assemlby, finding types you are interested in is easy - you need to use method assemlby.GetExportedTypes()
and Activator.CreateInstance()
(provided you have parameterless constructor - otherwise you may wish to use container to inject dependencies and build up your worker instances)
For simple case this is sufficient:
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");
}
Getting and loading assemlby is another topic. You can either load in run-time using Assemlby.LoadFrom()
or link them statically to your application and use something like this:
var assembly = typeof(SomeClassInTargetAssembly).Assembly;
Dynamic loading may be done by enumerating through all the *.dll files in a specific directory (for example, ./plugins
) like this:
foreach (var file in Directory.GetFiles(PluginsFolder, "*.dll"))
{
var assembly = Assembly.LoadFrom(file);
var workerTypes = GetWorkerTypes(assembly);
RunWorkers(workerTypes);
}
You may want to separate processes of loading and running workers to avoid loading worker types multiple times (in case you need to run workers more than once during application life time)
精彩评论