2013-05-04 6 views
7

Potrzebuję dodać i/lub zmodyfikować profile, aby umożliwić udostępnianie większej liczby klas i członków w PCL (wiele z nich jest wbudowanych w strukturę, na przykład Thread.Sleep). Jaki jest najlepszy sposób na zrobienie tego? Czy są jakieś narzędzia, aby temu zaradzić?



PS: Nie jestem szukając anwser do powiedzenia NO czy zatrzymać. Chcę mieć skompilowane biblioteki DLL, które mogą być udostępniane w innym środowisku. Bez plików binarnych na platformę, bez rekompilacji, bez ifdef.


Oto co mam do tej pory:

Dostosowywanie .NET Portable Class Library Profiles?

Wymagania:

  • docelowe environements: Silverlight 5 i .NET Framework 4.5.
  • Cel PCLS: wspólne infrastruktury przez klienta i serwera ASP.NET RIA (bez WCF)
  • Co brakuje w domyślnych profili: XPath, metod nici, DynamicMethod/ILGenerator

profili PCL: pod referencyjny zwoje \ Microsoft \ Framework.NETPortable:

  • Wszystkie zespoły są odcinki, z "zmiennocelowym" zestawu atrybutów.
  • Wszystkie zespoły mają flagi = 0x171: 0x001 jest podpisana, jest zmiennocelowym 0x100 i 0x070 jest niezdefiniowane w AssemblyNameFlags (wydaje się nie mieć wpływu)
  • Wszelkie odniesienia między zespołami są w „zmiennocelowym” atrybutów, jak również.
  • Wszystkie zespoły z obsługą Silverlight mają wersję 2.0.5.0.
  • zabudowy binarne PCL zawierają dwie referencje dla każdego z określonych zespołów (ex: mscorlib 2.0.5.0 zmiennocelowym + mscorlib 4,0)

Dostosowanie próba # 1

  • Profil: Silverlight 5 +. NET Framework 4.5 (profil 24)
  • Skopiuj SL5 mscorlib.dll do profilu 24
  • Mark SL5 mscorlib.dll jako retargetable (zmiana na opóźnione podpisane)
  • ReSharper: nie udało się rozwiązać wszystkie metody rozszerzenie, błąd w typ rodzajowy/wartości meczu
  • Budowa: sukces, uruchom: sukces

Dostosowanie próba # 2

  • Profil: Silverlight 5 + .NET Framework 4.5 (profil 24)
  • Skopiuj wszystkie pliki DLL SL5 do profilu 24
  • Oznacz wszystko SL5 DLL jako zmiennocelowym (zmiana opóźnienia podpisany)
  • Oznacz wszystkie odnośniki między SL5 DLL jak zmiennocelowym
  • ReSharper: nie udało się rozwiązać wszystkie metody przedłużania, błąd w typ rodzajowy/wartości meczu
  • Budowa: sukces, uruchom: sukces

Dostosowanie próba nr 3

  • Profil: Silverlight 4 + .NET Framework 4.0.3 (profil 18)
  • Kopiowanie SL4 mscorlib.dll do profilu 18
  • Mark SL4 pliku Mscorlib.dll jak zmiennocelowym (zmiany opóźnienia podpisany)
  • ReSharper: sukces
  • Budowa: sukces, Run: sukces

Dostosowanie próba nr 4

  • Profil: Silverlight 4 + .NET Framework 4.0.3 (profil 18)
  • Kopiuj wszystko SL4 DLL do profilu 18
  • zestaw wersję .NET wykonania wszystkich bibliotek DLL SL4 V4 (oryginalne DLL mają, że brak efektów)
  • Oznacz wszystko SL4 DLL jako zmiennocelowym (zmiana opóźnienia podpisany)
  • Oznacz wszystkie odnośniki między SL4 DLL jak zmiennocelowym
  • ReSharper: sukces
  • Budowa: sukces, Run: sukces

Dostosowanie próba # 5 dziedziczą # 4

  • Profil: Silverlight 4 + .NET Framework 4.0.3 (profil 18)
  • Dodaj System.Numerics SL4 za (ujęte w innych profilach SL) do RedistList \ FrameworkList.xml
  • Dodaj SL4 za System.Xml.XPath (nieuwzględnione w dowolnych profili SL) do RedistList \ FrameworkList.xml
  • Wynik: nie można rozwiązać System.Numerics i System.Xml.XPath z def ault PCL odwołuje
  • rozwiązania: porównawczą DLL ręcznie - nie można zmusić się zmiennocelowym jednak VS nie kompilacji z nie zmiennocelowym System.Numerics lub System.Xml.XPath uwagi na wspomniany problem poniżej

Uwagi:

  • błąd kompilacji: „... zdefiniowane w zespole, który nie jest odwołanie, należy dodać odwołanie do montażu”.Dzieje się po wszystkie zespoły są zmiennocelowym ale odniesień między nimi nie jest zmieniony na „zmiennocelowym”

To działa do pewnego stopnia, ale dość kłopotliwe, aby dostosować istniejący odwołuje DLL lub dodawać nowe, nie można łatwo sprawdź kod PCL po przesłonięciu odwołujących się bibliotek DLL (jeśli to możliwe).

+2

Wiem, że nie szukasz * odpowiedzi, która po prostu ci przerwie, ale pomysł, że możesz wybrać i wybrać, które części frameworka chcesz dołączyć, i po prostu zadziała, naprawdę nie jest rozsądny. Nawet jeśli znajdziesz jakiś niezręczny sposób na to, żeby to zadziałało do pewnego stopnia, prędzej czy później zostaniesz odblokowany - w którym to momencie zmarnujesz dużo czasu. –

+0

Ale to tylko niewygodne, bez odpowiedniego wsparcia narzędzi. Jeśli istnieje narzędzie do generowania plików pośredniczących dla referencji, byłoby całkiem dobrze. – AqD

+0

Zakładasz, że masz wystarczającą świadomość tego, co jeszcze jest wymagane, aby obsługiwać te interfejsy API ... wszystkie zależności pod względem zarówno natywnego kodu, jak i innego zarządzanego kodu. Nie sądzę, żeby było tak proste, jak się tego spodziewasz. –

Odpowiedz

4

NIE. ZATRZYMAĆ.

OK, ponieważ nie jest to to, co chcesz usłyszeć, kontynuuj na własne ryzyko. :) To na pewno nie jest obsługiwane, i IANAL, więc nie wiem, czy byłoby to dozwolone przez umowę licencyjną.

Wygląda na to, że głównym problemem w istniejących rozwiązaniach jest to, że nie można wybrać poszczególnych interfejsów API do dodania do profilu przenośnego. Aby to zrobić, możesz użyć ildazu na istniejących zestawach referencyjnych, a następnie dodać potrzebne interfejsy API (prawdopodobnie kopiując je z wyników działania ildazma na innym zestawie referencyjnym), a następnie użyć ilumina, aby utworzyć własne wersje odwołania złożenia z tymi dodatkowymi interfejsami API.

Będziesz musiał opóźnić znak i/lub wyłączyć silną weryfikację klucza nazwy kluczy do zmontowanych w ten sposób złożeń.

Inną opcją jest użycie przekierowania, jak opisano w mojej odpowiedzi here. W takim przypadku skończyłoby się na tym, że główny kod byłby udostępniany, tak jak jest, z zależnością od biblioteki DLL, która byłaby inna dla każdej platformy.

+0

Przekazywanie typu wydaje się dobrym pomysłem. Tak więc teoretycznie powinno być możliwe owinięcie przecinanych części wszystkich interfejsów API, a następnie przekazanie ich w celu poprawienia złożeń. Ale trzeba by było narzędzie do automatyzacji .. – AqD

10

Ponieważ nie zajmie NO lub STOP jako odpowiedź pozwól mi spróbować wyjaśnić, dlaczego jest to zły pomysł. Krótka odpowiedź brzmi: jeśli PCL nie ujawnia interfejsu API, to zwykle dlatego, że nie zadziała.

Po pierwsze, PCL nie ma własnego zestawu interfejsów API. PCL ujawnia tylko przecięcia interfejsów API między określonym zestawem platform, na które chcesz kierować reklamy. Teraz są przypadki, w których przecięcie na poziomie interfejsu API przyniosłoby więcej interfejsów API niż to, które ujawnia PCL. Istnieje kilka powodów, dla których może tak być.

  1. API nie jest dostępny na wszystkich platformach
  2. API jest dostępny, ale faktycznie nie pracują
  3. API jest zdefiniowana w różnych zespołach

Pierwsza z nich powinna być oczywista . Sam PCL nie jest rzeczywistą platformą, ale tylko ujawnia to, co tam jest. Nie możemy więc podać interfejsów API, które nie istnieją na wszystkich platformach, na które kierujesz. W końcu wystawiamy przecięcie.

Drugi brzmi trochę dziwnie, ale tak naprawdę się zdarza. Weźmy, na przykład, plik IO na Windows Phone 7. Mimo, na File class jest technicznie dostępna na Windows Phone, to udokumentowane jako

This type is present to support the .NET Compact Framework infrastructure in Silverlight for Windows Phone, and it is not intended to be used in your application code.

Można powiedzieć „co mnie to obchodzi?” i po prostu spróbuj, ale wtedy dowiadujesz się, że model zabezpieczeń telefonu uniemożliwi ci dostęp do plików, których szukasz. Ujawnienie tego interfejsu API w PCL nie byłoby pomocne. W rzeczywistości nasz zespół wierzy, że to cię skrzywdzi, ponieważ prowadzi cię to do nieprzenośnej ścieżki.

Trzeci problem związany z interfejsami API implementowanymi w różnych zestawach jest nieco bardziej zaangażowany.Aby zrozumieć, dlaczego jest to problem, należy wziąć pod uwagę sposób, w jaki CLR obsługuje interfejsy API w ogóle. Środowisko CLR nie ma koncepcji ładowania poszczególnych typów, jak na przykład Java. W typach .NET są zaimplementowane w zespoły i w celu ich użycia ("załaduj je"), należy załadować zestaw, który definiuje typ. Pod okładkami odwołania typu zawierają zarówno nazwę kwalifikowanego typu przestrzeni nazw, jak i złożenie, w którym jest zdefiniowany typ. Ogólnie typy, które mają tę samą kwalifikowaną nazwę przestrzeni nazw, ale są w różnych złożeniach, są uważane za różne. Na przykład: typ MyNamespace.MyType, Assembly1 i MyNamespace.MyType, Assembly2. Należy pamiętać, że same zestawy mają również w pełni kwalifikowaną nazwę; zawiera nazwę zespołu i token klucza publicznego. Dzięki temu dwie firmy mogą produkować zarówno zespół o nazwie "Foo", jak i nie mylić CLR (zakładając, że są one podpisane różnymi kluczami). Zasadniczo typ ładowania wymaga kilku kroków: odszukania zespołu, w którym zdefiniowano typ, załadowania tego zespołu, a następnie załadowania typu.

Zwykle różne platformy .NET używają różnych kluczy dla zestawów platform, na przykład mscorlib. Teraz możesz się zastanawiać, w jaki sposób możesz używać typów z Silverlight na .NET Framework. Powodem tego jest to, że CLR ma koncepcję niefunkcjonowania złożenia. Złożenie unfication pozwala .NET Framework traktować odniesienia do mscorlib Silverlight jako odniesienia do wersji na komputery. Jest to ważne, ponieważ mscorlib programu Silverlight został zaprojektowany jako podzestaw wersji .NET Framework (dla określonej kombinacji wersji).

Chociaż może to brzmieć jak srebrna kula, aby niwelować wszystkie różnice palet, w rzeczywistości tak nie jest. Z biegiem czasu różne platformy wybierały różne czynniki montażowe. Weźmy na przykład ICommand. Jest on dostępny w .NET 4 i Silverlight 4. Jednak w WPF jest zaimplementowany w PresentationCore.dll, a Silverlight umieszcza go w System.Windows.dll. Aby zrozumieć, dlaczego PCL nie ujawnia ICommand, gdy kierujesz się na .NET 4 i Silverlight 4, zobaczmy, co by się stało, gdyby PCL je ujawnił.

W języku PCL musimy umieścić ICommnad w jakimś zespole. Moglibyśmy albo wybrać zestaw Silverlight, albo kompletny. Bez względu na to, które wybieramy, typ nie zostanie rozwiązany na innej platformie, ponieważ PresenationCore.dll istnieje tylko w .NET 4, a System.Windows.dll istnieje tylko w Silverlight 4.

Rozwiązaliśmy ten problem, zezwalając na odniesienia dla ICommand w System.Windows.dll, aby odnieść sukces na pełnym systemie. Jak to zrobiliśmy? Odpowiedzią jest przekazywanie typu. Przekazywanie typów pozwala zespołowi powiedzieć "zdefiniowałem typ Foo". Kiedy CLR próbuje załadować typ Foo z tego zestawu, zespół faktycznie mówi "nie, nie - typ Foo jest faktycznie zdefiniowany na tym innym pasku zespołu". Innymi słowy, skład Foo zawiera coś w rodzaju wskaźnika do wersji tego typu. Nazywamy te wskaźniki przekazywaniem typów wskaźników.

Ta koncepcja pozwoliła nam rozwiązać niedopasowanie ICommand przez dodanie pliku System.Windows.dll do pełnej struktury zawierającej typ forward do rzeczywistej implementacji. PCL daje teraz ICommand w System.Windows.dll i może być pewny, że żądania ładowania typu mogą odnieść sukces zarówno na platformie .NET, jak i Silverlight. To jednak wymaga skierowania co najmniej .NET Framework 4.5, ponieważ poprzednie wersje nie miały typu forward.

W przypadku wszystkich interfejsów API, które powinny zostać ujawnione, ale nie współpracujemy z właścicielami platform, aby je zamknąć. Mamy zasadniczo dwie strategie, które:

  1. pytamy właścicieli platformy, aby dodać brakujące API lub wpisać do przodu
  2. Wysyłamy przenośny wdrożenie w out-of-band mody. Weźmy na przykład Async lub HttpClient.

Jednak "po prostu" dodanie go do PCL nie działa.

EDYCJA: Jeśli przegapisz funkcję w PCL, zawsze możesz się odblokować. Nasz tester Daniel ma written a blog post, który pokazuje kilka technik, których możesz użyć.

+0

Dzięki. Ale dopóki Microsoft nie doda tego, co chcę do PCL, nie ma dla mnie alternatywy. Nie mogę wziąć rozwiązania jako rozwiązania. – AqD

+0

Możesz rozwiązać ten problem bez konieczności dostosowywania zespołów referencyjnych PCL. Nasz tester napisał świetny blog na temat możliwych rozwiązań. Dodałem go do odpowiedzi. –