AntonioPelleriti.it [aka z9]

I code, therefore I am

NAVIGATION - SEARCH

Inglobare tutte le dll in un singolo exe e utilizzarle con la Reflection

La stragrande maggioranza delle applicazioni usa delle dll esterne, eventualmente di terze parti.

Quando l'applicazione deve essere distribuita anche gli assembly da cui dipende, cioè tutti i riferimenti esterni devono essere distribuiti assieme all'eseguibile. In generale lo si fa con la classica tecnica Xcopy, prendendo tutto quello che c'è nella cartella Bin/Release prodotta da Visual Studio per esempio, oppure creando un setup ad hoc che si occupi di tutto.

Un'altra possibile tecnica è quella di inglobare tutte le dll all'interno dell'eseguibile e quindi con la comodità di distribuire un solo file.

Supponiamo di avere una semplice applicazione Windows Forms, che utilizza una dll per esempio chiamata MyAssembly.dll.

Al progetto Windows Forms, che avrà un riferimento alla libreria, bisogna apportare una prima modifica, aggiungendo il file MyAssembly.dll come un normale file (click con il destro, Add Existing Item e selezione della dll) e quindi, fra le proprietà del file aggiunto, impostando il valore della proprietà Build Action a Embedded Resource.

A questo punto compilando l'applicazione, l'eseguibile prodotto conterrà la dll come risorsa inglobata. Potete verificarlo con un decompilatore come Reflector o JustDecompile.

 

 

Adesso bisogna fare in modo che a runtime l'applicazione sia in grado di recuperare la dll dalle risorse embedded.

Nel metodo Main dell'applicazione aggiungiamo un gestore dell'evento AssemblyResolve dell'AppDomain corrente:

 static void Main()
 {
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
...

 

Il gestore dell'evento, si occupa di ricercare fra le risorse embedded l'assembly (l'evento si scatena al primo utilizzo dell'assembly riferito) e di restituirlo leggendone il contenuto e caricandolo con il metodo Assembly.Load:

private static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            string dllName = new AssemblyName(args.Name).Name + ".dll";

            var asm = Assembly.GetExecutingAssembly();
            String resourceName = asm.GetManifestResourceNames().FirstOrDefault(rn => rn.EndsWith(dllName));
            if (resourceName == null) return null; // Non trovata

            using (var stream = asm.GetManifestResourceStream(resourceName))
            {
                Byte[] assemblyData = new Byte[stream.Length];
                stream.Read(assemblyData, 0, assemblyData.Length);
                return Assembly.Load(assemblyData);
            }
        }

 

 


 

Aggiungi Commento

  Country flag

biuquote
  • Commento
  • Anteprima
Loading