Mam projekt pomocnika, którego używam we wszystkich tworzonych przeze mnie aplikacjach. Zawiera kilka metod rozszerzenia i kilka ogólnych klas pomocników, kontroli itp. Od czasu do czasu aktualizuję / rozszerzam projekt pomocnika. Są to zwykle małe i niepowiązane ze sobą projekty, a ja jestem jedyną osobą, która nad nimi pracuje.
Wypróbowałem dwa podejścia do korzystania z niego
- dodaj pliki .cs bezpośrednio (Dodaj jako link) do każdego projektu, w którym ich używam
- skompiluj go jako .dll i dodaj jako odniesienie
Widzę pewne zalety i wady tych podejść.
Pierwszy:
- jest prostsze, ponieważ klasy pomocnicze są kompilowane do pliku exe, dlatego często bardzo łatwo mogę dostarczyć tylko jeden plik .exe, który będzie działał dobrze. Ponieważ dodaję jako łącze, mogę być całkiem pewien, że za każdym razem, gdy buduję projekt korzystający z pomocnika, pliki pomocnika będą najnowszą wersją.
- jest jeszcze prostsze, ponieważ mogę oddzielić pliki, dzięki czemu do moich metod rozszerzenia, które działają dobrze w .NET 4.0, można się odwoływać oddzielnie od tych, które wymagają .NET 4.5, co oznacza, że aplikacja jako całość może działać w .NET 4.0
- Umożliwia debugowanie za pomocą kodu, ze wszystkimi zaletami punktów przerwania itp. Itp.
- nie wydaje się być „najlepszą praktyką”
Drugie:
- wydaje się być właściwym podejściem, ale:
- wymaga ode mnie dostarczenia osobnego pliku .dll, który z jakiegoś powodu jest znacznie trudniejszy dla użytkowników (zwykle udostępniają moje programy bez pliku .dll, który następnie ulega awarii podczas uruchamiania)
- ponieważ zostanie skompilowany w pojedynczą bibliotekę .dll, będzie wymagał najwyższej wersji .NET - wielu moich użytkowników nie ma .NET 4.5 i wymagają tego tylko niektóre elementy mojej klasy pomocniczej, co oznacza, że mogę zmusić niektóre osoby aktualizować swoje systemy bez powodu
- Muszę również upewnić się, że za każdym razem, gdy aktualizuję którykolwiek z moich programów, dostarczam również plik .dll - nawet jeśli nie wiem, czy został zmieniony od ostatniej wersji, czy nie (mógł być, ale był równie dobrze może być ta sama wersja). Nie widzę prostego sposobu na określenie tego, bez śledzenia wersji zestawu, co jest dodatkową pracą. Na razie, kiedy aktualizuję swoje programy, dostarczam tylko zaktualizowane pliki exe i lubię, aby były małe i niskie.
Jaka jest zatem faktyczna korzyść z używania pliku .dll tutaj? Pamiętaj, że jestem jedyną osobą edytującą kod wszystkich aplikacji i plików pomocniczych.
Ponadto, aby wyjaśnić - aplikacje są zwykle bardzo małe, podczas gdy kod zawarty w klasach pomocniczych jest całkowicie ogólny dla nich wszystkich (niektóre proste porównania ciągów, ścieżki lub operacje XML itp.)
Właściwie ktoś mi uświadomił, że istnieje trzecia opcja. Ponieważ mam kod pomocniczy w projekcie separte, mogę dodać ten projekt do rozwiązań każdej z moich oddzielnych aplikacji - co działa jak „Dodaj jako łącze” dla pojedynczych plików, z tym wyjątkiem, że dodam tylko jeden projekt ... Ale jak zauważył Doc Brown, oznacza to zasadniczo, że .dll i tak będzie musiał zostać dodany do projektu ...
Kolejną rzeczą, która przemawia za nieużywaniem plików dll, jest możliwość aktywnego debugowania przez klasę pomocnika ...
Odpowiedzi:
Już zauważyłeś większość zalet i wad. Używanie plików cs jako odniesień jest rzeczywiście lżejsze i często łatwiejsze w zarządzaniu. Zalecam jednak stosowanie tego podejścia wyłącznie wtedy, gdy
cs
pliki są w pełni samowystarczalne i nie mają żadnych specjalnych wymagań dotyczących kompilacji.Korzystanie z oddzielnych bibliotek DLL
sprawi, że zależności od innych narzędzi lub bibliotek będą jawne (tak długo, jak nie będziesz mieć takich zależności, będzie działać dobrze)
pozwoli ci zdefiniować określone konfiguracje kompilacji (na przykład, jeśli klasa działa tylko w konfiguracji x86 lub potrzebuje przynajmniej .NET 4.0, konfiguracja kompilacji zestawu wyraźnie określa to wymaganie).
Tak więc, zwłaszcza jeśli masz wiele samodzielnych komponentów pojedynczej klasy, użycie odwołania do plików jest w porządku, ale jeśli masz komponenty odwołujące się do innych komponentów lub określone wymagania dotyczące kompilacji, zalecam użycie bibliotek DLL.
Aby złagodzić problemy z zarządzaniem wieloma oddzielnymi bibliotekami DLL, możesz albo utworzyć pakiet instalatora, albo użyć ILMerge , który może osadzić zestaw zestawów w jednym pliku wykonywalnym. W naszym środowisku rozwiązujemy ten problem inaczej, używając skryptu wdrażania dla każdej aplikacji. Ten skrypt zapewnia, że wszystkie potrzebne biblioteki DLL są zawsze dostarczane do produkcji po opublikowaniu nowej wersji aplikacji.
źródło
Biblioteki DLL są przydatne, gdy aplikacja jest duża i istnieją elementy wymagające aktualizacji, ale nie cała aplikacja. Tak więc, jeśli piszesz MS Word, dobrze jest mieć kod sprawdzania pisowni w DLL, który można aktualizować bez konieczności aktualizowania całego MS Word. Jeśli to, co piszesz, to niewielka aplikacja narzędziowa (lub seria samodzielnych aplikacji, z których wszyscy korzystają z tego samego kodu), nie ma większego znaczenia, czy kod jest osadzony w aplikacji (aplikacjach), czy nie.
źródło
Prawie podsumowałeś to w swoim pytaniu, mam tylko kilka punktów do dodania.
Opcje mono to świetny przykład pakietu NuGet, który bardzo dobrze wykorzystuje pierwsze podejście.
Alternatywnie, jeśli zdecydujesz się użyć bibliotek DLL, możesz użyć narzędzi takich jak Costura, aby osadzić to odniesienie w pliku wykonywalnym jako zasób osadzony. Aby go użyć, po prostu dodaj
Costura.Fody
pakiet:źródło
To, czy dll jest bardziej korzystne, czy nie, zależy od kilku czynników:
Celem biblioteki współdzielonej jest pobranie kodu wspólnego dla wielu plików wykonywalnych i scentralizowanie go, tak aby wszystkie pliki wykonywalne współdzieliły kopię. Ma to na celu zaoszczędzenie miejsca i ułatwienie aktualizacji kodu.
Jeśli ilość kodu w klasie pomocniczej jest bardzo mała, może nie być warte przeniesienia go do biblioteki DLL, ponieważ narzut kodu znajdujący się w bibliotece DLL może przeciwdziałać korzyściom wynikającym z centralizacji.
Ponadto, jeśli tworzysz tylko kilka plików wykonywalnych, rozmiar kodu w każdym pliku wykonywalnym może być wystarczająco mały, aby nie stanowić problemu. Jednak im więcej plików wykonywalnych używasz tego samego kodu, tym bardziej korzystne byłoby przeniesienie kodu do biblioteki dll.
Jako uproszczony przykład powiedzmy, że twoja klasa pomocnicza kompiluje się do 128 bajtów w pliku exe, ale po przeniesieniu do biblioteki dll ma 512 bajtów. Jeśli masz tylko 3 pliki wykonywalne, możesz zaoszczędzić miejsce, włączając kod do plików wykonywalnych. Jednak gdybyś miał 5 plików wykonywalnych, byłbyś wtedy w punkcie, w którym lepiej byłoby mieć bibliotekę DLL, ponieważ połączone miejsce zajmowane przez 5 kopii kodu (5 * 128 = 640 bajtów) jest więcej niż zajmowane miejsce przez umieszczenie kodu w bibliotece dll (512 bajtów).
Powiedzmy na przykład, że znajdziesz błąd w kodzie pomocnika. Jeśli skompilowałeś wszystkie pliki wykonywalne z wypalonym kodem, musisz ponownie skompilować każdy plik wykonywalny, a następnie rozpowszechnić ponownie skompilowane wersje. Jeśli skompilujesz kod do biblioteki dll, będziesz musiał tylko ponownie skompilować i redystrybuować jedną bibliotekę dll, a błąd zostanie automatycznie naprawiony dla wszystkich plików wykonywalnych, które z niego korzystają.
Wreszcie, aby program mógł znaleźć dll, musi wiedzieć, gdzie szukać dll. Jeśli trzymasz wszystkie pliki wykonywalne razem, możesz po prostu umieścić bibliotekę DLL w tym samym katalogu, a wszystkie one od razu ją znajdą. Jeśli celowo trzymasz je oddzielnie, trudniej jest ich koordynować, aby używać tej samej biblioteki DLL.
źródło
Trzecia opcja jest najbardziej odpowiednia (dodaj ją jako oddzielny projekt „biblioteki klas” do rozwiązania). Łączy to zalety wszystkich podejść:
Robimy to cały czas i nie mogę zrobić nic innego, jak tylko polecić to podejście.
Inną czwartą alternatywą, o której nie wspomniałeś, jest umieszczenie go w prywatnym repozytorium NuGet, co pozwoli ci poprawnie go zaktualizować i odwołać się do niego bez dodatkowego projektu w każdym rozwiązaniu.
źródło
Jako programista zawsze lubię dołączać odniesienie rozwiązania narzędzia do mojej aplikacji, ponieważ pozwala mi to debugować kod (i wykrywać ewentualne błędy w Narzędziu!), A wszelkie zmiany wprowadzone w narzędziu są automatycznie uwzględniane w aplikacji.
Więc tak naprawdę decyzja zależy od stopnia dojrzałości narzędzia ! Jeśli nie masz pewności co do błędów narzędzia, zawsze powinieneś dołączyć plik .cs tego narzędzia, aby dowiedzieć się o błędach. Ale jeśli masz pewność, że narzędzie jest wystarczająco dojrzałe i nie zwróci wyników z żadnymi błędami i tam nie ma możliwości rozszerzenia w Narzędziu, możesz dołączyć plik DLL.
źródło