Як Microsoft створила збірки, які мають кругові посилання?


107

У .NET BCL є кругові посилання між:

  • System.dll і System.Xml.dll
  • System.dll і System.Configuration.dll
  • System.Xml.dll і System.Configuration.dll

Ось скріншот із .NET Reflector, який показує, що я маю на увазі:

введіть тут опис зображення

Як Microsoft створила ці збірки, для мене загадка. Чи потрібен спеціальний процес компіляції, щоб це дозволити? Я думаю, що тут відбувається щось цікаве.


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

3
чому ті DLL не об'єднуються в одне, якщо вони вимагають один одного? чи є якась практична причина для цього?
Андреас Петерсон

1
Цікаве запитання ... Я хотів би знати відповідь Еріка Ліпперта на цей! І як сказав Андреас, мені цікаво, чому вони не поставили все в одну збірку ...
Томас Левеск

Ну а якщо одна збірка потребує оновлення, вони не потребують торкатися інших. Це єдина причина, яку я бачу. Хоча
цікаве

2
Подивіться на презентації (файли asmmeta): msakademik.net/academicdays2005/Serge_Lidin.ppt
Mehrdad Афшари

Відповіді:


58

Я можу лише сказати, як це робить проект «Моно». Теорема досить проста, хоч і дає кодовий безлад.

Спочатку вони компілюють System.Configuration.dll, без частини, яка потребує посилання на System.Xml.dll. Після цього вони компілюють System.Xml.dll звичайним способом. Тепер настає магія. Вони перекомпілюють System.configuration.dll, при цьому частина потребує посилання на System.Xml.dll. Зараз є вдала компіляція з круговою посиланням.

Коротко:

  • A складається без коду, що потребує B, і посилання на B.
  • Б складено.
  • A перекомпілюється.

1
Він блокується Visual Studio, але це можна зробити безпосередньо за допомогою компілятора командного рядка (csc.exe). Дивіться мою відповідь.
Альфред Майєрс

14
Я знаю. Основна система складання Mono - це не Visual Studio. Вгадайте, мікрософт теж не є.
Дікам

35

RBarryYoung і Dykam знаходяться на чомусь. Корпорація Майкрософт використовує внутрішній інструмент, який використовує ILDASM для розбирання збірок, роздягання всіх внутрішніх / приватних речей та тіл методів та повторної перекомпіляції IL (за допомогою ILASM) у те, що називається «зневоднена збірка» або збірка метаданих. Це робиться щоразу, коли публічний інтерфейс складання змінюється.

Під час збирання використовуються збірки метаданих замість реальних. Таким чином цикл порушений.


1
Цікава відповідь, чи є у вас посилання?
Хенк Холтерман

Я намагаюся знайти зовнішнє посилання на інструмент. Я не думаю, що він публікується за межами Microsoft, але концепція проста: розібрати смужку внутрішніх приміщень-перезбирати.
Srdjan Jovcic

Домовились - цікава відповідь. Деякі посилання, щоб підтвердити це, було б добре.
Дрю Ноакс

Так, це справді так (з особистого досвіду).
Павло Мінаєв

1
Вони не є сильно підписаними до моменту завершення (вони затримані підписані), тому зневоднені збори не підписуються.
Srdjan Jovcic

26

Це можна зробити так, як описав Dykam, але Visual Studio заважає вам це робити.

Вам доведеться використовувати компілятор командного рядка csc.exe безпосередньо.

  1. csc / target: бібліотека ClassA.cs

  2. csc / target: бібліотека ClassB.cs /reference:ClassA.dll

  3. csc / target: бібліотека ClassA.cs ClassC.cs /reference:ClassB.dll


//ClassA.cs
namespace CircularA {
    public class ClassA {
    }
}


//ClassB.cs
using CircularA;
namespace CircularB {
    public class ClassB : ClassA  {
    }
}


//ClassC.cs
namespace CircularA {
    class ClassC : ClassB {
    }
}

Ви можете це зробити і в Visual studio, хоча це занадто суворо, також основний спосіб - використовувати # if і видалити посилання за допомогою програми провідника рішень, повернувши це на третьому кроці. Інший спосіб, про який я думаю, - це третій файл проекту, що включає ті самі файли, але різні посилання. Це буде працювати, оскільки ви можете вказати порядок збирання.
Дікам

Наскільки я знаю, тут не можу протестувати.
Дікам

Я б дуже хотів це бачити. З того, що я тут експериментував, мить, коли ви намагаєтесь додати довідку, IDE зупиняє вас.
Альфред Майєрс

Я знаю. Але третій проект, що не має посилання AND символ #if, і на нього посилається другий, на який посилається перший. Жодного циклу. Але третій використовує код першого і виводить на перше місце складання. збірка легко може бути замінена іншою з тими ж характеристиками. Але я думаю, що зміцнення може спричинити проблеми в цьому методі.
Дікам

Це трохи нагадує відповідь Срджана, хоч і інший метод.
Дікам

18

У Visual Studio це зробити досить просто, доки ви не використовуєте посилання на проекти ... Спробуйте:

  1. Відкрита візуальна студія
  2. Створіть 2 бібліотечні проекти класів "ClassLibrary1" та "ClassLibrary2".
  3. Побудувати
  4. З ClassLibrary1 додайте посилання на ClassLibrary2, перейшовши на dll, створений на кроці 3.
  5. З ClassLibrary2 додайте посилання на ClassLibrary1, перейшовши на dll, створений на кроці 3.
  6. Збірка заново (Примітка: якщо ви внесете зміни в обидва проекти, вам потрібно буде скласти двічі, щоб зробити обидві посилання "свіжими")

Отже, це, як ви це робите. Але серйозно ... Хіба ви НІКОЛИ не зробите це в реальному проекті! Якщо ви це робите, Санта не буде приносити вам подарунків цього року.


1
Єдиний виняток, якщо це буде між 26-31 грудня і подарунки вже забезпечені
Джессі Хафстетлер

6

Я думаю, це можна зробити, починаючи з ациклічного набору збірок і використовуючи ILMerge, щоб потім об'єднати менші збори в логічно пов'язані групи.


4

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

Тож якщо у вас є дві бібліотеки, A і B, на які потрібно посилатися одна на одну, спробуйте щось подібне:

  1. Посилання А без жодних посилань на Б.
  2. Посилання В з відкликами до А.
  3. Посилання А, додаючи у відповідях на Б.

Dykam вказує на те, що це компіляція, а не посилання на .Net, але принцип залишається тим самим. Створіть свої перехресні посилання з експортованими вхідними точками, але з усіма, крім одного з них, які мають свої посилання на інші, затримані з. Побудуйте їх так. Потім розстебніть зовнішні посилання та відновіть їх. Це повинно працювати навіть без будь-яких спеціальних інструментів, насправді цей підхід працював на кожній операційній системі, на якій я коли-небудь пробував (близько 6 з них). Хоча, очевидно, щось, що автоматизує, було б великою допомогою.


теорема правильна. Однак у світі .Net зв'язок робиться динамічним і не є проблемою. Це крок компіляції, де потрібно це рішення.
Дікам

Вибачте, що знову виправили: P Але посилання (посилання) під час компіляції відбувається у світі .Net, який є всім, що виходить із конкретної специфікації ECMA. Таким чином, Mono, dotGnu та .Net. Не сама Windows.
Дікам

1

Один з можливих підходів полягає у використанні умовної компіляції (#if) для сперші компіляції System.dll, яка не залежить від цих інших збірок, потім компіляції інших збірок і, нарешті, перекомпіляції System.dll для включення частин залежно від Xml та Конфігурація.


1
На жаль, це не дозволяє умовно посилатись на збірку (я б хотів, щоб це було можливим, це дійсно допомогло б в одному з моїх проектів ...)
Thomas Levesque

1
Умовні посилання можна легко зробити, відредагувавши файл .csproj. Просто додайте атрибут Condition до елемента <Reference>.
Даніель

0

Технічно можливо, що вони зовсім не були складені, а зібрані вручну. Зрештою, це бібліотеки низького рівня.


Не зовсім. У ній не так багато матеріалів низького рівня, лише базові. Що змусило вас думати, що це буде низький рівень? Час виконання і корліб низький рівень. Відносно. Досі звичайний C або C ++, думав, що JIT містить матеріали низького рівня.
Дікам
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.