8

Ho bisogno di ottenere alcuni metadati sull'assembly che chiama il mio componente. Pertanto, l'utilizzo di Assembly.GetCallingAssembly() sembra essere una scelta naturale. Tuttavia, ho trovato funziona ovunque tranne che in Windows Store. Dove è supportato:Assembly.GetCallingAssembly non è supportato su WinRT, ma è destinato a librerie di classi portatili?

Tuttavia, se non è supportato direttamente all'interno di un'applicazione Windows Store. Posso creare una libreria di classi portatile e quindi chiamarla da lì all'interno di un'applicazione di Windows Store, ma non posso semplicemente inserirla direttamente nell'app/libreria di Windows Store.

Esiste una soluzione alternativa per questo o un altro modo per ottenere il tipo di metadati forniti da Assembly?

risposta

7

Assembly.GetCallingAssembly non è esposto in WinRT - presumibilmente perché la sua semantica è inaffidabile a fronte di inlining ecc. (source), ma non si adatta troppo alla riflessione limitata consentita nelle app di Windows Store. È possibile ottenere qualcosa di simile Assembly.GetCurrentAssembly(), ad esempio in questo modo:

typeof(MainPage).GetTypeInfo().Assembly 

Ma non è lo stesso a tutti. Con il modello di riflessione limitato, non è possibile neanche ottenere una traccia di stack in runtime come possibile in .NET.

Per quanto riguarda la libreria di classi portatili, stavo per dire che Assembly.GetCurrentAssembly() è supportato in librerie di classi portatili in generale, ma non solo in WinRT - il che avrebbe senso se non fosse semplicemente in quella piattaforma. Ma in realtà sembra che sia presente in tutti i profili incluso WinRT tranne WinRT + .NET4.5 - sembra che ci debba essere una sorta di supervisione qui con questa incoerenza. Quindi il metodo è presente in WinRT (e inoltre non c'è alcun tipo di reindirizzamento attivo), ma non visibile nei metadati disponibili al momento della compilazione.

Quindi si può chiamare il metodo con la riflessione:

var assembly = (Assembly) typeof(Assembly).GetTypeInfo() 
    .GetDeclaredMethod("GetCallingAssembly") 
    .Invoke(null, new object[0]); 

presumo la non visibilità di questo metodo in applicazioni Windows Store è un "Vogliamo questo sarebbe andato via".

(Questa risposta riguarda solo "posso" non "dovrei").

2

Il metodo è stato tagliato semplicemente perché è troppo inaffidabile in un'app WinRT. Un obiettivo di progettazione forte per WinRT era quello di rendere l'interoperabilità tra diversi ambienti di runtime linguistico semplice e senza problemi. Che funziona bene, puoi facilmente creare un componente WinRT in una lingua come C# e farlo utilizzare da un'app che è stata scritta in un linguaggio non gestito come C++ o Javascript.

Questo è possibile anche in un'app desktop .NET ma è molto più complicato, dovendo ricorrere a un assembly [ComVisible] o creare un assembly in modalità mista nel linguaggio C++/CLI. Anche l'utilizzo di Assembly.GetCallingAssembly() in questo caso fallirà, è comunque del tutto improbabile che il programmatore fallisca poiché è ben consapevole di fare qualcosa di speciale.

Questo diventa molto più torbido in un componente WinRT. Soprattutto dal momento che non è necessario fallire se la chiamata è stata effettivamente effettuata da un altro assembly .NET.Ma nessuna speranza quando proviene dal codice non gestito.

Questo tipo casuale di insuccesso è solo una grande sofferenza senza una soluzione decente. Di conseguenza il metodo è stato tagliato. L'utilizzo di PCL è una soluzione possibile, ma Microsoft ha severamente avvertito in passato che questo tipo di hackorama è altamente sconsigliato. Con probabilità diverse da zero che verranno catturate dalla procedura di convalida del negozio e comportano un rifiuto.