Vantaggi dell'uso dei file .dll rispetto al collegamento dei file .cs ai progetti (per le mie classi helper generiche / metodi di estensione)


38

Ho un progetto di aiuto che utilizzo in tutte le applicazioni che creo. Contiene alcuni metodi di estensione e un gruppo di classi helper generiche, controlli ecc. Di tanto in tanto aggiorno / estendo il progetto helper. Questi di solito sono progetti piccoli e non correlati, e io sono l'unica persona che lavora su tutti loro.

Ho provato due approcci per usarlo

  • aggiungere i file .cs direttamente (Aggiungi come collegamento) a ciascun progetto in cui li utilizzo
  • compilarlo come .dll e aggiungerlo come riferimento

Vedo alcuni vantaggi e svantaggi di questi approcci.
Il primo:

  • è più semplice, perché le classi helper vengono compilate nel file exe, quindi spesso posso facilmente fornire un solo file .exe che funzionerà perfettamente. Poiché aggiungo come collegamento, posso essere abbastanza sicuro che ogni volta che creo un progetto che utilizza l'helper, i file dell'helper saranno la versione più recente.
  • è ancora più semplice, perché posso separare i file, in modo che i miei metodi di estensione che funzionano correttamente su .NET 4.0 possano essere referenziati separatamente da quelli che richiedono .NET 4.5, il che significa che l'app nel suo complesso può funzionare su .NET 4.0
  • Permette il debug attraverso il codice, con tutti i vantaggi di breakpoint ecc. Ecc.
  • non sembra essere la "migliore pratica"

Il secondo:

  • sembra essere l'approccio giusto, ma:
  • mi richiede di consegnare un file DLL separato, che per qualche ragione è molto più difficile per gli utenti (tendono a condividere i miei programmi senza il DLL, che quindi si arresta in modo anomalo all'avvio)
  • poiché viene compilato in una singola DLL, richiederà la versione più alta di .NET - molti dei miei utenti non hanno .NET 4.5 e solo alcuni elementi della mia classe di supporto lo richiedono, il che significa che posso forzare alcune persone per aggiornare i loro sistemi senza motivo
  • Devo anche assicurarmi che ogni volta che aggiorno uno dei miei programmi, consegno anche il file .dll, anche se non so se è stato modificato dall'ultima versione, oppure no (avrebbe potuto essere, ma poteva potrebbe anche essere la stessa versione). Non riesco a vedere un modo semplice per determinarlo, senza tenere traccia della versione dell'assembly, che è un lavoro aggiuntivo. Per ora, quando aggiorno i miei programmi, consegno solo exe aggiornato e mi piace mantenerlo piccolo e di basso profilo.

Quindi, qual è il vantaggio effettivo dell'utilizzo del file DLL qui? Tieni presente che sono l'unica persona che modifica il codice di tutte le applicazioni e i file di supporto.


Inoltre, per chiarire: le app sono in genere molto piccole, mentre il codice contenuto nelle classi di supporto è completamente generico per tutte (alcune semplici comparazioni di stringhe, percorsi o operazioni XML, ecc.)


In realtà, qualcuno mi ha fatto capire proprio ora che c'è una terza opzione. Dato che ho il codice helper in un progetto separato, posso aggiungere questo progetto alle soluzioni di ciascuna delle mie applicazioni separate - che funziona in un modo come "Aggiungi come collegamento" per singoli file, tranne che per aggiungere solo un singolo progetto ... Ma come notato da Doc Brown, ciò significa essenzialmente che .dll dovrà comunque essere aggiunto al progetto ...

Ancora un'altra cosa che è in qualche modo a favore del non usare i file DLL è la possibilità di eseguire il debug attraverso la classe helper attivamente ...


3
Hai ragione, e lo sto anche facendo, perché aiuta in caso di requisiti .NET più elevati ... Ma non mi piace farlo ... Un programma di installazione per l'app da 40kb è un po 'eccessivo :)
Bartosz,

3
Bene, puoi sempre usare qualcosa come Costura , è uno strumento per unire le DLL. È possibile unire tutte le dipendenze a EXE, mantenendo un singolo file e consentendo di utilizzare tutte le librerie necessarie. Questo può essere automatizzato per il processo di compilazione, per semplicità.
Kroltan,

2
Quando aggiungi un progetto a una soluzione, devi comunque distribuire la DLL di questo progetto, con tutti gli svantaggi elencati in precedenza.
Doc Brown,

2
@DocBrown - merda santa, hai ragione :)
Bartosz,

1
Il collegamento di file o progetti .cs può avere un altro svantaggio. Se stai usando questi file condivisi in molti progetti e un progetto richiede una modifica sostanziale delle tue librerie condivise, ora devi rifattorizzare gli altri tuoi progetti. Le DLL di riferimento ti isolano da questo se non c'è motivo per il tuo codice per richiedere la logica aggiornata. Ho fatto parte di team di sviluppo che si sono imbattuti in questo problema quando i progetti condivisi riguardano cose come l'autenticazione personalizzata. Il cliente desidera provare una modifica per una nuova applicazione e ora è necessario in qualche modo eseguire la versione della libreria comune. Usando dlls farlo.
Ellesedil,

Risposte:


13

Hai già individuato la maggior parte dei pro e dei contro. L'uso dei file cs come riferimenti è infatti più leggero e spesso più facile da gestire. Tuttavia, ti consiglio di utilizzare questo approccio esclusivamente quando i tuoi csfile sono completamente autonomi e non hanno particolari requisiti di build.

Utilizzo di DLL separate

  • renderà esplicite le dipendenze da altre utilità o librerie (quindi finché non si hanno tali dipendenze, funzionerà bene)

  • ti consentirà di definire specifiche configurazioni di build (ad esempio, se una classe funziona solo in configurazione x86 o necessita almeno di .NET 4.0, la configurazione di build dell'assembly rende esplicito questo requisito).

Quindi, specialmente se disponi di molti componenti autonomi di una sola classe, l'uso del riferimento ai file va bene, ma se hai componenti che fanno riferimento ad altri componenti o requisiti di build specifici, consiglierei di utilizzare le DLL.

Per mitigare i problemi con la gestione di molte DLL separate, è possibile creare un pacchetto di installazione o utilizzare ILMerge , che può incorporare un set di assembly in un singolo eseguibile. Nel nostro ambiente, affrontiamo il problema in modo diverso, utilizzando uno script di distribuzione per ogni applicazione. Questo script assicura che tutte le DLL necessarie vengano sempre consegnate alla produzione quando viene pubblicata una nuova versione dell'applicazione.


Ok, grazie mille - quindi, ho capito bene, fintanto che le mie classi helper non fanno riferimento ad altre dll esterne (contengono solo codice .NET standard) non è un abominio semplicemente collegarle?
Bartosz,

@Bartosz: nessuna DLL esterna, e ogni classe di supporto non dovrebbe idealmente usare nessun'altra classe di supporto, o solo altre classi di supporto che sono archiviate nello stesso file. Ad essere onesti, in una certa misura è possibile gestire la situazione in cui la classe di supporto A necessita della classe di supporto B memorizzata in un file separato, ma questo approccio non si adatta bene.
Doc Brown,

1
@PeterK. - Sì, e l'ho fatto :)
Bartosz,

1
@whatsisname: non che questo non possa funzionare. Tuttavia, per me non sembra una soluzione che semplifichi le cose, più come una che può causare problemi imprevisti ;-)
Doc Brown,

1
@Ozkan: nel nostro ambiente, è solo una distribuzione xcopy su alcune condivisioni di rete (con alcuni passaggi aggiuntivi per il backup della versione precedente e per assicurarsi che nessuno utilizzi il programma attualmente - che si ottiene tentando di rinominare prima la cartella di distribuzione). Sa quali DLL distribuire perché codifichiamo la lista della DLL richiesta nello script - nessuna magia dietro di essa. Questa soluzione non è perfetta, ma funziona per noi nella maggior parte dei casi, ad eccezione dei programmi che sono utilizzati pesantemente da dozzine di utenti.
Doc Brown

11

Le DLL sono utili quando un'applicazione è grande e ci sono pezzi che richiedono aggiornamenti, ma non l'intera applicazione. Quindi, se stai scrivendo MS Word, è utile avere il codice di controllo ortografico in una DLL che può essere aggiornato senza dover aggiornare interamente MS Word. Se quello che stai scrivendo è una piccola app di utilità (o una serie di app autonome che utilizzano tutte lo stesso codice) non fa molta differenza se il codice è incorporato o meno nelle app.


2

Hai praticamente riassunto la tua domanda, ho solo un paio di punti da aggiungere.

Mono Options è un ottimo esempio di pacchetto NuGet che utilizza molto bene il primo approccio.

In alternativa, se decidi di usare le dll puoi usare strumenti come Costura per incorporare quel riferimento nel tuo eseguibile come risorsa incorporata. Per usarlo basta aggiungere il Costura.Fodypacchetto:

Install-Package Costura.Fody

In realtà, c'è un'altra cosa: con il progetto incorporato oi file aggiunti come link, puoi anche eseguire il debug attivo del codice attraverso il file di supporto ...
Bartosz,

1
@Bartosz Penso che tu possa ancora eseguire il debug "completamente" senza il "file helper", purché tu abbia il file pdb corretto.
Zack,

Ho provato la cosa Costura e mi piace molto!
Bartosz,

2

Se una DLL sia più vantaggiosa o meno dipende da diversi fattori:

  1. La dimensione del codice (una volta compilato).
  2. Quanti ex lo usano.
  3. Con quale frequenza intendi aggiornare il codice.
  4. Se gli ex debbano essere tenuti insieme o esistano completamente separatamente.

Lo scopo di una libreria condivisa è prendere il codice comune a più eseguibili e centralizzarlo in modo che tutti gli eseguibili condividano una copia. Questo ha lo scopo di risparmiare spazio e facilitare l'aggiornamento del codice.

Se la quantità di codice nella tua classe di supporto è molto piccola, potrebbe non valere la pena spostarlo in una dll poiché l'overhead del codice che si trova in una dll può contrastare il vantaggio di risparmiare spazio di averlo centralizzato.

Inoltre, se stai realizzando solo alcuni eseguibili, la dimensione del codice in ciascun eseguibile potrebbe essere abbastanza piccola da non costituire un problema. Tuttavia, più file eseguibili si utilizza lo stesso codice, più vantaggioso sarebbe che il codice venisse spostato in una dll.

Come esempio semplificato, supponiamo che la tua classe helper si compili in 128 byte in un file exe, ma quando viene spostata in una dll, la dll è di 512 byte. Se hai solo 3 eseguibili, risparmierai spazio includendo il codice negli eseguibili. Tuttavia, se avessi 5 eseguibili, allora saresti nel punto in cui sarebbe meglio avere una dll perché lo spazio combinato occupato da 5 copie del codice (5 * 128 = 640 byte) è maggiore dello spazio occupato avendo il codice in una dll (512 byte).

Ora dì per esempio che trovi un bug nel tuo codice helper. Se hai compilato tutti i tuoi eseguibili con il codice inserito, devi ricompilare ogni singolo eseguibile e quindi ridistribuire le versioni ricompilate. Se hai compilato il codice in una dll, dovresti solo ricompilare e ridistribuire la dll e il bug verrebbe automaticamente riparato per tutti gli eseguibili che lo utilizzavano.

Infine, affinché un programma trovi una dll, deve sapere dove cercare la dll. Se stai mantenendo tutti i tuoi eseguibili insieme, puoi semplicemente mettere la dll nella stessa directory e la troveranno subito. Se li stai tenendo intenzionalmente separati, diventa più difficile coordinarli per usare la stessa dll.


1

La terza opzione è la più appropriata (aggiungerla come progetto separato "libreria di classi" alla soluzione). Questo combina i vantaggi di tutti gli approcci:

  • Il tuo "progetto di aiuto" è sempre aggiornato su tutti i diversi progetti.
  • È possibile fare riferimento al codice del progetto quando si desidera vedere rapidamente le modifiche.
  • È possibile crearlo per la versione .NET corretta ogni volta.
  • Puoi comunque incorporare una DLL in un exe, quindi non preoccuparti che puoi averlo come parte della tua build.

Lo facciamo sempre e non posso fare altro che raccomandare questo approccio.

Un'altra quarta alternativa che non hai menzionato è quella di metterlo su un repository NuGet privato che ti consentirebbe di eseguirne la versione corretta e di fare riferimento a esso senza il progetto aggiuntivo in ciascuna soluzione.


2
Hm, mi sembra che quando lo aggiungo come progetto alla soluzione e quindi faccio riferimento a questo progetto in altri progetti, allora viene ancora creato come una DLL separata anziché essere incorporato ... C'è qualcosa che dovrei specificare?
Bartosz,

1

Come sviluppatore, mi piace sempre includere il riferimento della soluzione dell'utilità alla mia applicazione in quanto mi consente di eseguire il debug del codice (e individuare eventuali bug anche nell'utilità!) E qualsiasi modifica apportata all'utilità viene automaticamente inclusa nell'applicazione.

Quindi, in realtà la decisione dipende da quanto è matura l'utilità ! Se non sei sicuro dei bug di Utility, allora dovresti sempre includere il file .cs di quella utility per scoprire i bug .. Ma se sei sicuro che Utility sia abbastanza matura e non restituirà il risultato con nessun bug e lì non esiste alcun margine di miglioramento nell'utilità, è possibile andare avanti e includere il file DLL.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.