¿Cómo detecta el compilador de C# los tipos COM?

Resuelto Jon Skeet asked hace 15 años • 4 respuestas

EDITAR: He escrito los resultados como una publicación de blog .


El compilador de C# trata los tipos COM de forma algo mágica. Por ejemplo, esta afirmación parece normal...

Word.Application app = new Word.Application();

... hasta que te das cuenta de que Applicationes una interfaz. ¿Llamar a un constructor en una interfaz? ¡Yoiks! En realidad, esto se traduce en una llamada a Type.GetTypeFromCLSID()y otra a Activator.CreateInstance.

Además, en C# 4, puedes usar argumentos que no sean de referencia para reflos parámetros, y el compilador simplemente agrega una variable local para pasar por referencia, descartando los resultados:

// FileName parameter is *really* a ref parameter
app.ActiveDocument.SaveAs(FileName: "test.doc");

(Sí, faltan muchos argumentos. ¿No son buenos los parámetros opcionales? :)

Estoy intentando investigar el comportamiento del compilador y no logro falsificar la primera parte. Puedo hacer la segunda parte sin problema:

using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

[ComImport, GuidAttribute("00012345-0000-0000-0000-000000000011")]
public interface Dummy
{
    void Foo(ref int x);
}

class Test
{
    static void Main()
    {
        Dummy dummy = null;
        dummy.Foo(10);
    }
}

Me gustaría poder escribir:

Dummy dummy = new Dummy();

aunque. Obviamente explotará en el momento de la ejecución, pero está bien. Sólo estoy experimentando.

Los otros atributos agregados por el compilador para COM PIA vinculados ( CompilerGeneratedy TypeIdentifier) no parecen funcionar... ¿cuál es la salsa mágica?

Jon Skeet avatar Jul 08 '09 00:07 Jon Skeet
Aceptado

De ninguna manera soy un experto en esto, pero recientemente me topé con lo que creo que quieres: la clase de atributo CoClass .

[System.Runtime.InteropServices.CoClass(typeof(Test))]
public interface Dummy { }

Una coclase proporciona implementaciones concretas de una o más interfaces. En COM, estas implementaciones concretas se pueden escribir en cualquier lenguaje de programación que admita el desarrollo de componentes COM, por ejemplo, Delphi, C++, Visual Basic, etc.

Vea mi respuesta a una pregunta similar sobre Microsoft Speech API , donde puede "crear una instancia" de la interfaz SpVoice(pero en realidad, está creando una instancia SPVoiceClass).

[CoClass(typeof(SpVoiceClass))]
public interface SpVoice : ISpeechVoice, _ISpeechVoiceEvents_Event { }
Michael Petrotta avatar Jul 07 '2009 17:07 Michael Petrotta

Entre Michael y tú casi habéis juntado las piezas. Creo que así es como funciona. (No escribí el código, por lo que podría estar expresándolo un poco mal, pero estoy bastante seguro de que así es como funciona).

Si:

  • eres "nuevo" en un tipo de interfaz, y
  • el tipo de interfaz tiene una coclase conocida, y
  • ESTÁS usando la función "no pia" para esta interfaz

luego el código se genera como (IPIAINTERFACE)Activator.CreateInstance(Type.GetTypeFromClsid(GUID OF COCLASSTYPE))

Si:

  • eres "nuevo" en un tipo de interfaz, y
  • el tipo de interfaz tiene una coclase conocida, y
  • NO ESTÁS utilizando la función "no pia" para esta interfaz

luego el código se genera como si hubieras dicho "nuevo COCLASSTYPE()".

Jon, no dudes en molestarnos a mí o a Sam directamente si tienes preguntas sobre este tema. Para su información, Sam es el experto en esta función.

Eric Lippert avatar Jul 07 '2009 18:07 Eric Lippert