EDIT: Ich habe die Ergebnisse als Blog-Beitrag geschrieben .
Der C # -Compiler behandelt COM-Typen etwas magisch. Zum Beispiel sieht diese Aussage normal aus ...
Word.Application app = new Word.Application();
... bis Sie erkennen, dass dies Application
eine Schnittstelle ist. Einen Konstruktor auf einer Schnittstelle aufrufen? Yoiks! Dies wird tatsächlich in einen Anruf an Type.GetTypeFromCLSID()
und einen anderen an übersetzt Activator.CreateInstance
.
Darüber hinaus können Sie in C # 4 Nicht-Ref-Argumente für ref
Parameter verwenden, und der Compiler fügt lediglich eine lokale Variable hinzu, die als Referenz übergeben werden soll, und verwirft die Ergebnisse:
// FileName parameter is *really* a ref parameter
app.ActiveDocument.SaveAs(FileName: "test.doc");
(Ja, es fehlen eine Reihe von Argumenten. Sind optionale Parameter nicht nett? :)
Ich versuche, das Verhalten des Compilers zu untersuchen, und ich kann den ersten Teil nicht vortäuschen. Ich kann den zweiten Teil ohne Probleme machen:
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);
}
}
Ich möchte schreiben können:
Dummy dummy = new Dummy();
obwohl. Natürlich wird es zur Ausführungszeit knallen, aber das ist okay. Ich experimentiere nur.
Die anderen Attribute, die der Compiler für verknüpfte COM PIAs ( CompilerGenerated
und TypeIdentifier
) hinzugefügt hat, scheinen nicht den Trick zu tun ... Was ist die magische Sauce?
quelle
dynamic
... finden. Wir sind einfach zu sehr an statisches / starkes Tippen gewöhnt, um zu sehen, warum es außerhalb von COM wichtig ist.Antworten:
Ich bin kein Experte in diesem Bereich, aber ich bin kürzlich über das gestolpert, was Sie meiner Meinung nach wollen: die CoClass- Attributklasse.
Siehe meine Antwort auf eine ähnliche Frage zur Microsoft Speech API , bei der Sie die Benutzeroberfläche "instanziieren" können
SpVoice
(aber wirklich, Sie instanziierenSPVoiceClass
).quelle
Zwischen dir und Michael hast du fast die Teile zusammengesetzt. Ich denke, so funktioniert es. (Ich habe den Code nicht geschrieben, daher könnte ich ihn leicht falsch ausdrücken, aber ich bin mir ziemlich sicher, dass dies so ist.)
Wenn:
dann wird der Code als (IPIAINTERFACE) Activator.CreateInstance (Type.GetTypeFromClsid (GUID OF COCLASSTYPE)) generiert.
Wenn:
dann wird der Code so generiert, als hätten Sie "new COCLASSTYPE ()" gesagt.
Jon, zögern Sie nicht, mich oder Sam direkt zu nerven, wenn Sie Fragen zu diesem Zeug haben. Zu Ihrer Information, Sam ist der Experte für diese Funktion.
quelle
Okay, dies ist nur, um Michaels Antwort ein bisschen mehr Fleisch zu verleihen (er kann es gerne hinzufügen, wenn er möchte, in diesem Fall werde ich diese entfernen).
Bei der Betrachtung der ursprünglichen PIA für Word.Application handelt es sich um drei Typen (Ignorieren der Ereignisse):
Es gibt zwei Schnittstellen aus Gründen, über die Eric Lippert in einer anderen Antwort spricht . Und da ist, wie Sie sagten, das
CoClass
- sowohl in Bezug auf die Klasse selbst als auch auf das Attribut auf derApplication
Schnittstelle.Wenn wir nun die PIA-Verknüpfung in C # 4 verwenden, ist ein Teil davon in die resultierende Binärdatei eingebettet ... aber nicht alles. Eine Anwendung, die nur eine Instanz von erstellt, hat folgende
Application
Typen:Nein
ApplicationClass
- vermutlich, weil dies zur Ausführungszeit dynamisch vom realen COM-Typ geladen wird.Eine weitere interessante Sache ist der Unterschied im Code zwischen der verknüpften Version und der nicht verknüpften Version. Wenn Sie die Zeile dekompilieren
in der referenzierten Version endet es als:
in der verlinkten Version endet es als
So sieht es aus wie die „echte“ PIA das braucht
CoClass
Attribut, aber die verknüpfte Version nicht , weil es nicht ist eineCoClass
der Compiler kann tatsächlich Referenz. Es muss es dynamisch machen.Ich könnte versuchen, eine COM-Schnittstelle mit diesen Informationen zu fälschen und zu sehen, ob ich den Compiler dazu bringen kann, sie zu verknüpfen ...
quelle
Nur um Michaels Antwort ein wenig zu bestätigen:
Der folgende Code wird kompiliert und ausgeführt:
Sie brauchen sowohl das
ComImportAttribute
als auch das,GuidAttribute
damit es funktioniert.Beachten Sie auch die Informationen, wenn Sie mit der Maus über
new IFoo()
: Intellisense nimmt die Informationen richtig auf: Schön!quelle