2012-03-16 17 views
6

cercando di creare un mapper per un oggetto di Microsoft Office per POCO di e trovato questoriflessione sulla interoperabilità COM oggetti

// 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)); 

così devono ricorrere a questo

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

che funziona per ora, ma chiedendo perché il RCW.GetProperties() non funziona qui?

risposta

17

Le altre due risposte al momento della stesura sono corrette, ma manca un'occasione importante per spiegare come l'associazione tardiva di un oggetto COM abbia un aspetto in termini di sistema di tipo .NET. Quando si chiama GetType sull'oggetto COM, il valore restituito è il tipo interno __ComObject, non il tipo di interfaccia COM con cui si lavora normalmente durante la scrittura del codice di interoperabilità. Puoi vederlo nel debugger o con un codice come Console.WriteLine(o.GetType().Name);.

Il tipo __ComObject non ha proprietà; ecco perché ottieni un array vuoto quando chiami o.GetType().GetProperties(). (Almeno alcune cose nella vita hanno senso!)

Se decompilate il metodo InvokeMember, troverete che ha una gestione speciale per gli oggetti COM, delegando la chiamata a un metodo nativo interno. Per oggetti .NET "regolari", il metodo utilizza la riflessione .NET "regolare", recuperando l'appropriato MemberInfo per il membro richiesto e richiamandolo.

È possibile uso .NET riflessione sul interfaccia tipo. Ad esempio, se si sa che l'oggetto è un Excel Worksheet, è possibile utilizzare typeof(Worksheet).GetProperties() e utilizzare le istanze risultanti PropertyInfo con il proprio oggetto. Se non si conosce il tipo di oggetto in fase di compilazione, tuttavia, è necessario chiamare GetType(), come nel codice di esempio. In tal caso, sei bloccato con l'utilizzo di InvokeMember.

1

È necessario specificare per nome utilizzando Type.InvokeMember(propertyName, BindingFlags.GetProperty, binder, target, args) perché non c'è modo di sapere quali sono le proprietà di un oggetto ultimamente-bound sarà avere in fase di compilazione. Al contrario, è necessario eseguire tale ricerca in fase di esecuzione, in genere tramite il confronto delle stringhe.

RCW.GetProperties() funziona solo se è possibile determinare le proprietà e le relative posizioni in fase di compilazione.

Problemi correlati