2013-02-21 15 views
10

Teraz jestem świadomy, że jeśli biblioteka jest w .NET, jest to trochę bezsensowne, aby uzyskać do niej dostęp za pośrednictwem COM, jednak jestem nieco zakłopotany, ponieważ gdybym poprosił kogoś o napisanie biblioteki i odsłonięcie jej przez COM , ta osoba powinna mieć do tego prawo z dowolnym językiem.Dlaczego biblioteka .NET COM nie może być używana przez COM w .NET?

Nie ma dla mnie znaczenia, w jakim języku jest napisana biblioteka COM, więc dlaczego ma to znaczenie?

Dla porównania, jest to, co się dzieje, gdy używasz tlbimp na pliku wygenerowanego .tlb z biblioteki .NET:

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. 

Dodatkowo moja próba biblioteki COM używa IUnknown, wspierając tylko wcześnie związany współdziałanie COM .

+0

pst: Narzędzie tlbimp.exe nie zezwala na import typów. – Arafangion

+0

pst: Jak inaczej można użyć biblioteki .NET COM przez COM w .NET? – Arafangion

+0

tlbimp.exe to narzędzie do automatycznego wyodrębniania/budowania powiązań. Nie jest to wymagane, a cały proces można wykonać ręcznie, tak jak w przypadku każdego innego interfejsu COM używanego w .NET. –

Odpowiedz

11

tlbimp to tylko początek problemu.

Każdy widoczny obiekt COM .NET implementuje obiekt IManagedObject. Za każdym razem, gdy próbujesz wywołać obiekt za pośrednictwem interfejsu COM, .NET wykonuje QueryInterface dla obiektu IManagedObject, a jeśli mu się to uda, obiekt jest rozpakowywany i uzyskuje bezpośredni dostęp do niego. Wyeliminowanie połączenia interop w ten sposób jest uważane za optymalizację wydajności.

Jest to poważny problem w scenariuszach współdziałających z COM, w których wiele komponentów może być implementowanych w językach .NET. Jeśli każdy składnik .NET implementuje własną wersję interfejsu COM generowaną przez tlbimp, nie będą one mogły komunikować się ze sobą za pomocą tego interfejsu. Chociaż każda tlbimp'ed kopia interfejsu ma ten sam COM GUID, .NET uważa je za osobne interfejsy. "Prawidłowe" rozwiązanie tego problemu polega na zdefiniowaniu interfejsu COM w głównym zespole współdziałania, a każdy komponent zaimplementowany w technologii .NET używa tej samej kopii interfejsu, ale jeśli nie ma koordynacji między programistami składników, jest mało prawdopodobne.

Ten problem został wyróżniony przez programistę Microsoft pod numerem http://blogs.msdn.com/b/jmstall/archive/2009/07/09/icustomqueryinterface-and-clr-v4.aspx wraz z rozwiązaniem dla platformy .NET 4, ale był oparty na wersji przedpremierowej i nie działa w wersji ostatecznej. Nie wiem, gdzie indziej został uznany przez Microsoft.

Jednym z rozwiązań jest rezygnacja z interfejsu w scenariuszu .NET-to-.NET i użycie zamiast niego refleksji. Może to działać w wielu przypadkach, ale oczywiście nie jest zbyt wydajne. Prawdopodobnie najlepszym rozwiązaniem jest użycie niezarządzanego kodu do agregowania każdego zarządzanego komponentu i odrzucenia prób QueryInterface dla obiektu IManagedObject. Jest to podobne do opisanego w powyższym wpisie blogu, ale nie polega na funkcjach .NET, które nie działają zgodnie z opisem na tym blogu.

Zachowanie interakcji .NET jest, IMO, dość przerażające i wyraźnie narusza reguły COM (ten sam interfejs IID == i nie powinien się troszczyć o to, w jakim języku obiekt jest zaimplementowany). Ale .NET zachowywał się w ten sposób od samego początku i żadna informacja zwrotna od deweloperów pogrążonych w tym zachowaniu nie zmieniła umysłu kogokolwiek z zespołu .NET.

+0

Bah, to jest do bani. Czy możesz podać referencje? – Arafangion

+0

Sucky wszechstronnie. Czy możesz umieścić te odniesienia w powyższej odpowiedzi, a otrzymasz nagrodę. – Arafangion

+0

Scalono wszystko razem. Niestety, nie używałem tak dużo i nadal nie jestem przyzwyczajony do edycji zamiast publikowania. –

4

Tlbimp może zobaczyć z biblioteki typów, że został on wyprodukowany z zestawu .NET. To po prostu zacina się na tym, co próbujesz zrobić. Co nie ma sensu, jeśli chcesz użyć zestawu .NET, po prostu dodaj do niego odniesienie.

Można oszukać komputer za pomocą późno związanego COM, najłatwiej zrobić słowem kluczowym dynamic w języku C#. To nadal nie oszukuje środowiska CLR, może zobaczyć, że współdziała z zarządzanym wirtualnym zbiorem i faktycznie nie tworzy opakowania COM do wywoływania. Najczęściej robi się to, aby napisać program testowy, aby przetestować serwer COM. Wynika z tego, że twój test faktycznie nie testuje sposobu, w jaki twój serwer COM będzie używany w praktyce. Bardzo podstawowe rzeczy, takie jak konwertowanie wariantów na obiekty i powrót, nie będą w ogóle testowane. I może również dać bardzo nieprzyjemne niespodzianki podczas korzystania z montażu w produkcji.

+0

Ale opóźnione połączenie COM działa tylko z IDispatch, IUnknown wymaga wczesnego powiązania COM; Rzeczywiście, do testowania systemu chcę używać interfejsów COM. – Arafangion

+0

Dostajesz IDispatch za darmo, więc nie ma sensu go unikać. Ale wyraźnie moje uwagi dotyczące testowania zdecydowanie mają zastosowanie tutaj. –

+0

Aplikacja kliencka użyje IUnknown, więc unikanie IDispatch oznacza zmuszanie moich testów do używania interfejsu IUnknown. – Arafangion

Powiązane problemy