2013-08-09 13 views
10

Mam następujący problem: Chcę zadzwonić pod numer Delegate.CreateDelegate z mojej biblioteki przenośnej klasy targetowania .NET 4.5, Windows Phone 8 i Windows 8 Store Apps, ale mój kod nie kompiluje się. Kompilator twierdzi, że nie może znaleźć metody na typie Delegate.Dlaczego nie mogę wywołać Delegate.CreateDelegate w mojej bibliotece przenośnych klas?

Zabawne jest to, że np. biblioteka PRISM firmy Microsoft może wywoływać "Delegate.CreateDelegate" z Portable Class Library. Czyni to w klasie DelegateReference. Biblioteka przenośnych klas PRISM jest przeznaczona dla bibliotek .NET 4.0, Windows 8 Store Apps, Windows Phone 8 i Silverlight 5 (a tym samym nawet bardziej restrykcyjnego zestawu).

Kod, który nie kompiluje wygląda następująco:

public class MyClass 
{ 
    public void MyMethod<T>(EventHandler handler) 
    { 
     var @delegate = Delegate.CreateDelegate(typeof (OpenEventHandler<T>), null, handler.GetMethodInfo()); 
    } 
} 

public delegate void OpenEventHandler<in T>(T target, object sender, EventArgs arguments); 

Przykładem można pobrać tutaj: https://dl.dropboxusercontent.com/u/14810011/PortableClassLibraryReferenceProblem.zip

Zawiera mój projekt biblioteki i bardzo uproszczoną wersję projektu PRISM PubSubEvents zawierającą tylko klasa DelegateReference i jej interfejs. Pełny kod źródłowy tego ostatniego można znaleźć tutaj: http://prismwindowsruntime.codeplex.com/SourceControl/latest

Co mogę zrobić, aby korzystać ze wszystkich członków Delegate? Z góry dziękuję za Twoją pomoc!

EDIT po Henk Holterman za odpowiedź:

GetMethodInfo() to metoda rozszerzenie, które jest obsługiwane przez podzbiór PCL. W każdym razie nie jest to związane z problemem, którego nie mogę nazwać Delegate.CreateDelegate, podczas gdy projekt PRLM na PCL może.

Picture of code that does not compile

EDIT 2 po Hans Passants Komentarz:

po prostu bawił się i okazało się, że kiedy aktywować Silverlight 5 jako cel przenośnej biblioteki następnie Delegate.CreateDelegate rzeczywiście jest dostępny (i Metoda rozszerzenia GetMethodInfo już nie jest). Czy w takim razie może być zmapowany do innego API dla Windows 8 Sklep i aplikacje telefoniczne? To jedyny sposób, w jaki mogłem wymyślić, w jaki sposób ta metoda byłaby nagle dostępna tylko dlatego, że dodałem Silverlight 5 jako prawidłowy cel.

(Można odtworzyć to klikając prawym przyciskiem myszy na projekcie „MyPortableClassLibrary”, kliknij „Właściwości” oraz w „Library” zmiany zakładce zaznacz ram, które są kierowane przez przenośnej biblioteki.)

Również wcześniej, wcześniej stworzyłem projekt aplikacji Windows Store App i zobaczyłem, że nie było metody zdefiniowanej w klasiew środowisku .NET dla środowiska wykonawczego Windows.

W moim rzeczywistym projekcie nie chcę kierować na Silverlight 5, ponieważ używam IObservable<T> i IObserver<T> w dużym stopniu używając Rx i te interfejsy nie są zdefiniowane w Silverlight.

+1

Działa dobrze na moim komputerze. –

+0

@ Czy rozpoznaję, że nie pobrałeś przykładowego kodu? Ponieważ tam nie działa. W każdym razie, zaktualizowałem moje pytanie do moich ostatnich ustaleń. – feO2x

+1

To jest problem z bibliotekami przenośnymi, niektóre podzbiory dają różne interfejsy API, zdarzały mi się niektóre typy odbić, które nie były dostępne w zestawach Windows 8/Telefon, dopóki nie zostałem skierowany do Silverlight. – Rafael

Odpowiedz

10

Co widzisz podczas dodawania/usuwania Silverlight jest przenośny przerzucanie między dwoma różnymi obszarami powierzchni API .NET API. Obejmuję te dwa różne obszary tutaj: What is .NET Portable Subset (Legacy)?.

W tym, co nazywamy starszą powierzchnią, ta metoda funkcjonuje na Delegacie. W nowej powierzchni ta metoda została przeniesiona do MethodInfo.

Dlaczego to zrobiliśmy?

Ze względu na warstwowość. Na nowej powierzchni typy odbić (tj. Assembly, MemberInfo, MethodInfo, itp.) Są uważane za żyjące w wyższej warstwie niż podstawowe prymitywy, w tym Delegate. W przeciwieństwie do dotychczasowej powierzchni (gdzie wszystkie żyją w mscorlib), te typy w różnych złożeniach; System.Reflection.dll i System.Runtime.dll, odpowiednio.

Ta metoda (kilka innych) powodowała, że ​​coś w niższej warstwie (System.Runtime.dll) zależało od czegoś na wyższej warstwie (System.Reflection.dll). Aby temu zapobiec, zależność została odwrócona.

+0

Dziękuję za dodatkowe spostrzeżenia, David. – feO2x

11

OK, po nocy snu, zdałem sobie sprawę, że moje pytanie powinno brzmieć: "Jak dynamicznie tworzyć delegatów w nowym interfejsie API wprowadzonym w środowisku wykonawczym systemu Windows?". Jak Rafael zaznaczył w komentarzach mojego pytania, różne API są dostarczane, gdy oprócz Windows .NET jest kierowany również system Windows 8/Phone 8.Jeśli Silverlight jest również celem, wówczas interfejsy API, które nie są dostępne w systemie Windows 8/Phone 8, zostaną zmapowane i to wyjaśnia, dlaczego mogę nagle zadzwonić pod numer Delegate.CreateDelegate, gdy dodaję Silverlight jako cel przenośnej biblioteki klas. W .NET nowe API dla Reflection zostały wprowadzone z .NET 4.5.

W każdym razie, aby utworzyć delegata w Windows 8/Windows Phone 8, trzeba użyć metody MethodInfo.CreateDelegate, podobnie jak to:

public class MyClass 
{ 
    public void MyMethod<T>(EventHandler handler) 
    { 
     var methodInfo = handler.GetMethodInfo(); 
     var @delegate = methodInfo.CreateDelegate(typeof(OpenEventHandler<T>), null); 
    } 
} 

public delegate void OpenEventHandler<in T>(T target, object sender, EventArgs arguments); 
Powiązane problemy