2010-03-04 13 views
7

Una domanda interessante è sorta oggi. Diciamo che ho un oggetto .NET che implementa una determinata interfaccia IMyInterface ed è anche COM Visible.Sto chiamando un oggetto .NET o un oggetto COM?

Ora, ho caricare il tipo dal suo ProgID e gettato a un'interfaccia fortemente tipizzato, in questo modo:

IMyInterface objEarlyBound = null; 
Type t = Type.GetTypeFromProgID("My.ProgId"); 
objLateBound = Activator.CreateInstance(t); 

objEarlyBound= (IMyInterface)objLateBound; 

objEarlyBound.Method(); 

Se eseguo il codice di cui sopra, quando objEarlyBound.Method() esegue, sono io chiamando in un oggetto COM o direttamente nell'oggetto .NET? Come posso dimostrare questo in un modo o nell'altro?

risposta

2

Non si può provare molto in entrambi i casi: è una scelta di implementazione interna che è stata deliberatamente nascosta a voi.

objEarlyBound e objLateBound sono necessari per avere la stessa identità, ovvero == su di essi restituirà true. Quindi da ognuno di essi è sempre possibile ottenere l'altro, e idem per qualsiasi altra interfaccia che supportano, e anche se si assegna uno di loro a object. Ma questo non prova molto.

Se si fa riferimento direttamente l'assembly contenente la classe che viene esposta tramite COM come My.ProgId, si potrebbe dire:

IMyInterface objEarlyBound = new MyClassExposedThroughCOM(); 

A questo punto il supporto COM del CLR non è stata richiesta a tutti. Ma potreste passare quell'oggetto ad una libreria COM esterna, e a quel punto il CLR creerebbe un CCW da associare all'oggetto. E una volta fatto, può sempre tornare alla stessa CCW per ogni dato oggetto CLR.

Quindi per metterlo in relazione con il tuo esempio, si avvia con un RCW attorno ad un oggetto COM, lo si lancia su un'interfaccia e, a quel punto, il CLR potrebbe (per quanto ne sappiamo) interrogare per un'interfaccia COM interna speciale che , se trovato, consente di ottenere l'oggetto CLR interno e quindi di ignorare completamente COM da quel momento in poi. Se in qualsiasi momento ha bisogno di tornare al CCW, può farlo, in quanto deve essere in grado di farlo in qualsiasi momento quando si lavora nella direzione opposta.

Ho provato a inserire un punto di interruzione in una funzione QueryInterface dell'oggetto COM C++ implementato a mano, per vedere a cosa servono le richieste CLR. Praticamente cerca un sacco di cose, alcune delle quali non sono stato in grado di identificare immediatamente, quindi potrebbe benissimo essere "sniffing" per un altro oggetto CLR. Ha senso farlo, per evitare una pazza situazione a sandwich COM, in cui un riferimento CLR punta a un RCW, che punta a un CCW, che punta a un oggetto CLR. Questo può essere chiaramente semplificato avendo il riferimento CLR puntare direttamente all'oggetto CLR.

In realtà ora penso a questo proposito, non ha bisogno di interrogare per scoprirlo: ha una tabella globale di CCWs che ha generato in precedenza, in modo che possa solo cercare qualsiasi nuova IUnknown in là. Gli oggetti COM devono restituire sempre lo stesso identico indirizzo per IUnknown in modo che possa essere utilizzato per il confronto dell'identità dell'oggetto. Quindi, il CLR può sempre riconoscere un oggetto COM che sta implementando sé stesso e ottenere l'oggetto CLR corrispondente.

A proposito, tutta questa discussione presuppone che l'oggetto COM sia in-process. Se è out-of-process, la situazione è completamente diversa; ogni processo ha una propria istanza CLR e quindi può anche utilizzare l'implementazione COM del marshalling dei processi.

+0

Questo è interessante e utile, grazie. Posso dirlo in testa e dire, se prendo objLateBound dal mio esempio qui sopra, e chiamarlo usando objLateBound.InvokeMember ("Metodo", ...) come influisce sulle cose? Sarebbe sempre una chiamata attraverso il CCW, o pensi ancora che il CLR potrebbe essere abbastanza intelligente da annusare la classe .NET e usarla direttamente? –

3

RCW di dovrebbe essere (da quello che so) di tipo speciale sistema di .__ ComObject, ma probabilmente quello che si vuole fare è chiamare Marshal.IsComObject che vi dirà se l'oggetto è un wrapper di runtime o meno.In un test rapido, un oggetto creato dalla COM tramite quel percorso finisce come oggetto gestito diretto e perde il wrapper COM.

Problemi correlati