Domanda

Se si crea una libreria di classi che utilizza elementi di altri assembly, è possibile incorporare quegli altri assembly all'interno della libreria di classi come una sorta di risorsa?

vale a dire. invece di avere MyAssembly.dll , SomeAssembly1.dll e SomeAssembly2.dll presenti nel file system, questi altri due file vengono raggruppati in < em> MyAssembly.dll e sono utilizzabili nel suo codice.


Sono anche un po 'confuso sul perché gli assembly .NET sono file .dll . Questo formato non esisteva prima di .NET? Tutte le DLL degli assembly .NET sono, ma non tutte le DLL sono assembly .NET? Perché usano lo stesso formato e / o estensione di file?

È stato utile?

Soluzione

Dai un'occhiata a ILMerge per la fusione di assiemi.

  

Sono anche un po 'confuso sul perché gli assembly .NET sono file DLL. Questo formato non esisteva prima di .NET?

Sì.

  

Sono tutte le DLL degli assembly .NET,

Normalmente DLL o EXE, ma possono anche essere netmodule.

  

ma non tutte le DLL sono assembly .NET?

Una corretta.

  

Perché usano lo stesso formato e / o estensione di file?

Perché dovrebbe essere diverso - serve allo stesso scopo!

Altri suggerimenti

ILMerge unisce gli assiemi, il che è carino, ma a volte non è proprio quello che vuoi. Ad esempio, quando l'assembly in questione è un assembly con un nome sicuro e non si dispone della chiave per esso, non è possibile eseguire ILMerge senza interrompere tale firma. Ciò significa che è necessario distribuire più assembly.

In alternativa a ilmerge, puoi incorporare uno o più assembly come risorse nel tuo exe o DLL. Quindi, in fase di esecuzione, quando gli assembly vengono caricati, è possibile estrarre l'assembly incorporato in modo programmatico, caricarlo ed eseguirlo. Sembra complicato, ma c'è solo un po 'di codice del boilerplate.

Per farlo, incorpora un assembly, proprio come faresti con qualsiasi altra risorsa (immagine, file di traduzione, dati, ecc.). Quindi, imposta un AssemblyResolver che viene chiamato in fase di esecuzione. Dovrebbe essere impostato nel costruttore statico della classe startup. Il codice è molto semplice

    static NameOfStartupClassHere()
    {
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolver);
    }

    static System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args)
    {
        Assembly a1 = Assembly.GetExecutingAssembly();
        Stream s = a1.GetManifestResourceStream(args.Name);
        byte[] block = new byte[s.Length];
        s.Read(block, 0, block.Length);
        Assembly a2 = Assembly.Load(block);
        return a2;
    }

La proprietà Name sul parametro ResolveEventArgs è il nome dell'assembly da risolvere. Questo nome si riferisce alla risorsa, non al nome del file. Se incorpori il file "MyAssembly.dll" e chiami la risorsa incorporata "Foo", allora il nome che desideri qui è "Foo". Ma sarebbe confuso, quindi suggerisco di usare il nome file dell'assembly per il nome della risorsa. Se hai incorporato e nominato correttamente il tuo assembly, puoi semplicemente chiamare GetManifestResourceStream () con il nome dell'assembly e caricare l'assembly in quel modo. Molto semplice.

Funziona con più assiemi, esattamente come con un singolo assieme incorporato.

In un'app reale vorrai una migliore gestione degli errori in quella routine - come se non ci fosse stream con il nome dato? Cosa succede se la lettura fallisce? ecc. Ma ti resta da fare.

Nel resto del codice dell'applicazione, si utilizzano normalmente i tipi dall'assieme.

Quando crei l'app, devi aggiungere un riferimento all'assembly in questione, come faresti normalmente. Se si utilizzano gli strumenti da riga di comando, utilizzare l'opzione / r in csc.exe; se usi Visual Studio, dovrai " Aggiungi riferimento ... " nel menu popup sul progetto.

In fase di esecuzione, il controllo e la verifica della versione dell'assembly funzionano normalmente.

L'unica differenza è nella distribuzione. Quando si distribuisce o distribuisce l'app, non è necessario distribuire la DLL per l'assembly incorporato (e referenziato). Basta distribuire l'assemblaggio principale; non è necessario distribuire gli altri assembly perché sono incorporati nella DLL o EXE principale.

Puoi puoi incorporare un assembly (o qualsiasi file, in realtà) come risorsa (e quindi utilizzare la classe ResourceManager per accedervi), ma se vuoi semplicemente combinare assiemi, stai meglio usando uno strumento come ILMerge .

I file EXE e DLL sono File eseguibili portatili di Windows , che sono abbastanza generici da ospitare futuri tipi di codice, incluso qualsiasi codice .NET (possono anche essere eseguiti in DOS ma visualizzano solo un messaggio che dice che non dovrebbero essere eseguiti in DOS). Includono le istruzioni per avviare .NET runtime se non è già in esecuzione. È anche possibile che un singolo assembly si estenda su più file, anche se questo non è quasi mai il caso.

Nota ILMerge non funziona con risorse integrate come XAML, quindi le app WPF ecc. dovranno usare il metodo Cheeso.

Esiste anche l'utilità mkbundle offerta da il progetto Mono

Perché usano lo stesso formato e / o estensione di file?

  
    

Perché dovrebbe essere diverso - serve allo stesso scopo!

  

My 2 & # 162; qualche chiarimento qui: DLL è Dynamic Link Library. Sia il vecchio stile .dll (C-code) che .net style .dll sono per definizione "link dinamico" librerie. Quindi .dll è una descrizione corretta per entrambi.

Rispetto alla risposta di Cheeso di incorporare gli assembly come risorse e caricarli dinamicamente utilizzando il sovraccarico Load (byte []) utilizzando un gestore eventi AssemblyResolve, è necessario modificare il resolver per controllare AppDomain per un'istanza esistente dell'Assemblea per caricare e restituire l'istanza di assembly esistente se è già caricata.

Gli assembly caricati utilizzando quel sovraccarico non hanno un contesto, il che può far sì che il framework tenti di ricaricare l'assembly più volte. Senza restituire un'istanza già caricata, è possibile ottenere più istanze dello stesso codice assembly e tipi che dovrebbero essere uguali ma non lo saranno, poiché il framework li considera provenienti da due assembly diversi.

Almeno un modo in cui più eventi AssemblyResolve verranno creati per lo stesso assembly caricato nel "Nessun contesto" è quando hai riferimenti a tipi che espone da più assembly caricati nel tuo AppDomain, poiché il codice viene eseguito che necessita di quei tipi risolti.

https://msdn.microsoft. com / it-it / library / dd153782% 28v = vs.110% 29.aspx

Un paio di punti salienti del link:

"Altri assiemi non possono essere associati ad assiemi caricati senza contesto, a meno che non si gestisca l'evento AppDomain.AssemblyResolve"

" Il caricamento di più assembly con la stessa identità senza contesto può causare problemi di identità del tipo simili a quelli causati dal caricamento di assembly con la stessa identità in più contesti. Consulta Evita di caricare un assieme in più contesti. & Quot;

Ti suggerirei di provare Costura.Fody . Basta non dimenticare di installare il pacchetto Fody prima di Costura.Fody (per ottenere il Fody più recente!)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top