10

私はリフレクションに頭を悩ませようとしているので、私が書いているプログラムにプラグイン機能を追加することにしました。概念を理解する唯一の方法は、指を動かしてコードを書くことです。そのため、IPlugin および IHost インターフェイスで構成される単純なインターフェイス ライブラリ、IPlugin を実装するクラスのプラグイン実装ライブラリ、および単純なプラグイン オブジェクトで簡単な作業を行う IHost 実装クラスをインスタンス化するコンソール プロジェクト。

リフレクションを使用して、プラグイン実装 dll 内に含まれる型を繰り返し処理し、型のインスタンスを作成したいと考えました。このコードでクラスを正常にインスタンス化できましたが、作成したオブジェクトをインターフェイスにキャストできませんでした。

このコードを試してみましたが、期待どおりにオブジェクト o をキャストできませんでした。デバッガーを使用してプロセスをステップ実行すると、適切なコンストラクターが呼び出されました。オブジェクト o をクイックウォッチすると、実装クラスで期待していたフィールドとプロパティが含まれていることがわかりました。

loop through assemblies
  loop through types in assembly
    // Filter out unwanted types
    if (!type.IsClass || type.IsNotPublic || type.IsAbstract )
      continue;
    // This successfully created the right object
    object o = Activator.CreateInstance(type);
    // This threw an Invalid Cast Exception or returned null for an "as" cast
    // even though the object implemented IPlugin      
    IPlugin i = (IPlugin) o;

これでコードが機能するようにしました。

using System.Runtime.Remoting;
ObjectHandle oh = Activator.CreateInstance(assembly.FullName, type.FullName);
// This worked as I intended
IPlugin i = (IPlugin) oh.Unwrap();
i.DoStuff();

ここに私の質問があります:

  1. Activator.CreateInstance(Type t) はオブジェクトを返しますが、オブジェクトが実装するインターフェイスにオブジェクトをキャストできませんでした。なんで?
  2. CreateInstance() の別のオーバーロードを使用する必要がありましたか?
  3. リフレクションに関連するヒントとコツは何ですか?
  4. 私が得ていない反射の重要な部分はありますか?
4

7 に答える 7

4

あなたのコードからIPluginインターフェースの定義がどこにあるかは明らかではないので、私はここで推測していますが、ホストアプリケーションでキャストできない場合は、おそらくホストアセンブリにIPluginインターフェースがあり、同時にプラグインアセンブリ。これは機能しません。

最も簡単な方法は、ホストアセンブリでIPluginインターフェイスをパブリックとしてマークしてから、プラグインアセンブリがホストアプリケーションアセンブリを参照するようにすることです。これにより、両方のアセンブリがまったく同じインターフェイスにアクセスできるようになります。

于 2008-08-28T03:46:33.257 に答える
2

うーん... Assembly.LoadFrom を使用してアセンブリをロードしている場合は、代わりに Assembly.LoadFile を変更してみてください。

私のために働いた

ここから: http://www.eggheadcafe.com/community/aspnet/2/10036776/solution-found.aspx

于 2008-10-07T12:52:14.350 に答える
1

私はこれを自分で解決しようとしていたところ、答えに出くわしました!

3 つの異なる C# プロジェクトがありました

  • A - プラグイン インターフェイス プロジェクト
  • B - ホスト exe プロジェクト -> 参照 A
  • C - プラグイン実装プロジェクト -> 参照 A

Plugin Interface proj のアセンブリ名を、キャスト先の名前空間に一致するように変更するまで、キャスト エラーも発生していました。

例えば

IPluginModule pluginModule = (IPluginModule)Activator.CreateInstance(curType);

IPluginModule インターフェイスが定義されているアセンブリが「Common」と呼ばれていたため、失敗していました。ただし、キャスト先の -type- は「Blah.Plugins.Common.IPluginModule」でした。

インターフェイス proj のアセンブリ名を「Blah.Plugins.Common」に変更しました。これは、キャストが成功したことを意味します。

この説明が誰かの役に立てば幸いです。コードに戻る..

于 2008-10-07T12:26:48.083 に答える
1

@ルボス・ハスコ

あなたはそれを鼻に釘付けにしました。私の元の設計には、ホストとプラグインの両方の実装がプラグイン インターフェイス アセンブリを参照する 3 つの異なるアセンブリがありました。

ホスト実装とインターフェイス アセンブリ、およびプラグイン実装アセンブリを使用して、別のソリューションを試しました。そのソリューション内で、最初のブロックのコードは期待どおりに機能しました。

共通アセンブリを参照する 2 つのアセンブリが共通アセンブリから同じ型を取得しない理由がよくわからないため、もう少し考えてみてください。

于 2008-08-28T23:47:08.283 に答える
0

@ Haacked

擬似コードを単純にしようとしました。foreachは多くのスペースと中括弧を使用します。明確にしました。

o.GetType()。FullNameは、期待されるオブジェクトであるPlugins.Multiplyを返します。Plugins.MultiplyはIPluginを実装します。夕方に諦めるまで、デバッガーでプロセスを何度も実行しました。全体の混乱について不機嫌になるまでコンストラクターが発砲するのを見ていたので、なぜそれをキャストできなかったのか理解できませんでした。今晩戻ってきて動作させましたが、最初のコードブロックでキャストが失敗した理由がまだわかりません。2番目のコードブロックは機能しますが、私には気分が悪くなります。

于 2008-08-28T03:35:46.557 に答える
0

あなたの型は公開されていませんか?もしそうなら、ブール値を取るオーバーロードを呼び出します:

Activator.CreateInstance(type, true);

また、最初の例では、 o が null かどうかを確認し、そうでない場合は o.GetType().Name を出力して、実際の内容を確認してください。

于 2008-08-28T02:57:30.440 に答える
0

上記のeggheadへのリンクは、.LoadFrom()の代わりにAssembly.LoadFile()を使用する問題の主な解決策です

于 2011-01-26T18:45:15.087 に答える