Natrafiłem na ten interesujący artykuł: How I Came to Love COM Interoperability on CodeProject, co skłoniło mnie do myślenia ...
Autor twierdzi, że nie chce żadnych COM w swojej bibliotece .NET, ponieważ odbiera to piękno ich biblioteki .NET. Zamiast tego wolą napisać osobną bibliotekę Interop, która udostępnia ich bibliotekę .NET COM. Ta biblioteka Interop poradziłaby sobie z faktem, że COM nie obsługuje konstruktorów z parametrami, metodami przeładowanymi, rodzajowymi, dziedziczeniem, metodami statycznymi itp.
I choć myślę, że jest to bardzo nowatorskie, czy to nie tylko komponuje projekt?
- Teraz musisz przetestować jednostkę bibliotekę .NET ORAZ bibliotekę Interop.
- Teraz musisz poświęcić czas na zastanawianie się, jak obejść swoją piękną bibliotekę .NET i udostępnić ją COM.
- Musisz podwoić lub potroić liczbę swoich klas.
Z pewnością rozumiem, czy potrzebujesz swojej biblioteki do obsługi zarówno COM, jak i non-COM. Jeśli jednak zamierzasz używać modelu COM, czy tego rodzaju konstrukcja przynosi korzyści, których nie widzę? Czy zyskujesz tylko zalety języka C #?
A może ułatwia wersjonowanie biblioteki, zapewniając opakowanie? Czy sprawia, że testy jednostkowe przebiegają szybciej, ponieważ nie wymagają użycia COM?
źródło
Odpowiedzi:
Ten fragment pytania jest tutaj najważniejszą częścią decyzji projektowej, a odpowiedź jest (jak zawsze) zależna .
Jeśli zamierzasz korzystać z biblioteki tylko przez COM Interop, powinieneś zaprojektować cały system, mając to na uwadze. Nie ma powodu, aby trzykrotnie zwiększyć liczbę linii. Im więcej LoC w systemie, tym więcej będzie wad. Dlatego należy zaprojektować system tak, aby korzystał tylko z funkcji zgodnych z COM.
Jednak , nie mogę myśleć o dobry powód, aby ograniczyć korzystanie z biblioteki .NET do COM. Dlaczego nie chcesz mieć możliwości używania zestawu w innym kodzie .Net? Ograniczanie się w ten sposób nie ma sensu.
Mam z tym pewne doświadczenie, więc podzielę się tym, jak sobie z tym poradziłem. Z pewnością nie jest idealny. Dokonałem pewnych kompromisów. Używam tylko elewacji dla klas COM (naprawdę interfejsy), które są niezgodne z nowszymi idiomami .Net, w przeciwnym razie bezpośrednio udostępniam interfejs .Net COM. Zasadniczo oznacza to, że używam elewacji dla każdego interfejsu, który używa ogólnych. Generics to jedyna rzecz, na którą się natknąłem, która jest po prostu niekompatybilna. Niestety oznacza to fasadę dla wszystkiego, co zwraca
IEnumerable<T>
, co jest dość powszechne.Jednak nie jest to wcale tak złe, jak się wydaje, ponieważ klasa elewacji dziedziczy po klasie .Net i implementuje określony interfejs Interop. Coś takiego.
Dzięki temu zduplikowany kod jest absolutnie minimalny i chroni interfejs COM przed „niezamierzonymi” zmianami. Gdy zmienia się podstawowa klasa / interfejs, klasa adaptera musi opanować więcej metod (lub przerwać interfejs i podważyć główny numer wersji). Z drugiej strony nie cały kod Interopa jest przechowywany w
Interop
przestrzeni nazw, co może prowadzić do mylącej organizacji plików. Tak jak powiedziałem, to kompromis.Aby uzyskać pełny przykład tego, możesz przeglądać foldery SourceControl i Interop mojego repozytorium.
ISourceControlProvider
iGitProvider
będą szczególnie interesujące.źródło
IEnumerable
do VBA? Ponadto,Rubberduck.Interop.GitProvider
dlaczego zdefiniowałeś sparametryzowane konstruktory, jeśli COM ich nie obsługuje?IEnumerable
COM, ale musi to być starsza, ogólna wersja. Jeśli chodzi o konstruktorów, spójrz naSourceControlClassFactory
. Zasadniczo fałszujesz go, inicjując instancję klasy, która nie potrzebuje parametrów dla jej ctor i wykorzystując ją do uzyskania dostępu do nowych instancji klas interfejsu API.ComVisible(true)
klasach / interfejsach, które nie obsługuje COM, jest po prostu „ignorowane”? Zgaduję również, jeśli masz klasę o tej samej nazwie zdefiniowaną w wielu przestrzeniach nazw, musisz podać unikat,ProgId
jeśli chcesz ujawnić więcej niż jedną z nich?static
metody są ignorowane. Próbuję sprawdzić, czy jest dostępny odpowiednik VB6VB_PredeclaredId
. Myślę, że może być możliwe utworzenie domyślnej instancji.Ten autor potrzebuje buziaka w twarz. Celem każdego profesjonalnego projektu jest stworzenie działającego oprogramowania, z którego ludzie chcą korzystać. Wszelkie błędne ideały dotyczące piękna pojawiają się długo potem. Jeśli to ich jedyne uzasadnienie, autor stracił całą wiarygodność.
Umiejętność oznaczania swoich klas jako widocznych i możliwość komunikowania się z kodem .NET przez COM jest niezwykle przydatna. Odrzucenie tej wielkiej korzyści dla produktywności dla piękna jest szalone.
Jednak sprawienie, by rzeczy działały z COM, wymaga pewnych kompromisów, wymaganie konstruktora bez argumentu jest jednym z nich, a niektóre z innych rzeczy, o których wspomniałeś. Jeśli są to funkcje, których i tak nie używasz, lub nie zaszkodzi ci ich nieużywanie, wtedy musisz zaoszczędzić dużo pracy, używając tej samej klasy dla COM i non com.
Z drugiej strony, jeśli Twoi klienci COM oczekują zupełnie innego interfejsu, mają zależności lub inne ograniczenia, które są nieprzyjemne w przypadku klas .NET, lub oczekujesz, że znacząco zmienisz swoje klasy .NET i będziesz musiał zachować COM - kompatybilność, a następnie należy stworzyć klasę Interop, aby wypełnić tę lukę.
Ale nie myśl o „pięknie”. Możliwość ujawnienia COM przez .NET ma na celu zaoszczędzić ci pracy. Nie twórz więcej pracy dla siebie.
źródło
Set oObject = MyCOMInterop.NewMyClass()
bez konieczności tworzenia nowego obiektu Factory?Cóż, szczerze mówiąc, autor tego artykułu nie użył słowa „piękno” nigdzie w swoim artykule, to byłeś ty, co może wywrzeć na nim stronnicze wrażenie w przypadku tych, którzy nie poświęcili czasu na przeczytanie artykułu sami.
O ile rozumiem ten artykuł, biblioteka .NET już istniała i została napisana z myślą o COM - prawdopodobnie dlatego, że w momencie tworzenia biblioteki nie było wymogu obsługi COM.
Później wprowadzono dodatkowy wymóg obsługi COM. W takiej sytuacji masz dwie opcje:
przeprojektuj oryginalną bibliotekę lib, aby była kompatybilna z interfejsem COM (z ryzykiem uszkodzenia)
pozwól oryginalnej bibliotece roboczej przeważnie taką jaka jest, a zamiast tego utwórz oddzielny zespół z funkcją „otoki” (lub „adaptera”)
Tworzenie opakowań lub adapterów jest dobrze znanym wzorcem projektowym (lub w tym przypadku bardziej wzorem architektonicznym), a zalety i wady są również dobrze znane. Jednym z argumentów przemawiających za tym jest lepsze „rozdzielenie obaw”, a to nie ma nic wspólnego z pięknem.
Do twoich obaw
Po wprowadzeniu interfejsu COM do istniejącej biblioteki .NET poprzez przeprojektowanie, należy przetestować ten interfejs. Wprowadzenie ręcznie napisanego adaptera może oczywiście wymagać dodatkowych testów działania interfejsu, ale nie ma potrzeby kopiowania wszystkich testów jednostkowych podstawowej funkcjonalności biznesowej biblioteki lib. Nie zapominaj, że to tylko kolejny interfejs do lib.
Kiedy trzeba przeprojektować oryginalną bibliotekę, trzeba to również wymyślić i myślę, że będzie to o wiele więcej pracy.
Tylko dla klas, które są udostępniane przez publiczny interfejs COM, który powinien być niewielką liczbą klas należących do oryginalnej biblioteki.
Powiedział, że w innej sytuacji, o której wspomniałeś, kiedy już wiesz, że musisz wspierać COM jako obywatel pierwszej klasy od samego początku, myślę, że masz rację: należy zaoszczędzić kłopotów z dodaniem oddzielnej biblioteki lib i zaprojektować .NET lib z obsługą COM bezpośrednio.
źródło