我在C#中有一个来自*的插件系统.
关键部分是Assembly.LoadFile,Type.IsAssignableFrom和Activator.CreateInstance.它有效,但是我不完全了解IsAssignableFrom如何识别外部程序集加载的类型.
说,我有
public interface PluginInterface
{
int calculateSomething();
}
我已经将其编译为PluginInterface.dll.
PluginInterface.dll是示例插件中的引用,例如:
public class CalculateOnePlugin : PluginInterface
{
public int calculateSomething() { return 1; }
}
它被编译为CalculateOnePlugin.dll.
现在,创建一个引用PluginInterface.dll的应用程序,并尝试加载和使用CalculateOnePlugin.dll:
var pluginAssembly = Assembly.LoadFile("CalculateOnePlugin.dll");
Type interfaceType = typeof(PluginInterface);
Type[] typesInLoadedAssembly = pluginAssembly.GetTypes();
Type pluginType = null;
foreach (var typeInLoadedAssembly in typesInLoadedAssembly)
if (interfaceType.IsAssignableFrom(typeInLoadedAssembly)) // ???
{
pluginType = typeInLoadedAssembly;
break;
}
if (pluginType!=null)
{
PluginInterface pi = (PluginInterface)Activator.CreateInstance(pluginType);
// and do what you want with that plugin object
}
我的问题是IsAssignableFrom如何识别和匹配从两个外部程序集加载的类型? IsAssignableFrom考虑哪些程序集或类属性?
如果我复制PluginInterface的源代码并将其编译为(例如)AnotherPluginInterface.dll,并在构建CalculateOnePlugin.dll时使用此引用,则它将无法正常工作.因此,类型匹配不仅在乎方法签名,例如,它以某种方式知道程序集和类型的来源.
当我为应用程序和插件使用两种不同版本的PluginInterface时(即在后者中添加了一个方法),它将无法再次使用,因此这两个dll的来源还不够,它内部必须包含某些版本的东西它.
但是,只需在两种用法(应用程序和插件)之间重新编译PluginInterface不会使事情变得混乱,它可以工作.
PluginInterface.dll的GUID是否包含在CalculateOnePlugin.dll的引用中,这是IsAssignableFrom知道它们相同的方式吗?还是将类似哈希的值用于类型?还是两者都?
解决方法:
My question is how IsAssignableFrom identifies and matches the types loaded from two external assembly? What assembly or class properties are taken into consideration by IsAssignableFrom?
本质上进行了等效比较.
类型派生自称为RunTimeType的类.
RunTimeType有一个Equality运算符,它执行如下检查:
return RuntimeTypeHandle.IsEquivalentTo(this, otherRtType);
不幸的是RuntimeTypeHandle.IsEquivalentTo被标记为CLR核心的一部分,无法反映出来,因此我无法确切告诉您它的外观或代码中的功能.
但是,根据this article entitled “Anatomy of a .NET Assembly”,
Type values are stored using a string representing the type name and fully qualified assembly name (for example,
MyNs.MyType, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0123456789abcdef
). If the type is in the current assembly or mscorlib then just the type name can be used.
因此,程序集名称,区域性,版本,名称空间和公共密钥令牌似乎都可以匹配,以便唯一地标识类型.