4

public abstract class CompositionPlugin { ... }

public class MyCompositionPlugin : CompositionPlugin { ... }

オブジェクトの型が特定の型と等しいかどうかを確認したい:

public class Framework {

    public IList<CompositionPlugin> CompositionPlugins = new List<CompositionPlugin>();

    public CompositionPlugin GetCompositionPlugin(Type ofType)
    {
        foreach (CompositionPlugin plugin in CompositionPlugins)
        {
            if (plugin.GetType().Equals(ofType))
                return plugin;
        }

        throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found");
    }
}

メソッドは次のように呼び出されます。

Framework framework = new Framework();
// Adding the plugin to the framework is done by loading an assembly and
// checking if it contains plugin-compatible classes (i.e. subclasses
// of <CompositionPlugin>)
framework.RegisterAssembly("E:\\Projects\\Framework\\MyPlugin\\bin\\Debug\\MyPlugin.dll");
CompositionPlugin plugin = framework.GetCompositionPlugin(typeof(MyCompositionPlugin));

しかし、テストを行うと、要求したリストにそのタイプのオブジェクトが確実に含まれているにもかかわらず、このチェックは常に失敗します。

私の理解では、 -ListMyCompositionPlugin内で見つかった最初のインスタンスを返す必要があります。CompositionPlugins

私のタイプチェックは間違っていますか?なんで?それはどのように正しく行われますか?

4

5 に答える 5

8

IsAssignableFromタイプで使用したい:

if (ofType.IsAssignableFrom(plugin.GetType())

Equalsタイプがまったく同じ場合のみを処理します。また、 がプラグインの継承元の型、または実装されているインターフェイスであるIsAssignableFrom場合も処理します。ofType

于 2012-08-01T14:16:33.880 に答える
5

答えではありませんが、コメントには長すぎます... メソッドの呼び出し方法やコレクションの作成方法に問題があるのではないですか? この単純化されたバージョンのコードで示されているように、比較自体は問題ありません。

class A {}

bool TestType(A item, Type ofType)
{       
    return item.GetType().Equals(ofType);
}

今:

Console.WriteLine(TestType(new A(), typeof(A))); // True
Console.WriteLine(TestType(new A(), typeof(string))); // False

編集

@vcsjonesが正しいと思います。派生クラスを基本クラスと比較しようとしています。プラグインを CompositionPlugin であると宣言している行foreach (CompositionPlugin plugin in CompositionPlugins)ではありますが、クライアント コードでは と比較していますtypeof(MyCompositionPlugin)。(再編集いいえ、私は間違っています。あなたのケースは、Console.WriteLinetrue を返す私の s の 4 番目に対応しています)

あなたと同様のシナリオで Equals の真理値表を含むこの例を参照してください。

class CompositionPlugin {}
class MyCompositionPlugin : CompositionPlugin  {}

// Define other methods and classes here
bool TestType(CompositionPlugin item, Type ofType)
{       
    return item.GetType().Equals(ofType);
}

Console.WriteLine(TestType(new CompositionPlugin(), 
            typeof(CompositionPlugin))); //True
Console.WriteLine(TestType(new CompositionPlugin(), 
            typeof(MyCompositionPlugin))); //False
Console.WriteLine(TestType(new MyCompositionPlugin(), 
            typeof(CompositionPlugin))); //False
Console.WriteLine(TestType(new MyCompositionPlugin(),
            typeof(MyCompositionPlugin))); //True
于 2012-08-01T14:27:04.503 に答える
3

キーワードを使うis

if (plugin is ofType)
    return plugin;

編集:

これについては@vcsjonesと一緒に行かなければなりません。isassignablefrom関数を使用します。

しかし、本当にうまくいくと思うなら、私はいつもデバッグテキストをファイルに書き込むためのクイック関数を作成しています。

public class Framework {

    public IList<CompositionPlugin> CompositionPlugins = new List<CompositionPlugin>();

    public CompositionPlugin GetCompositionPlugin(Type ofType)
    {
        using(var writer = System.IO.File.CreateText(@"C:\test.log"))
        {
            writer.WriteLine("ofType: " + ofType.toString());
            foreach (CompositionPlugin plugin in CompositionPlugins)
            {
                writer.WriteLine("plugin: " + plugin.GetType().toString());
                if (plugin.GetType().Equals(ofType))
                    return plugin;
            }
        }

        throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found");
    }
}
于 2012-08-01T14:13:18.513 に答える
0

あなたの問題は、アセンブリが 2 回目に読み込まれ、そのために等価が失敗するという事実が原因である可能性が最も高いです。アセンブリが再度読み込まれないようにすることをお勧めします。そのため、ダーティな文字列比較を使用する代わりに、通常の型比較を使用できます。私は同じ問題を抱えていました.私のプラグインインターフェースは別のアセンブリで定義されていました.このアセンブリはスタートアップフォルダーに存在しましたが、プラグインアセンブリが動的にロードされたプラグインフォルダーにも存在し、結果としてインターフェースタイプの等価性が失敗しました. プラグイン フォルダーからインターフェイス dll を削除した後、すべてが期待どおりに機能しました。

于 2015-04-01T07:05:36.810 に答える
0

結局のところ、私が最初は重要ではないと考えて質問から外した情報は、結局のところそうでした.

MyCompositionPluginとはCompositionPlugin両方とも異なるアセンブリで定義されており、実行中のプログラムが実行時に動的にロードします。

.NET-Runtime は、実行中のアセンブリによって参照されるものとは別のアセンブリから読み込まれた型を考慮するようになり、実際には同じであっても、別のアセンブリから読み込まれた型とは異なると見なされるMyCompositionPlugin-Type をレンダリングします。ProgramMyCompositionPlugin

(常識的には同じ「クラス」であるという点で) 2 つを等しいかどうか比較する解決策は、定義アセンブリの文字列の等価性に分解することです。これは間違いなく汚いですが、うまくいきます。

public CompositionPlugin GetCompositionPlugin(Type ofType)
{
    foreach (CompositionPlugin plugin in CompositionPlugins)
        if (ofType.AssemblyQualifiedName.Equals(plugin.GetType().AssemblyQualifiedName))
            return plugin;

    throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found");
}

この質問を指摘したパオロ・ファラベラへの称賛

于 2012-08-03T07:09:19.247 に答える