我想检索一个实例化类的枚举,这些类实现了解决方案文件夹中几个程序集的接口。
我有以下文件夹结构(如果这有意义):
Solution
-SolutionFolder
- Project1
- class implementing interface I would like to find
- other classes
- Project2
- class implementing interface I would like to find
- other classes
-MainProject
- classes where my code is running in which I would like to retrieve the list of classes
因此,如果正在实现的接口是ISettings
,那么我希望IEnumerable<ISettings>
引用该接口的实例化对象。
到目前为止,我已经使用反射从已知的类名中检索实现接口的类:
IEnumerable<ISettings> configuration =
(from t in Assembly.GetAssembly(typeof(CLASSNAME-THAT-IMPLEMENTs-INTERFACE-HERE)).GetTypes()
where t.GetInterfaces().Contains(typeof(ISettings)) && t.GetConstructor(Type.EmptyTypes) != null
select (ISettings)Activator.CreateInstance(t)).ToList();
但这是一个单独的程序集,我实际上不会知道类名。
这可以通过反射实现还是需要更多?
答案 0 :(得分:1)
只要您只谈论加载到AppDomain中的程序集(它们必须是为了完成您所做的事情),您可以使用类似的东西来迭代它们:< / p>
AppDomain.CurrentDomain
.GetAssemblies().ToList()
.ForEach(a => /* Insert code to work with assembly here */);
或者,如果您将它们加载到其他AppDomain中,则可以在上面的AppDomain.CurrentDomain
处使用实例。
答案 1 :(得分:0)
要解决此问题,我将解决方案文件夹中每个项目的post build事件设置为将其程序集复制到主项目bin文件夹中的bin文件夹。
post build事件的设置类似于:
copy "$(TargetPath)" "$(SolutionDir)MainProjectName\bin"
然后我使用以下内容从此bin目录中检索程序集文件名(感谢Darin的解决方案here):
string[] assemblyFiles = Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin"), "*.dll");
然后我使用以下方法检索实现接口ISettings的对象的实现:
IEnumerable<ISettings> configuration = assemblyFiles.Select(f => Assembly.LoadFrom(f))
.SelectMany(a => a.GetTypes())
.Where(t => t.GetInterfaces().Contains(typeof(ISettings)) && t.GetConstructor(Type.EmptyTypes) != null)
.Select(t => (ISettings)Activator.CreateInstance(t));
这允许我添加更多实现设置的项目,而无需重新编译主项目。
此外,我看到的一个替代方法是使用MEF
,其中可以找到介绍here。