【发布时间】:2012-06-04 07:54:54
【问题描述】:
我想让使用我的产品的开发人员能够通过实现接口然后将程序集放入执行文件夹来扩展产品。 我应该如何寻找这些类型,我必须通过文件夹中的每个 DLL 运行还是可以避免那些属于原始应用程序的那些?
【问题讨论】:
标签: c# reflection
我想让使用我的产品的开发人员能够通过实现接口然后将程序集放入执行文件夹来扩展产品。 我应该如何寻找这些类型,我必须通过文件夹中的每个 DLL 运行还是可以避免那些属于原始应用程序的那些?
【问题讨论】:
标签: c# reflection
你为什么不使用microsoft's solutions?
据我了解,它完全可以解决您的需求
【讨论】:
您可以将新程序集放入不同的文件夹(例如调用或插件或扩展),然后在运行时实例化它们;或者,维护产品程序集列表并使用 Path.GetFiles 并删除列表中出现的所有程序集。
【讨论】:
我将它用于用户定义的工具。
private static void getImplementedTypes(Type baseType, Assembly assembly, IList<Type> list) {
Type[] types = assembly.GetExportedTypes();
foreach (Type t in types) {
if (baseType.IsInterface) {
Type[] interfaces = t.GetInterfaces();
foreach (Type i in interfaces) {
if (i == baseType) list.Add(t);
}
}
else {
if ((!list.Contains(t)) && (t.IsSubclassOf(baseType)) && (!t.IsAbtract)) {
list.Add(t);
}
}
}
return n;
}
在一个循环中,我会遍历工具目录中 Directory.GetFiles 找到的所有 DLL(或 EXE):
Assembly assembly = Assembly.LoadFile("toolbox.dll");
List<Type> types = new List<Type>();
getImplementedTypes(typeof(ToolBase), assembly, types);
ToolBase theTool = Activator.CreateInstance(type, true) as ToolBase;
这适用于接口和基类。
我不知道如何以不同的方式找到已实现的类。 这可能要花点时间。因此,如果您知道要搜索哪些 DLL,只需遍历它们即可。
【讨论】:
最后,我选择简单地加载并搜索我在 bin 中找到的所有 dll。 这是大部分代码。关键函数是“IsAssignableToGenericType”函数,它可以找到我正在寻找的通用接口。
我相信这是提供大部分解决方案的链接 Implementations of interface through Reflection
static AssemblyLocator()
{
AllDlls = GetAllDlls();
SubscribersInBin = GetSubscribersInBin();
}
public static IEnumerable<Type> TypesImplementingInterface(Assembly[] assemblies, Type desiredType)
{
return assemblies
.SelectMany(assembly => assembly.GetTypes())
.Where(type => IsAssignableToGenericType(type, desiredType));
}
public static bool IsAssignableToGenericType(Type givenType, Type genericType)
{
if (givenType == null) throw new ArgumentNullException("givenType");
if (genericType == null) throw new ArgumentNullException("genericType");
var interfaceTypes = givenType.GetInterfaces();
foreach (var it in interfaceTypes)
{
if (it.IsGenericType)
{
if (it.GetGenericArguments()[0].Name.Equals(genericType.GetGenericArguments()[0].Name))
return true;
}
}
Type baseType = givenType.BaseType;
if (baseType == null) return false;
return (baseType.IsGenericType &&
baseType.GetGenericTypeDefinition() == genericType) ||
IsAssignableToGenericType(baseType, genericType);
}
private static ReadOnlyCollection<string> GetAllDlls()
{
string binFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
IList<string> dllFiles = Directory.GetFiles(binFolder, "*.dll", SearchOption.TopDirectoryOnly).ToList();
return new ReadOnlyCollection<string>(dllFiles);
}
private static ReadOnlyCollection<Type> GetSubscribersInBin()
{
IList<Assembly> assembliesFoundInBin = new List<Assembly>();
foreach (var item in AllDlls)
{
var assembly = System.Reflection.Assembly.LoadFrom(item);
assembliesFoundInBin.Add(assembly);
}
var typesInBin = TypesImplementingInterface(assembliesFoundInBin.ToArray(), typeof(ISubscriber<T>));
return new ReadOnlyCollection<Type>(typesInBin.ToList<Type>());
}
【讨论】: