Переваги використання .dll-файлів над прив’язкою .cs-файлів до проектів (для моїх загальних допоміжних класів / методів розширення)


38

У мене є помічник проекту, який я використовую у всіх створених програмах. Він містить деякі методи розширення та купу загальних допоміжних класів, елементів управління тощо. Час від часу я оновлюю / розширюю хелперний проект. Зазвичай це невеликі та непов'язані проекти, і я єдина людина, яка працює над усіма ними.

Я спробував два підходи до його використання

  • додайте файли .cs безпосередньо (Додати як посилання) до кожного проекту, де я їх використовую
  • компілюйте його як .dll і додайте його як довідник

Я бачу деякі переваги та недоліки цих підходів.
Перший:

  • простіше, тому що класи помічників збираються у файл exe, тому я часто дуже просто можу надати лише один .exe-файл, який буде працювати чудово. Оскільки я додаю як посилання, я можу бути впевнений, що коли я будую будь-який проект, який використовує помічник, файли помічників будуть останньою версією.
  • ще простіше, тому що я можу розділити файли, так що мої методи розширення, які добре працюють на .NET 4.0, можна посилатись окремо від тих, для яких потрібна .NET 4.5, а це означає, що програма в цілому може працювати на .NET 4.0
  • Дозволяє налагоджувати код, з усіма перевагами точок прориву тощо тощо ...
  • не здається, що це "найкраща практика"

Другий:

  • виявляється правильним підходом, але:
  • вимагає, щоб я доставив окремий .dll файл, який чомусь набагато складніше для користувачів (вони, як правило, діляться моїми програмами без .dll, який потім виходить з ладу при запуску)
  • оскільки він збирається в один .dll, для нього знадобиться найвища версія .NET - багато моїх користувачів не мають .NET 4.5, і цього вимагають лише деякі елементи мого допоміжного класу, це означає, що я можу змусити деяких людей оновлювати свої системи без причини
  • Мені також потрібно переконатися, що щоразу, коли я оновлюю будь-яку з моїх програм, я також надсилаю файл .dll - навіть якщо я не знаю, чи він був змінений після останньої версії, чи ні (це могло бути, але це могла б бути та ж версія). Я не можу побачити простий спосіб визначити це, не відслідковуючи версію збірки, що є додатковою роботою. Наразі, коли я оновлюю свої програми, я постачаю лише оновлений exe, і мені подобається, щоб він був невеликим і низьким.

Отже, у чому полягає фактична перевага використання тут файлу .dll? Зауважте, що я єдина особа, яка редагує код усіх програм та допоміжних файлів.


Крім того, для уточнення - додатків зазвичай дуже мало, тоді як код, що міститься в допоміжних класах, є абсолютно загальним для всіх (деякі прості порівняння рядків, шляхи чи XML-операції тощо)


Насправді хтось змусив мене зрозуміти, що існує третій варіант. Оскільки у мене є допоміжний код у проекті separte, я можу додати цей проект до рішень кожного мого окремого додатка - який працює на зразок "Додати як посилання" для окремих файлів, за винятком того, що я додаю лише один проект ... Але як зауважив Док Браун, це по суті означає, що .dll потрібно буде все-таки додати до проекту ...

Ще одна річ, яка на користь того, що не використовувати файли dll, - це можливість активно налагоджувати хелперний клас ...


3
Ви маєте рацію, і я навіть робити це, так як це допомагає в разі більш високих вимог до .NET ... Але мені не подобається це робити ... Інсталятор для 40Kb додатки є трохи зайвим :)
Bartosz

3
Ну, ви завжди можете використовувати щось на зразок Costura , це інструмент для об'єднання DLL. Ви можете об'єднати всі залежності з EXE, зберігаючи єдиний файл і дозволяючи використовувати будь-які необхідні бібліотеки. Це може бути автоматизовано для процесу збирання для простоти.
Кролтан

2
Коли ви додаєте проект до рішення, вам все одно доведеться розгорнути DLL цього проекту з усіма недоліками, які ви перелічили вище.
Doc Brown

2
@DocBrown - святе дерьмо, ти маєш рацію :)
Bartosz

1
Пов’язання файлів або проектів .cs може мати ще один недолік. Якщо ви використовуєте ці спільні файли у багатьох проектах, і один проект вимагає грубих змін у ваших спільних бібліотеках, тепер вам потрібно переробляти інші проекти. Референтні dll захищають вас від цього, якщо немає причини, щоб ваш код вимагав оновленої логіки. Я був частиною команд розробників, які стикалися з цим питанням, коли спільні проекти включають такі речі, як власна автентифікація. Замовник хоче спробувати змінити нову програму, і тепер вам потрібно якось оновлювати вашу спільну бібліотеку. За допомогою dlls зробіть це.
Ellesedil

Відповіді:


13

Ви вже помітили більшість плюсів і мінусів. Використання файлів cs в якості посилань дійсно легше і часто простіше в управлінні. Однак я рекомендую використовувати цей підхід виключно тоді, коли ваші csфайли повністю автономні та не мають особливих вимог до збірки.

Використання окремих DLL-файлів

  • зробить залежності від інших утиліт або бібліотек явними (якщо ви не маєте таких залежностей, це буде добре)

  • дозволить визначити конкретні конфігурації збірки (наприклад, якщо клас працює лише у конфігурації x86 або потребує принаймні .NET 4.0, конфігурація збірки збірки робить цю вимогу явною).

Тому особливо, якщо у вас є багато однокласних, автономних компонентів, використання посилань на файли нормально, але якщо у вас є компоненти, що посилаються на інші компоненти, або конкретні вимоги до збірки, я рекомендую використовувати DLL.

Для усунення проблем з керуванням багатьма окремими DLL можна створити пакет інсталятора або використовувати ILMerge , який може вбудувати набір збірок в єдиний виконуваний файл. У нашому середовищі ми вирішуємо проблему по-різному, використовуючи сценарій розгортання для кожної програми. Цей скрипт гарантує, що всі необхідні DLL-файли завжди будуть доставлені у виробництво при публікації нової версії програми.


Добре, дякую - так, я правильно розумію, що поки мої допоміжні класи не посилаються на будь-які інші зовнішні dll (містять лише стандартний код .NET), це не гидота просто пов'язувати їх?
Бартош

@Bartosz: ніяких експланальних DLL-файлів, і кожен клас-помічник не повинен в ідеалі використовувати жоден інший допоміжний клас або лише інші допоміжні класи, які зберігаються в одному файлі. Якщо чесно, певною мірою ви можете керувати ситуацією, коли для класу A-помічника потрібен помічник класу В, який зберігається в окремому файлі, але такий підхід не відповідає масштабам.
Doc Brown

1
@PeterK. - так, і я зробив :)
Bartosz

1
@whatsisname: не те, що це не може працювати. Однак мені це не здається рішенням, яке б спростило речі, більше схоже на таке, яке може спричинити несподівані проблеми ;-)
Doc Brown

1
@Ozkan: в нашому середовищі це просто розгортання xcopy на деяку мережу (з деякими додатковими кроками для резервного копіювання колишньої версії та переконання, що ніхто зараз не використовує програму - що досягається спробою спочатку перейменувати папку розгортання). Він знає, які dll розгортати, тому що ми жорстко кодуємо список необхідних DLL в сценарій - не магія за ним. Це рішення не є ідеальним, але працює для нас у більшості випадків, за винятком програм, якими активно користуються десятки користувачів.
Док Браун

11

DLL-файли зручні, коли додаток великий і є фрагменти, які потребують оновлення, але не для всієї програми. Отже, якщо ви пишете MS Word, зручно мати код перевірки орфографії у DLL, який можна оновити без необхідності оновлювати всю MS Word. Якщо те, що ви пишете, - це невеликий утилітний додаток (або серія автономних додатків, які трапляються з усіма одним і тим же кодом), це не має великої різниці, вбудований код у програму чи ні.


2

Ви майже підсумували це у своєму запитанні, я маю лише додати декілька пунктів.

Mono Options - чудовий приклад пакету NuGet, який дуже добре використовує перший підхід.

Крім того, якщо ви вирішили використовувати dlls, ви можете використовувати такі інструменти, як Costura, щоб вбудувати цю посилання у свій виконуваний файл як вбудований ресурс. Для його використання просто додайте Costura.Fodyпакет:

Install-Package Costura.Fody

Насправді, є ще одне - із вбудованим проектом чи файлами, що додаються як посилання, ви також можете активно налагоджувати код до кінця через файл помічника ...
Bartosz,

1
@Bartosz Я думаю, ви все ще можете налагоджувати "до кінця" без "файлу помічника", якщо у вас є правильний файл pdb.
Зак

Я спробував річ Costura і мені це дуже подобається!
Бартош

2

Чи корисніше DLL, чи ні, залежить від кількох факторів:

  1. Розмір коду (при складанні).
  2. Скільки екзеїв це використовують.
  3. Як часто ви маєте намір оновити код.
  4. Незалежно від того, чи потрібно, щоб сім'ї утримувались разом чи існували цілком окремо.

Мета спільної бібліотеки - взяти код, який є загальним для кількох виконуваних файлів, та централізувати його, щоб усі виконувані файли мали спільну копію. Це призначено для економії місця та полегшення оновлення коду.

Якщо кількість коду у вашому допоміжному класі дуже мала, можливо, не варто перенести його на dll, оскільки накладні витрати коду, що знаходиться у dll, можуть протидіяти перевазі економії місця від централізації.

Крім того, якщо ви робите лише кілька виконуваних файлів, розмір коду в кожному виконуваному файлі може бути досить малим, щоб не виникнути проблеми. Однак чим більше виконуваних файлів ви використовуєте один і той же код, тим вигідніше було б переміщення коду в dll.

Як спрощений приклад, скажімо, що ваш клас помічників збирається до 128 байт у файлі EXE, але при переміщенні в dll dll становить 512 байт. Якщо у вас є лише три виконувані файли, ви б економили місце, включивши код у виконувані файли. Однак якби у вас було 5 виконуваних файлів, ви б тоді опинилися в точці, коли вам краще мати dll, оскільки об'єднаний простір, який займає 5 копій коду (5 * 128 = 640 байт), більше, ніж займаний простір маючи код у dll (512 байт).

Скажімо, наприклад, що ви знайдете помилку у своєму помічницькому коді. Якщо ви зібрали всі свої виконувані файли з запеченим кодом, вам доведеться перекомпілювати кожен виконаний файл і потім перерозподілити перекомпільовані версії. Якщо ви компілювали код у dll, вам доведеться лише перекомпілювати та перерозподілити один dll, і помилка автоматично виправляється для всіх виконуваних файлів, що використовують його.

Нарешті, для програми пошуку dll вона повинна знати, де шукати dll. Якщо ви зберігаєте всі свої виконувані файли разом, ви можете просто поставити dll в один і той же каталог, і всі вони знайдуть його відразу. Якщо ви навмисно тримаєте їх відокремленими, стає важче координувати їх для використання одного і того ж dll.


1

Третій варіант є найбільш підходящим (додайте його до окремого проекту «бібліотека класів» до рішення). Це поєднує в собі переваги всіх підходів:

  • Ваш "проект-помічник" завжди в курсі всіх різних проектів.
  • Ви можете посилатися на код проекту, коли хочете швидко побачити зміни.
  • Ви можете створювати його для правильної версії .NET кожного разу.
  • Ви можете вбудувати DLL в exe в будь-якому випадку, тому не хвилюйтеся, що ви можете просто мати це як частину вашої збірки.

Ми робимо це постійно, і я нічого не можу, окрім як рекомендую такий підхід.

Ще одна четверта альтернатива, яку ви не згадували, - це розмістити її у приватному сховищі NuGet, що дозволить вам правильно її версію та посилатись на неї без зайвого проекту у кожному рішенні.


2
Гм, мені здається, що коли я додаю його як проект до рішення, а потім посилаюсь на цей проект в інших проектах, він все одно створюється як окремий .dll, а не вбудовується ... Чи є щось, що я повинен вказати?
Бартош

1

Як розробник, я завжди люблю включати в свою програму посилання на рішення утиліти, оскільки це дозволяє мені налагоджувати код (і виявляти можливі помилки в Утиліті!), А також будь-які зміни, внесені до утиліти, автоматично включаються в додаток.

Отже, насправді рішення залежить від того, наскільки зріла Утиліта ! Якщо ви не впевнені в помилках утиліти, тоді вам слід завжди включати .cs-файл цієї утиліти, щоб дізнатися про помилки. Але якщо ви впевнені, що утиліта досить зріла, і вона не буде повертати результат з будь-якими помилками і там немає можливості для вдосконалення утиліти, ви можете продовжити і включити файл DLL.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.