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()がカスタムアプリドメインのコンテキストで実行されることを意味します。

問題は、IsSubclassOf()の呼び出しは、IMHOがtrueを返す必要がある場合でも、常にfalseを返すことです。問題の「タイプ」は実際にはClientPluginから継承されます-それについては疑いの余地はありません。

ClientPluginは、上記のコードフラグメントで明らかなように、手動で解決している別のプライベートアセンブリで定義されています。

行にブレークポイントを設定し、if (type.IsSubclassOf(...))この式がfalseであることを確認しました。

type.BaseType == typeof(ClientPlugin)

一方、この式は真です。

type.BaseType.FullName == typeof(ClientPlugin).FullName

これはどのように可能ですか?どうしたの?

更新:ケント・ブオゴールは私を正しい方向に向けました。私はもう少しウェブを検索して、このブログ投稿に出くわしました。これを機能させるには、Load / LoadFrom/ReflectionOnlyLoadFromの競合を解決する必要があるようです。

4

2 に答える 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();
    }
}

詳細については、こちらを参照してください。

于 2009-01-21T16:53:54.173 に答える
2

同様の問題がありました。私もこのアーキテクチャを持っていました.ClientPlugin基本クラスを含む.DLLです。この .DLL を参照するいくつかのプラグイン。そして、この .DLL も参照するメイン アプリケーション。問題は、ClientPlugin 基本クラスを含む .DLL が 2 つのフォルダー (Plugins フォルダーとメイン アプリケーション フォルダーの両方) にコピーされていたことです。したがって、AppDomain に 2 回ロードされました (プラグインも間接的にロードしました)。また、メイン アプリケーションがリフレクション タイプのマジックを実行しようとすると、失敗しました。ClientPlugin タイプのインスタンスが 2 つあったためです。

これがまさにあなたのケースだとは思いませんが、ここで学ぶべき教訓がまだあります。.DLL が 2 回読み込まれると、型も複製されます。あなたの場合、別のAppDomainsまたは「ReflectionOnlyLoad」のいずれかが疑われます。これは、.DLLが何らかの方法でロードされるためです。

于 2009-01-21T16:43:17.347 に答える