Jestem w trakcie tworzenia nowego, niewielkiego wydania o numerze toy project. Ten projekt jest wydany na NuGet i jest kompatybilny z .NET 4.0 i nowszym. Niektóre nowe funkcje, które wprowadzam wymagają .NET 4.5 (użytkownicy powinni być w stanie rozwiązać IReadOnlyCollection<T>
i IReadOnlyList<T>
, oba interfejsy, które zostały wprowadzone w .NET 4.5), ale muszę zachować zgodność projektu z .NET 4.0, ponieważ nie wszyscy programiści mogą łatwo migrować do najnowszej platformy .NET.Jak włączyć kompatybilność forward w bibliotece .NET do wielokrotnego użytku?
Problemem, który napotykam, jest rozwiązanie tego problemu "zgodności z przodu". Są dwa rozwiązania, o których myślałem, ale oba nie są zbyt atrakcyjne, więc mam nadzieję, że każdy może podać mi jakieś pomysły lub wskazówki.
Oto dwa rozwiązania wymyśliłem:
Rozwiązanie 1: Użyj #if
dyrektyw kompilatora i zbudować DLL za NET wersji ramowej i wysyła te wersje z wykorzystaniem pakietów Nuget i pobrania na stronie projektu.
Wadą tej metody jest to, że gdy deweloperzy aktualizują swój projekt Visual Studio z .NET 4.0 do .NET 4.5, nie otrzymują automatycznie wersji .NET 4.5 (z właściwymi funkcjami .NET 4.5). Jest to sprzeczne z Principle of least astonishment i pozostawiłoby twórców oszołomionych, dlaczego funkcja nie działa, gdy próbują jej używać kilka miesięcy później.
Rozwiązanie 2: Użyj jednej pojedynczej biblioteki DLL i wysyłaj typy w locie, które implementują oba nowe interfejsy, jeśli istnieją w bieżącej domenie aplikacji. Pozwala to wysłać pojedynczą bibliotekę DLL do użytkownika i umożliwia dostęp do funkcji, gdy programista przełącza wersje platformy .NET w swoim projekcie. To sprawi, że rzeczy będą po prostu działać. To jest kierunek, w którym aktualnie zmierzam.
Ponieważ muszę zwrócić typ, który musi implementować interfejsy, wadą jest to, że ten typ musi zostać utworzony w środowisku wykonawczym za pomocą Reflection.Emit, ModuleBuilder, TypeBuilder i tym podobnych. To jest naprawdę paskudne shizzle. Ale poza tym, ponieważ ten typ musi być tworzony w nowym (anonimowym) zestawie, muszę uczynić niektóre typy wewnętrzne publicznymi (typ, który musi odziedziczyć i interfejs, który musi implementować). Upublicznienie tych typów wewnętrznych powoduje zanieczyszczenie API projektu i uniemożliwi mi wprowadzanie zmian w tych typach.
Wierzę, że to są moje opcje, ale być może brakuje mi czegoś oczywistego. Moje pytanie brzmi: czy brakuje mi możliwości? Czy istnieje sposób na obejście problemów z rozwiązaniem 1, czy lepiej byłoby pójść z korzeniami typu runtime?
json.net używa rozwiązania 1. –
Nie sądzę, że pierwsza opcja jest sprzeczna z zasadą: dlaczego miałbym się spodziewać, że moje referencje od osób trzecich będą tak gwałcone? Byłbym zaskoczony, gdyby tak było! –
Nie jestem pewien, czy to naprawdę pasuje tutaj, czy jest tu nawet powiązane, ale czy przekierowanie zespołu uderza w jakiś akord? –