Type.IsSubclassOf()无法跨越AppDomains工作?

7

我在以下代码中遇到了一些问题:

private class ClientPluginLoader : MarshalByRefObject
{
    public bool IsPluginAssembly(string filename)
    {
        AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(CurrentDomainReflectionOnlyAssemblyResolve);

        Assembly asm = Assembly.ReflectionOnlyLoadFrom(filename);

        Type[] types = asm.GetTypes();
        foreach (Type type in types)
        {
            if (type.IsSubclassOf(typeof(ClientPlugin)))
            {
                return true;
            }
        }

        return false;
    }
}

这段代码是通过我创建的代理调用的,代理是通过我的自定义应用程序域的CreateInstanceFromAndUnwrap()方法创建的。这意味着IsPluginAssembly()在我的自定义应用程序域的上下文中执行。

问题在于,尽管在我的看法中应该返回true,但IsSubclassOf()调用始终返回false。毫无疑问,“type”确实从ClientPlugin派生出来。

ClientPlugin在另一个私有程序集中定义,我正在手动解析它,就像上面的代码片段所示。

我已经在if (type.IsSubclassOf(...))行上设置了断点,并确认了这个表达式为false:

type.BaseType == typeof(ClientPlugin)

另一方面,这个表达式是正确的:
type.BaseType.FullName == typeof(ClientPlugin).FullName

这怎么可能?发生了什么?
更新:Kent Boogaart指引我朝正确方向前进。我在网上搜索了一些信息,并发现这篇博客文章。看起来我需要解决我的Load/LoadFrom/ReflectionOnlyLoadFrom冲突,才能使这个工作正常运作。
2个回答

7
这是因为加载到不同的上下文中。您如何加载程序集(Load / LoadFrom / ReflectionOnlyLoad)决定了它被加载到哪个上下文中。这个简单的例子也展示了问题:
using System;
using System.Reflection;

class Foo
{
    public static void Main()
    {
        var type = typeof(Foo);
        var reflectionLoadType = Assembly.ReflectionOnlyLoad("ConsoleApplication1").GetType("Foo");
        Console.WriteLine(type == reflectionLoadType);  //false
        Console.WriteLine(type.Equals(reflectionLoadType));  //false

        Console.WriteLine("DONE");
        Console.ReadKey();
    }
}

See here for more info.


2
我遇到过类似的问题。我的架构也是这样的-一个包含ClientPlugin基类的.DLL;几个引用此.DLL的插件;以及一个也引用此.DLL的主应用程序。问题在于,包含ClientPlugin基类的.DLL被复制到了两个文件夹中-Plugins文件夹和主应用程序文件夹。因此,在我的AppDomain中加载了两次(插件也间接地加载它)。当主应用程序尝试进行反射类型操作时,它失败了,因为存在两个ClientPlugin类型的实例。
虽然我不认为这恰好是你的情况,但仍有教训可学-如果一个.DLL被加载两次,类型也将被复制。在你的情况下,我会怀疑是否使用了单独的AppDomains或“ReflectionOnlyLoad”,因为.DLL会以某种不同的方式加载。

我曾经遇到过这个问题,我的两个文件夹中有同一个DLL的两个副本。当我手动执行“IsSubclassOf”时,我收到了这个错误消息:“类型'ServiceCore.BaseService'存在于'ServiceCore.dll'和'ServiceCore.dll'中”。 - vpalmu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接