2010-03-04 19 views
7

Una pregunta interesante surgió hoy. Digamos que tengo un objeto .NET que implementa una cierta interfaz IMyInterface y también es COM Visible.¿Estoy llamando a un objeto .NET o un objeto COM?

Ahora, me carga el tipo de su identificador de programa y convertirse a un interfaz inflexible de tipos, así:

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

objEarlyBound= (IMyInterface)objLateBound; 

objEarlyBound.Method(); 

Si ejecuto el código anterior, cuando objEarlyBound.Method() ejecuta, estoy llamando en un objeto COM o directamente en el objeto .NET? ¿Cómo puedo probar esto de una forma u otra?

Respuesta

2

No se puede demostrar mucho: es una opción de implementación interna que se le ha ocultado deliberadamente.

objEarlyBound y objLateBound se requieren para tener la misma identidad, es decir == en ellos devolverá verdadero. Por lo tanto, de cada uno de ellos siempre puede obtener el otro, y lo mismo para cualquier otra interfaz que admita, y también si asigna cualquiera de ellos al object. Pero eso no prueba mucho.

Si directa referencia al ensamblado que contiene la clase que se expone a través de COM como My.ProgId, se podría decir:

IMyInterface objEarlyBound = new MyClassExposedThroughCOM(); 

En este punto de apoyo COM del CLR no se ha exigido en absoluto. Pero luego podría pasar ese objeto a una biblioteca COM externa, y en ese punto el CLR crearía una CCW para asociarlo con el objeto. Y una vez hecho esto, siempre puede regresar a la misma CCW para cualquier objeto CLR dado.

Para relacionar eso con su ejemplo, comienza con un RCW alrededor de un objeto COM, lo transfiere a una interfaz, y en ese momento el CLR podría (por lo que sabemos) consultar una interfaz COM interna especial que , si se encuentra, permite que se adhiera al objeto CLR interno y, por lo tanto, omite COM por completo a partir de ese momento. Si en algún momento necesita volver a la CCW, puede hacerlo, ya que debe poder hacerlo en cualquier momento cuando trabaje en la otra dirección.

He intentado poner un punto de interrupción en una función QueryInterface del objeto COM de C++ implementado a mano, para ver qué consulta el CLR. Básicamente, prueba muchas cosas, algunas de las cuales no pude identificar de inmediato, por lo que bien podría ser "olfatear" para un objeto compañero CLR. Tiene sentido que lo haga, para evitar una loca situación de sándwich COM, en la que una referencia CLR apunta a un RCW, que apunta a una CCW, que apunta a un objeto CLR. Esto se puede simplificar claramente haciendo que la referencia CLR simplemente apunte directamente al objeto CLR.

En realidad, ahora que lo pienso, no necesita consultar para descubrir esto: tiene una tabla global de CCW que ha generado previamente, por lo que puede buscar cualquier nuevo IUnknown allí. Se requiere que los objetos COM devuelvan siempre la misma dirección exacta para IUnknown, de modo que se pueda usar para la comparación de identidad de objetos. Por lo tanto, el CLR siempre puede reconocer un objeto COM que se está implementando y obtener el objeto CLR correspondiente.

Por cierto, toda esta discusión asume que el objeto COM está en proceso. Si está fuera de proceso, la situación es totalmente diferente; cada proceso tiene su propia instancia de CLR y, por lo tanto, también puede usar la implementación COM de clasificación interproceso.

+0

Eso es interesante y útil, gracias. ¿Puedo soportarlo en su cabeza decir, si tomo objLateBound de mi ejemplo anterior, y llamar a él usando objLateBound.InvokeMember ("Método", ...) ¿cómo afecta eso las cosas? ¿Sería eso una llamada a través de la CCW, o aún crees que la CLR podría ser lo suficientemente inteligente como para olfatear la clase .NET y usarla directamente? –

3

RCW debe ser (por lo que sé) del tipo especial System .__ ComObject, sin embargo, probablemente lo que quiere hacer es llamar al Marshal.IsComObject que le dirá si el objeto es un contenedor de tiempo de ejecución o no.En una prueba rápida, un objeto creado por COM a través de esa ruta termina como un objeto administrado directo y pierde el contenedor COM.

Cuestiones relacionadas