2013-08-09 6 views
10

Ho il seguente problema: Voglio chiamare Delegate.CreateDelegate dalla mia libreria di classi portatile con targeting per .NET 4.5, Windows Phone 8 e Windows 8 Store, ma il mio codice non viene compilato. Il compilatore dice che non riesce a trovare il metodo sul tipo Delegate.Perché non riesco a chiamare Delegate.CreateDelegate nella mia libreria di classi portatile?

La cosa divertente è che, ad es. la libreria PRISM di Microsoft può chiamare "Delegate.CreateDelegate" da una libreria di classi portatile. Lo fa nella classe DelegateReference. La libreria di classi portatili PRISM punta a .NET 4.0, App Store di Windows 8, Windows Phone 8 e Silverlight 5 (e quindi un set ancora più restrittivo).

Il codice che non può essere compilato simile al seguente:

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); 

Un esempio può essere scaricato qui: https://dl.dropboxusercontent.com/u/14810011/PortableClassLibraryReferenceProblem.zip

Contiene il mio progetto biblioteca e una versione molto ridotta del progetto PRISM PubSubEvents contenente solo la classe DelegateReference e la sua interfaccia. Il codice sorgente completo di quest'ultimo può essere trovato qui: http://prismwindowsruntime.codeplex.com/SourceControl/latest

Cosa posso fare per utilizzare tutti i membri Delegate? Grazie in anticipo per il vostro aiuto!

EDIT dopo la risposta di Henk Holterman:

GetMethodInfo() è un metodo di estensione che è supportato dal sottoinsieme PCL. Ad ogni modo, ciò non è correlato al problema che non posso chiamare Delegate.CreateDelegate mentre il progetto PCL di PRISM può.

Picture of code that does not compile

EDIT 2 dopo Hans passants commento:

Ho appena giocato intorno e ho scoperto che quando attivo Silverlight 5 come un obiettivo della libreria portabile poi Delegate.CreateDelegate è davvero accessibile (e la Il metodo di estensione GetMethodInfo non è più disponibile). Delegate.CreateDelegate quindi può essere mappato a un'altra API per le app di Windows 8 Store e Phone internamente? È l'unico modo in cui potrei pensare a come questo metodo sarebbe improvvisamente accessibile solo perché ho aggiunto Silverlight 5 come target valido.

(È possibile riprodurre questo facendo clic destro sul progetto "MyPortableClassLibrary", fare clic su "Proprietà" e nel cambiamento scheda click "Library" per selezionare i quadri che sono indirizzate dalla libreria portabile.)

Inoltre, prima di oggi, ho creato un progetto di app di Windows Store e ho visto che non esisteva il metodo CreateDelegate definito nella classe Delegate in .NET per Windows Runtime.

Nel mio progetto attuale, non voglio di indirizzare Silverlight 5 come io uso IObservable<T> e IObserver<T> pesantemente con Rx e queste interfacce non sono definiti in Silverlight.

+1

Funziona perfettamente sulla mia macchina. –

+0

@Hans Riconosco che non hai scaricato il codice di esempio? Perché non funziona lì. Ad ogni modo, ho aggiornato la mia domanda alle mie recenti scoperte. – feO2x

+1

Questo è un problema con le librerie portatili, alcuni sottoinsiemi forniscono diverse API, mi è successo con alcuni tipi di riflessione che non erano disponibili su sottoinsiemi di Windows 8/Phone fino a quando non ho scelto Silverlight. – Rafael

risposta

10

Quello che state vedendo quando si aggiunge/rimuovere Silverlight, è portatile sfogliare tra due diverse aree di superficie API .NET. Copro queste due diverse aree di superficie qui: What is .NET Portable Subset (Legacy)?.

In quella che chiamiamo superficie legacy, questo metodo è in Delegate. Nella nuova area di superficie, questo metodo è stato spostato su MethodInfo.

Perché lo abbiamo fatto?

Per motivi di stratificazione. Nella nuova superficie, i tipi di riflessione (cioè Assembly, MemberInfo, MethodInfo, ecc.) Sono considerati come residenti in uno strato superiore rispetto ai primitivi core, che include Delegato. A differenza della superficie legacy (dove vivono tutti in mscorlib), questi tipi in diversi assembly; System.Reflection.dll e System.Runtime.dll, rispettivamente.

Questo metodo (alcuni altri) causava qualcosa in un livello inferiore (System.Runtime.dll) per dipendere da qualcosa in un livello superiore (System.Reflection.dll). Per evitare ciò, la dipendenza è stata invertita.

+0

Grazie per le informazioni aggiuntive, David. – feO2x

11

OK, dopo una notte di sonno ho riconosciuto che la mia domanda in realtà dovrebbe essere "Come creare dinamicamente i delegati nella nuova API introdotta con Windows Runtime?". Come indicato da Rafael nei commenti della mia domanda, vengono fornite diverse API quando Windows 8/Phone 8 è indirizzato in aggiunta a .NET.Se anche Silverlight viene scelto come target, le API che non sono disponibili in Windows 8/Phone 8 verranno mappate e questo spiega il motivo per cui posso improvvisamente chiamare Delegate.CreateDelegate quando aggiungo Silverlight come destinazione della libreria di classi portatili. In .NET, le nuove API per Reflection sono state introdotte con .NET 4.5.

In ogni caso, per creare un delegato in Windows 8/Windows Phone 8, si deve utilizzare il metodo MethodInfo.CreateDelegate, proprio come questo:

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);