2012-03-16 11 views
6

が今なぜ疑問に思うために働くこの反射は

foreach(var field in tgt.GetFields()){ 
    var pv = o.InvokeMember(field.Name, System.Reflection.BindingFlags.GetProperty, null, o, null); 
    i.SetValue(rc, pv); 
} 

に頼る必要がありPOCOさんへのMicrosoft Officeオブジェクトに対するマッパーを作成しようとし、この

// doesn't work 
// returns an empty array where o is a RCW on an office object 
foreach(var pi in o.GetType().GetProperties()) 
    tgt.SetValue(rc, pi.GetValue(o, null)); 

を発見したオブジェクトRCW.GetProperties()はここでは機能しませんか?

答えて

17

この執筆時点での他の2つの答えは正しいですが、COMオブジェクトの遅延バインディングが.NETタイプのシステムでどのように見えるかを説明する重要な機会がありません。 GetTypeをCOMオブジェクトで呼び出すと、返される値は__ComObject内部型であり、通常は相互運用コードの作成時に使用するCOMインターフェイス型ではありません。これはデバッガで、またはConsole.WriteLine(o.GetType().Name);のようなコードで確認できます。

__ComObjectタイプにはプロパティはありません。そのため、o.GetType().GetProperties()に電話すると空の配列が返されます。

InvokeMemberメソッドを逆コンパイルすると、内部ネイティブメソッドへの呼び出しを委任するCOMオブジェクトに対して特別な処理が行われることがわかります。 「通常の」.NETオブジェクトの場合、メソッドは「通常の」.NETリフレクションを使用して、要求されたメンバに対して適切なMemberInfoを取得し、呼び出す。

のインタフェースタイプの.NETリフレクションを使用します。たとえば、オブジェクトがExcel Worksheetであることがわかっている場合は、typeof(Worksheet).GetProperties()を使用して、結果のPropertyInfoインスタンスをオブジェクトに使用できます。ただし、コンパイル時にオブジェクトの型がわからない場合は、コード例のようにGetType()を呼び出す必要があります。その場合は、InvokeMemberを使用しています。

1

何の特性最近、バインドされたオブジェクトをだろう知る方法はありませんので、あなたがType.InvokeMember(propertyName, BindingFlags.GetProperty, binder, target, args)を使用して、名前でそれらを指定する必要があります。ここでは

は、件名にいくつかの良い記事がありますコンパイル時に持っています。その代わりに、通常は文字列比較を介して、実行時にそのルックアップを実行する必要があります。

RCW.GetProperties()は、コンパイル時にプロパティとその場所を判断できる場合にのみ機能します。