Vorteile der Verwendung von DLL-Dateien gegenüber dem Verknüpfen von CS-Dateien mit Projekten (für meine eigenen generischen Hilfsklassen / Erweiterungsmethoden)


38

Ich habe ein Hilfsprojekt, das ich in allen von mir erstellten Anwendungen verwende. Es enthält einige Erweiterungsmethoden und eine Reihe allgemeiner Hilfsklassen, Steuerelemente usw. Ich aktualisiere / erweitere das Hilfsprojekt von Zeit zu Zeit. Dies sind normalerweise kleine und unabhängige Projekte, und ich bin die einzige Person, die an allen arbeitet.

Ich habe zwei Ansätze ausprobiert

  • Fügen Sie .cs-Dateien direkt (Als Link hinzufügen) zu jedem Projekt hinzu, in dem ich sie verwende
  • Kompilieren Sie es als DLL und fügen Sie es als Verweis hinzu

Ich sehe einige Vor- und Nachteile dieser Ansätze.
Der erste:

  • ist einfacher, weil die Hilfsklassen in die exe-Datei kompiliert werden, daher kann ich oft sehr einfach nur eine einzelne .exe-Datei bereitstellen, die gut funktioniert. Da ich als Link hinzufüge, kann ich ziemlich sicher sein, dass die Hilfedateien immer die neueste Version sind, wenn ich ein Projekt erstelle, das den Helfer verwendet.
  • ist noch einfacher, da ich die Dateien trennen kann, sodass meine Erweiterungsmethoden, die unter .NET 4.0 einwandfrei ausgeführt werden, getrennt von denen referenziert werden können, für die .NET 4.5 erforderlich ist. Dies bedeutet, dass die App als Ganzes unter .NET 4.0 ausgeführt werden kann
  • Ermöglicht das Debuggen des Codes mit allen Vorteilen von Haltepunkten usw. usw.
  • scheint nicht 'best practice' zu sein

Der zweite:

  • scheint der richtige Ansatz zu sein, aber:
  • Ich muss eine separate DLL-Datei bereitstellen, was für Benutzer aus irgendeinem Grund sehr viel schwieriger ist (sie geben meine Programme normalerweise ohne die DLL frei, die dann beim Start abstürzt).
  • Da es zu einer einzigen DLL kompiliert wird, ist die höchste Version von .NET erforderlich. Viele meiner Benutzer verfügen nicht über .NET 4.5, und dies ist nur für einige Elemente meiner Helferklasse erforderlich. Dies bedeutet, dass ich einige Leute zwingen kann ihre Systeme ohne Grund zu aktualisieren
  • Ich muss auch sicherstellen, dass ich bei jedem Update eines meiner Programme auch die DLL-Datei übergebe - auch wenn ich nicht weiß, ob sie seit der letzten Version geändert wurde oder nicht (es hätte sein können, aber es ist) könnte genauso gut die selbe Version sein). Ich kann keinen einfachen Weg finden, dies festzustellen, ohne die Versionsnummer der Baugruppe zu verfolgen, was zusätzliche Arbeit bedeutet. Fürs Erste, wenn ich meine Programme aktualisiere, liefere ich nur aktualisierte exe, und ich mag es klein und unauffällig zu halten.

Also, was ist der eigentliche Vorteil für die Verwendung der DLL-Datei hier? Bitte beachten Sie, dass ich der einzige Bearbeiter aller Anwendungen und Hilfedateien bin.


Zur Verdeutlichung: Die Apps sind normalerweise sehr klein, während der in den Hilfsklassen enthaltene Code für alle von ihnen generisch ist (einige einfache Zeichenfolgenvergleiche, Pfade oder XML-Operationen usw.).


Eigentlich hat mir gerade jemand klar gemacht, dass es eine dritte Option gibt. Da ich den Hilfecode in einem separaten Projekt habe, kann ich dieses Projekt zu Lösungen für jede meiner separaten Anwendungen hinzufügen. Dies funktioniert ähnlich wie "Als Link hinzufügen" für einzelne Dateien, außer ich füge nur ein einziges Projekt hinzu ... Aber Wie Doc Brown bemerkt hat, bedeutet dies im Wesentlichen, dass die .dll-Datei trotzdem zum Projekt hinzugefügt werden muss ...

Eine weitere Möglichkeit, die DLL-Dateien nicht zu verwenden, ist die Möglichkeit, aktiv über die Hilfsklasse zu debuggen ...


3
Du hast recht, und ich mache es sogar, da es bei höheren .NET-Anforderungen hilft ... Aber ich mache es nicht gerne ... Ein Installer für eine 40-kb-App ist ein bisschen übertrieben :)
Bartosz

3
Nun, Sie können immer so etwas wie Costura verwenden , es ist ein Tool zum Zusammenführen von DLLs. Sie können alle Abhängigkeiten mit der EXE-Datei zusammenführen, eine einzige Datei beibehalten und alle erforderlichen Bibliotheken verwenden. Dies kann der Einfachheit halber für den Erstellungsprozess automatisiert werden.
Kroltan

2
Wenn Sie einer Projektmappe ein Projekt hinzufügen, müssen Sie die DLL dieses Projekts mit allen oben aufgeführten Nachteilen weiterhin bereitstellen.
Doc Brown

2
@ DocBrown - Heiliger Mist, du hast Recht :)
Bartosz

1
Das Verknüpfen von CS-Dateien oder -Projekten kann einen weiteren Nachteil haben. Wenn Sie diese freigegebenen Dateien in vielen Projekten verwenden und für ein Projekt eine grundlegende Änderung an Ihren freigegebenen Bibliotheken erforderlich ist, müssen Sie jetzt Ihre anderen Projekte umgestalten. Verweisende DLLs isolieren Sie davon, wenn es keinen Grund für Ihren Code gibt, die aktualisierte Logik zu erfordern. Ich war Teil von Entwicklungsteams, die auf dieses Problem gestoßen sind, wenn es bei freigegebenen Projekten um benutzerdefinierte Authentifizierung geht. Der Kunde möchte eine Änderung für eine neue Anwendung versuchen, und jetzt müssen Sie Ihre gemeinsame Bibliothek irgendwie versionieren. Verwenden Sie dazu DLLs.
Ellesedil,

Antworten:


13

Sie haben die meisten Vor- und Nachteile bereits erkannt. Die Verwendung von cs-Dateien als Referenzen ist in der Tat einfacher und oft einfacher zu verwalten. Ich empfehle jedoch, diesen Ansatz ausschließlich zu verwenden, wenn Ihre csDateien vollständig in sich geschlossen sind und keine besonderen Build-Anforderungen bestehen.

Verwenden separater DLLs

  • macht Abhängigkeiten zu anderen Dienstprogrammen oder Bibliotheken explizit (solange Sie keine solchen Abhängigkeiten haben, funktioniert es einwandfrei)

  • Mit dieser Option können Sie bestimmte Buildkonfigurationen definieren (wenn eine Klasse beispielsweise nur in einer x86-Konfiguration funktioniert oder mindestens .NET 4.0 benötigt, wird diese Anforderung in der Buildkonfiguration der Assembly explizit angegeben).

Vor allem, wenn Sie viele in sich geschlossene Einzelklassen-Komponenten haben, ist die Verwendung von Verweisen auf Dateien in Ordnung. Wenn Sie jedoch Komponenten haben, die auf andere Komponenten verweisen, oder bestimmte Build-Anforderungen haben, würde ich die Verwendung von DLLs empfehlen.

Um die Probleme bei der Verwaltung vieler separater DLLs zu verringern, können Sie entweder ein Installationspaket erstellen oder ILMerge verwenden , mit dem eine Reihe von Assemblys in eine einzelne ausführbare Datei eingebettet werden können. In unserer Umgebung wird das Problem unterschiedlich behandelt, indem für jede Anwendung ein Bereitstellungsskript verwendet wird. Dieses Skript stellt sicher, dass alle benötigten DLLs immer an die Produktion geliefert werden, wenn eine neue Anwendungsversion veröffentlicht wird.


Ok, vielen Dank - verstehe ich also richtig, dass es kein Gräuel ist, sie einfach zu verlinken, solange meine Helferklassen nicht auf andere externe DLLs verweisen (nur Standard-.NET-Code enthalten)?
Bartosz,

@Bartosz: Keine externen DLLs, und jede Hilfsklasse sollte idealerweise keine andere Hilfsklasse oder nur andere Hilfsklassen verwenden, die in derselben Datei gespeichert sind. Um ehrlich zu sein, können Sie bis zu einem gewissen Grad die Situation bewältigen, in der Hilfsklasse A Hilfsklasse B in einer separaten Datei gespeichert werden muss, aber dieser Ansatz lässt sich nicht gut skalieren.
Doc Brown

1
@PeterK. - Ja, und ich tat :)
Bartosz

1
@whatsisname: nicht, dass das nicht funktionieren könnte. Für mich klingt es jedoch nicht nach einer Lösung, die die Dinge vereinfachen würde, sondern nach einer, die unerwartete Probleme verursachen kann ;-)
Doc Brown

1
@Ozkan: In unserer Umgebung handelt es sich lediglich um eine xcopy-Bereitstellung auf einer Netzwerkfreigabe (mit einigen zusätzlichen Schritten zum Sichern der früheren Version und zum Sicherstellen, dass niemand das aktuelle Programm verwendet - was durch den Versuch erreicht wird, den Bereitstellungsordner zuerst umzubenennen). Es weiß, welche DLLs bereitgestellt werden müssen, da wir die Liste der erforderlichen DLLs fest in das Skript codieren - keine Magie dahinter. Diese Lösung ist nicht perfekt, funktioniert aber in den meisten Fällen, mit Ausnahme von Programmen, die von Dutzenden von Benutzern häufig verwendet werden.
Doc Brown

11

DLLs sind praktisch, wenn eine Anwendung groß ist und es Teile gibt, die aktualisiert werden müssen, jedoch nicht die gesamte Anwendung. Wenn Sie also MS Word schreiben, ist es praktisch, den Rechtschreibprüfungscode in einer DLL zu haben, die aktualisiert werden kann, ohne dass die Gesamtheit von MS Word aktualisiert werden muss. Wenn Sie eine kleine Utility-App schreiben (oder eine Reihe von in sich geschlossenen Apps, die alle denselben Code verwenden), spielt es keine große Rolle, ob der Code in die App (s) eingebettet ist oder nicht.


2

Sie haben es in Ihrer Frage so ziemlich zusammengefasst, ich habe nur ein paar Punkte hinzuzufügen.

Mono Options ist ein großartiges Beispiel für ein NuGet-Paket, das den ersten Ansatz sehr gut verwendet.

Wenn Sie sich für die Verwendung von DLLs entscheiden, können Sie auch Tools wie Costura verwenden , um diesen Verweis als eingebettete Ressource in Ihre ausführbare Datei einzubetten. Um es zu benutzen, füge einfach das Costura.FodyPaket hinzu:

Install-Package Costura.Fody

Tatsächlich gibt es noch etwas - mit eingebetteten Projekten oder Dateien, die als Link hinzugefügt wurden, können Sie den Code auch aktiv durch die Hilfedatei debuggen ...
Bartosz

1
@ Bartosz Ich denke, Sie können immer noch "den ganzen Weg durch" ohne die "Hilfedatei" debuggen, solange Sie die richtige PDB-Datei haben.
Zack

Ich habe das Costura-Ding ausprobiert und es gefällt mir sehr gut!
Bartosz

2

Ob eine DLL vorteilhafter ist oder nicht, hängt von mehreren Faktoren ab:

  1. Die Größe des Codes (beim Kompilieren).
  2. Wie viele Exes benutzen es?
  3. Wie oft möchten Sie den Code aktualisieren?
  4. Ob die Exes zusammengehalten werden sollen oder ganz getrennt existieren.

Der Zweck einer gemeinsam genutzten Bibliothek besteht darin, Code zu verwenden, der mehreren ausführbaren Dateien gemeinsam ist, und ihn so zu zentralisieren, dass alle ausführbaren Dateien eine Kopie gemeinsam nutzen. Dies soll Platz sparen und die Aktualisierung des Codes vereinfachen.

Wenn die Menge an Code in Ihrer Hilfsklasse sehr gering ist, lohnt es sich möglicherweise nicht, ihn in eine DLL zu verschieben, da der Overhead des Codes in einer DLL dem platzsparenden Vorteil der Zentralisierung entgegenwirken kann.

Wenn Sie nur wenige ausführbare Dateien erstellen, ist die Größe des Codes in jeder ausführbaren Datei möglicherweise so gering, dass dies kein Problem darstellt. Je mehr ausführbare Dateien Sie jedoch mit demselben Code verwenden, desto vorteilhafter ist es, den Code in eine DLL zu verschieben.

Nehmen wir vereinfacht an, Ihre Hilfsklasse kompiliert in einer exe-Datei bis zu 128 Bytes, aber wenn sie in eine dll verschoben wird, beträgt die dll 512 Bytes. Wenn Sie nur drei ausführbare Dateien haben, sparen Sie Platz, indem Sie den Code in die ausführbaren Dateien aufnehmen. Wenn Sie jedoch 5 ausführbare Dateien hätten, wären Sie an dem Punkt angelangt, an dem Sie eine DLL besser hätten, da der kombinierte Speicherplatz, der von 5 Kopien des Codes belegt wird (5 * 128 = 640 Byte), mehr als der belegte Speicherplatz ist durch den Code in einer DLL (512 Bytes).

Angenommen, Sie finden einen Fehler in Ihrem Hilfecode. Wenn Sie alle Ihre ausführbaren Dateien mit dem eingebauten Code kompiliert haben, müssen Sie jede einzelne ausführbare Datei neu kompilieren und anschließend die neu kompilierten Versionen neu verteilen. Wenn Sie den Code in eine DLL kompilieren würden, müssten Sie nur die eine DLL neu kompilieren und verteilen, und der Fehler würde automatisch für alle ausführbaren Dateien behoben, die sie verwenden.

Damit ein Programm eine DLL finden kann, muss es wissen, wo es nach der DLL suchen muss. Wenn Sie alle ausführbaren Dateien zusammenhalten, können Sie die DLL einfach in dasselbe Verzeichnis stellen, und alle finden sie sofort. Wenn Sie sie absichtlich getrennt halten, wird es schwieriger, sie zu koordinieren, um dieselbe DLL zu verwenden.


1

Ihre dritte Option ist die am besten geeignete (fügen Sie sie als separates "Klassenbibliothek" -Projekt zur Lösung hinzu). Dies vereint die Vorteile aller Ansätze:

  • Ihr "Hilfsprojekt" ist in allen Projekten immer auf dem neuesten Stand.
  • Sie können auf den Code des Projekts verweisen, wenn Sie Änderungen schnell sehen möchten.
  • Sie können es jedes Mal für die richtige .NET-Version erstellen.
  • Sie können eine DLL trotzdem in eine Exe einbetten, machen Sie sich also keine Sorgen, dass Sie diese als Teil Ihres Builds haben können.

Wir machen das die ganze Zeit und ich kann nichts anderes tun, als diesen Ansatz zu empfehlen.

Eine andere vierte Alternative, die Sie nicht erwähnt haben, besteht darin, sie in ein privates NuGet-Repository zu stellen, damit Sie sie korrekt versionieren und ohne das zusätzliche Projekt in jeder Lösung darauf verweisen können.


2
Hm, es scheint mir, dass wenn ich es als Projekt zur Projektmappe hinzufüge und dann auf dieses Projekt in anderen Projekten verweise, es trotzdem als separate DLL erstellt wird, anstatt eingebettet zu werden ... Gibt es etwas, das ich spezifizieren sollte?
Bartosz,

1

Als Entwickler möchte ich immer die Referenz der Utility-Lösung in meine Anwendung aufnehmen, da dies mir ermöglicht, den Code zu debuggen (und mögliche Fehler auch in Utility zu erkennen!). Außerdem werden alle am Utility vorgenommenen Änderungen automatisch in die Anwendung aufgenommen.

Die Entscheidung hängt also davon ab, wie ausgereift das Dienstprogramm ist! Wenn Sie sich über die Programmfehler nicht sicher sind, sollten Sie immer die .cs-Datei dieses Dienstprogramms einschließen, um die Fehler herauszufinden. Wenn Sie sich jedoch sicher sind, dass das Dienstprogramm ausgereift genug ist, wird es dort keine Fehler auslösen Wenn das Dienstprogramm keine Erweiterungsmöglichkeiten bietet, können Sie die DLL-Datei einbinden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.