2013-02-21 4 views
10

Nun, ich weiß, wenn die Bibliothek in .NET ist, ist es ein wenig sinnlos, über COM darauf zuzugreifen, aber ich bin etwas perplex, weil ich jemanden bitten würde, eine Bibliothek zu schreiben und sie über COM zu enthüllen Diese Person sollte das in jeder Sprache tun können.Warum kann eine .NET COM-Bibliothek nicht über COM in .NET verwendet werden?

Es sollte mir egal sein, in welcher Sprache die COM-Bibliothek geschrieben ist, also warum ist es wichtig?

Als Referenz ist das, was passiert, wenn man auf einer TLB-Datei aus einer .NET-Bibliothek erzeugt verwenden tlbimp:

C:\dev>tlbimp test.tlb 
Microsoft (R) .NET Framework Type Library to Assembly Converter 4.0.30319.1 
Copyright (C) Microsoft Corporation. All rights reserved. 

TlbImp : error TI1029 : Type library 'test' was exported from 
a CLR assembly and cannot be re-imported as a CLR assembly. 

Zusätzlich mein Test COM-Bibliothek verwendet IUnknown, nur früh gebundenes COM-Interop unterstützt .

+0

pst: Die tlbimp.exe weigert sich, die Typen importieren zu lassen. – Arafangion

+0

pst: Wie sonst würden Sie eine .NET COM-Bibliothek über COM in .NET verwenden? – Arafangion

+0

tlbimp.exe ist nur ein Tool zum automatischen Extrahieren/Erstellen von Bindungen. Es ist nicht erforderlich und der gesamte Prozess kann wie bei jeder anderen in .NET verwendeten COM-Schnittstelle von Hand ausgeführt werden. –

Antwort

11

tlbimp ist nur der Anfang des Problems.

Jedes COM-sichtbare .NET-Objekt implementiert IManagedObject. Jedes Mal, wenn Sie versuchen, ein Objekt über eine COM-Schnittstelle aufzurufen, führt .NET ein QueryInterface für IManagedObject aus, und wenn es erfolgreich ist, wird das Objekt ausgepackt und direkt darauf zugegriffen. Die Eliminierung des Interop-Aufrufs auf diese Weise wird als Leistungsoptimierung angesehen.

Dies ist ein schwerwiegendes Problem in COM-basierten Interop-Szenarien, wo mehrere Komponenten in .NET-Sprachen implementiert werden können. Wenn jede .NET-Komponente eine eigene tlbimp-generierte Version der COM-Schnittstelle implementiert, können sie über diese Schnittstelle nicht miteinander kommunizieren. Obwohl jede DLL-Kopie der Schnittstelle die gleiche COM-GUID aufweist, betrachtet .NET sie als separate Schnittstellen. Die "richtige" Lösung für dieses Problem besteht darin, die COM-Schnittstelle in einer primären Interop-Assembly zu definieren und jede .NET-implementierte Komponente dieselbe Kopie der Schnittstelle verwenden zu lassen. Wenn es keine Koordination zwischen den Komponentenentwicklern gibt, ist dies eher unwahrscheinlich.

Dieses Problem wurde einmal von einem Microsoft-Entwickler unter http://blogs.msdn.com/b/jmstall/archive/2009/07/09/icustomqueryinterface-and-clr-v4.aspx zusammen mit einer Lösung für .NET 4 hervorgehoben, aber es basierte auf einer Vorabversion und funktioniert nicht im endgültigen. Ich bin mir nicht bewusst, wo sonst es von Microsoft bestätigt wurde.

Eine Lösung besteht darin, auf die Schnittstelle im .NET-zu-.NET-Szenario zu verzichten und stattdessen Reflektion zu verwenden. Dies kann in vielen Fällen funktionieren, ist aber natürlich nicht sehr performant. Die möglicherweise beste Lösung besteht darin, nicht verwalteten Code zu verwenden, um alle verwalteten Komponenten zu aggregieren und Versuche von QueryInterface für IManagedObject abzulehnen. Dies ist ähnlich wie im obigen Blogeintrag beschrieben, basiert jedoch nicht auf .NET-Funktionen, die nicht mehr wie in diesem Blog beschrieben funktionieren.

Das .NET-Interop-Verhalten ist, IMO, ziemlich schrecklich und verstößt eindeutig gegen COM-Regeln (gleiche IID == gleiche Schnittstelle, und sollte sich nicht darum kümmern müssen, in welcher Sprache das Objekt implementiert ist). Aber .NET hat sich von Anfang an so verhalten und keine Menge Feedback von Entwicklern, die durch dieses Verhalten gebissen wurden, hat die Meinung von irgendjemandem im .NET Team verändert.

+0

Bah, das ist scheiße. Können Sie Referenzen angeben? – Arafangion

+0

Sucky Allround. Könnten Sie diese Hinweise in die obige Antwort schreiben, dann erhalten Sie das Kopfgeld. – Arafangion

+0

Alles zusammengefügt. Entschuldigung, ich habe SO nicht viel benutzt und bin immer noch nicht daran gewöhnt, zu editieren anstatt zu posten. –

4

Tlbimp kann anhand der Typbibliothek sehen, dass es aus einer .NET-Assembly erstellt wurde. Es ist nur schlecht bei dem, was Sie versuchen zu tun. Was nicht sinnvoll ist, wenn Sie eine .NET Assembly verwenden möchten, fügen Sie einfach einen Verweis hinzu.

Sie können die Maschine täuschen, indem Sie spät gebundene COM verwenden, am einfachsten mit dem dynamischen Schlüsselwort in C#. Das täuscht die CLR immer noch nicht, es kann sehen, dass es mit einer verwalteten Assembly interagiert und den COM-aufrufbaren Wrapper nicht tatsächlich erstellt. In der Regel schreiben Sie ein Testprogramm, um Ihren COM-Server zu testen. Die Implikation ist, dass Ihr Test nicht tatsächlich die Art und Weise testet, wie Ihr COM-Server in der Praxis verwendet wird. Sehr einfache Dinge wie das Konvertieren von Varianten in Objekte und zurück werden einfach nicht getestet. Und möglicherweise können Sie sehr unangenehme Überraschungen erleben, wenn Sie die Baugruppe in der Produktion verwenden.

+0

Aber spät gebundene COM funktioniert nur mit IDispatch, IUnknown erfordert früh gebundene COM; In der Tat ist es für Systemtests, dass ich die COM-Schnittstellen verwenden möchte. – Arafangion

+0

Nun, Sie erhalten IDispatch kostenlos, also hat es wenig Sinn, es zu vermeiden. Aber klar meine Anmerkungen zum Testen gelten hier stark. –

+0

Die Client-Anwendung verwendet IUnknown. IDispatch zu vermeiden bedeutet, dass ich meine Tests für die Verwendung der IUnknown-Schnittstelle erzwinge. – Arafangion

Verwandte Themen