2011-09-26 24 views
23

Dalla versione 3.0, .NET installa una serie di "assembly di riferimento" diversi in C: \ Programmi \ Reference Files \ Reference .... per supportare profili diversi (ad esempio profilo client .NET 3.5, profilo Silverlight). Ognuno di questi è un assembly .NET corretto che contiene solo metadati - nessun codice IL - e ogni assembly è contrassegnato con lo ReferenceAssemblyAttribute. I metadati sono limitati a quei tipi e membri disponibili sotto il profilo applicabile - è così che intellisense mostra un insieme limitato di tipi e membri. Gli assembly di riferimento non vengono utilizzati in fase di esecuzione.Come posso creare e utilizzare un "Assembly di riferimento" solo per i metadati .NET?

Ho imparato un po 'a riguardo da this blog post.

Mi piacerebbe creare e utilizzare un tale assieme di riferimento per la mia libreria.

  1. Come creare un assembly solo per metadati: c'è qualche indicatore del compilatore o un post-processore ildasm?
  2. Esistono attributi che controllano quali tipi vengono esportati in "profili" diversi?
  3. Come funziona la risoluzione dell'assembly di riferimento in fase di esecuzione - se avessi l'assembly di riferimento presente nella directory dell'applicazione anziché l'assembly 'reale', e non nel GAC del tutto, il sondaggio continuerà e il mio evento AssemblyResolve verrà attivato in modo che io può fornire l'effettivo assemblaggio in fase di runtime?

Qualsiasi idea o suggerimento su dove potrei saperne di più su questo sarebbe molto apprezzato.

Aggiornamento: Guardando un po 'intorno, vedo il 'assembly di riferimento' .NET 3.0 sembrano avere un certo codice, e il Reference Assembly attribute è stato aggiunto solo in .NET 4.0. Quindi il comportamento potrebbe essere cambiato un po 'con il nuovo runtime.

Perché? Per la libreria del componente aggiuntivo Excel-DNA (http://exceldna.codeplex.com), creo il componente aggiuntivo .xll a file singolo comprimendo gli assi di riferimento nel file .xll come risorse. Gli assembly compressi includono il codice aggiuntivo dell'utente, nonché la libreria gestita da Excel-DNA (a cui potrebbe fare riferimento l'assemblaggio dell'utente).

Sembra piuttosto complicato, ma funziona meravigliosamente bene la maggior parte del tempo - il componente aggiuntivo è un singolo file di piccole dimensioni, quindi nessuna installazione di problemi di distribuzione. Eseguo problemi (non inaspettati) a causa di versioni diverse - se c'è una vecchia versione della libreria gestita da Excel-DNA come file, il runtime caricherà quella invece di quella imballata (non ho mai la possibilità di interferire con il Caricamento in corso).

Spero di creare un assembly di riferimento per la parte gestita da Excel-DNA a cui gli utenti possono fare riferimento durante la compilazione dei componenti aggiuntivi. Ma se hanno erroneamente una versione di questo assembly in fase di runtime, il runtime dovrebbe fallire nel caricarlo e mi dà la possibilità di caricare il vero assembly dalle risorse.

+1

Perché vuoi farlo? – svick

risposta

9

Per creare un assembly di riferimento, si dovrebbe aggiungere questa riga al vostro file AssemblyInfo.cs:

[assembly: ReferenceAssembly] 

Per caricare gli altri, è possibile farvi riferimento come al solito dai vostri riferimenti del progetto VisualStudio, o in modo dinamico in fase di esecuzione utilizzando:

Assembly.ReflectionOnlyLoad()

o

Assembly.ReflectionOnlyLoadFrom()


Se è stato aggiunto un riferimento a un metadati/di riferimento assembly utilizzando VisualStudio, quindi intellisense e costruire il vostro progetto funziona bene, se si tenta di eseguire l'applicazione contro uno, si otterrà un errore:

System.BadImageFormatException: Cannot load a reference assembly for execution.

Così l'aspettativa è che in fase di esecuzione si dovrebbe sostituire in un'assemblea reale che ha la stessa firma dei metadati.

Se è stato caricato dinamicamente un assieme con Assembly.ReflectionOnlyLoad(), è possibile eseguire tutte le operazioni di riflessione su di esso (leggere tipi, metodi, proprietà, attributi, ecc., Ma non richiamarne dinamicamente nessuno).


Sono curioso di sapere qual è il tuo caso d'uso per creare un assembly solo per metadati. Non ho mai dovuto farlo prima e mi piacerebbe sapere se hai trovato un uso interessante per loro ...

+2

che costituisce un ** esempio forzato **: è possibile creare un'immagine nativa di un assembly .NET utilizzando ad es. Mono mkbundle.exe. Ora si potrebbe ancora voler consentire alle DLL di plugin di accedere all'interfaccia pubblica dell'assieme originale. Sono sicuro che puoi farlo funzionare in questo modo. Se qualcosa dovesse risultare in _really_ obfuscated e _large_ assemblies :) – sehe

+0

L'aggiunta dell'attributo ReferenceAssembly non modifica l'output in un assembly solo per metadati come gli assembly di riferimento .NET 4. Sto cercando di scoprire come vengono costruiti. Dovrò provare, ma dopo aver gestito l'eccezione BadImageFormatException, pensi che la risoluzione dell'assembly chiamerà il mio gestore AssemblyResolve? (Aggiungerò i dettagli del mio caso d'uso alla domanda.) – Govert

+0

Ho aggiunto alcune informazioni sul motivo per cui sono interessato. @sehe non è lontano dal marchio! Quegli assemblaggi impacchettati sono in realtà piccoli, poiché li comprimono prima di essere imballati e gli assembly CLI si comprimono molto bene. Il risultato è offuscato solo nel senso di "oscurità" - gli assembly .NET non sono nella tua faccia, quindi devi fare un po 'di lavoro prima di puntarli su ILSpy. Ma un offuscatore di questo genere sarebbe un altro buon caso d'uso. – Govert

2

Sì, questo è nuovo per. NET 4.0. Sono abbastanza sicuro che questo è stato fatto per evitare i brutti problemi di versioning nei pacchetti di servizi .NET 2.0. Il miglior esempio è il sovraccarico WaitHandle.WaitOne (int), aggiunto e documentato in SP2. Un sovraccarico popolare perché evita di dover indovinare il valore corretto per * exitContext "nel sovraccarico di WaitOne (int, bool). Il problema è, il programma bombs quando viene eseguito su una versione 2.0 più vecchia di SP2. diagnostico sia. Isolando le assemblee di riferimento assicura che questo non possa accadere di nuovo.

io penso queste assemblee di riferimento sono stati creati a partire da una copia dei assembly compilati (come è stato fatto nelle versioni precedenti) e in esecuzione attraverso uno strumento che rimuove l'IL dall'assemblaggio, ma questo strumento non è disponibile per noi, nulla nella sottodirectory di Windows 7.1 SDK bin/netfx 4.0 che potrebbe farlo. Non è esattamente uno strumento che viene usato spesso, quindi probabilmente non è qualità della produzione :)

+0

Ah! Penso che sia lo strumento che sto cercando ... – Govert

+1

Hans, credo che quello strumento sia effettivamente usato più spesso di quanto tu possa pensare. Solo gli assemblaggi di meta-dati vengono utilizzati per il bootstrap degli assembly Core .Net Framework, come spiegato in [questa risposta] (http://stackoverflow.com/questions/1316518/z/1316587) a una domanda su come vengono compilati .Net Assemblee quadro. Naturalmente, ci sono altre modifiche apportate tramite strumenti speciali per quegli assembly, come i tipi di primitivi che hanno riferimenti al membro 'm_value' sostituito con riferimenti a' this'. –

+0

Grazie Kevin per il puntatore all'altra domanda. Quindi tali assembly di riferimento sono assembly "solo" metadati "disidratati". – Govert

1

Potresti avere fortuna con la Biblioteca Cecil (da Mono); Penso che l'implementazione consenta la funzionalità di ILMerge, potrebbe anche scrivere solo assemblaggi di metadati.

ho scansionato il codice di base (documentazione è scarsa), ma non ho trovato alcun indizio evidenti ancora ...

YYMV

3

Se siete ancora interessati a questa possibilità, ho fatto un fork del progetto il-repack basato su Mono.Cecil che accetta un argomento della riga di comando "/ meta" per generare un assembly solo metadati per i tipi public e protected.

https://github.com/KarimLUCCIN/il-repack/tree/xna

(ho provato su Framework XNA piena e il suo lavoro per quanto ne so ...)

+0

Grazie (anche per la pubblicazione di nuovo qui)! Ancora interessato - darò un'occhiata quando avrò la possibilità. – Govert

Problemi correlati