Как Microsoft создала сборки, имеющие круговые ссылки?
В .NET BCL есть круглые ссылки между:
-
System.dll
и System.Xml.dll
-
System.dll
и System.Configuration.dll
-
System.Xml.dll
и System.Configuration.dll
Вот скриншот из .NET Reflector, который показывает, что я имею в виду:
![enter image description here]()
Как Microsoft создала эти сборки, для меня загадка. Требуется ли для этого специальный процесс компиляции? Я предполагаю, что здесь происходит что-то интересное.
Ответы
Ответ 1
Я могу только сказать, как это делает Mono Project. Теорема довольно проста, хотя и дает кодовый беспорядок.
Сначала они компилируют System.Configuration.dll без части, требующей ссылки на System.Xml.dll. После этого они компилируют System.Xml.dll обычным способом. Теперь приходит волшебство. Они перекомпилируют System.configuration.dll с частью, требующей ссылки на System.Xml.dll. Теперь есть успешная компиляция с круговой ссылкой.
Короче:
- А скомпилирован без кода
необходимо B и ссылку на B.
- B скомпилирован.
- A перекомпилируется.
Ответ 2
RBarryYoung и Dykam находятся на чем-то. Microsoft использует внутренний инструмент, который использует ILDASM для демонтажа сборок, разбивает все внутренние/частные вещи и тела методов и снова переписывает IL (используя ILASM) в так называемую сборку "обезвоженные сборки" или метаданные. Это делается каждый раз, когда изменяется общий интерфейс сборки.
Во время сборки вместо обычных используются метаданные. Таким образом, цикл нарушается.
Ответ 3
Это можно сделать так, как описал Dykam, но Visual Studio блокирует вас от этого.
Вам нужно будет напрямую использовать компилятор командной строки csc.exe.
-
csc/target: library ClassA.cs
-
csc/target: library ClassB.cs/reference:ClassA.dll
-
csc/target: library 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 {
}
}
Ответ 4
Его довольно легко сделать в Visual Studio, если вы не используете ссылки на проект... Попробуйте следующее:
- Открыть визуальную студию
- Создайте проекты библиотеки классов "ClassLibrary1" и "ClassLibrary2".
- Построить
- В ClassLibrary1 добавьте ссылку на ClassLibrary2, просмотрев DLL, созданную на шаге 3.
- В ClassLibrary2 добавьте ссылку на ClassLibrary1, просмотрев DLL, созданную на шаге 3.
- Сборка еще раз (обратите внимание: если вы вносите изменения в оба проекта, вам нужно будет построить дважды, чтобы обе ссылки были "свежими" ).
Так вот как вы это делаете. Но серьезно... Разве вы никогда не делаете это в реальном проекте! Если вы это сделаете, Санта не принесет вам подарков в этом году.
Ответ 5
Я думаю, это можно сделать, начав с ациклического набора сборок и используя ILMerge, чтобы затем объединить меньшие сборки в логически связанные группы.
Ответ 6
Ну, я никогда не делал этого в Windows, но я сделал это на многих средах компиляции-ссылок-rtl, которые служили в качестве практических предшественников. То, что вы делаете, сначала делает заглушки "цели" без перекрестных ссылок, затем ссылки, затем добавляет циклические ссылки, а затем повторно соединяет. Обычно линкеры не заботятся о циклических ссылках или последующих цепях ref, они только заботятся о возможности разрешить каждую ссылку на нее.
Итак, если у вас есть две библиотеки, A и B, которые должны ссылаться друг на друга, попробуйте что-то вроде этого:
- Ссылка A без ссылок на B.
- Ссылка B с ссылками на A.
- Ссылка A, добавление ссылок на B.
Dykam делает хорошую точку, он компилируется, а не связан в .Net, но принцип остается тем же: сделайте свои источники с перекрестными ссылками с их экспортированными точками входа, но при этом все, кроме одного, имеют свои собственные ссылки на другие прорезали. Постройте их так. Затем развяжите внешние ссылки и перестройте их. Это должно работать даже без каких-либо специальных инструментов. Фактически, этот подход работал на каждой операционной системе, которую я когда-либо пробовал (около 6 из них). Хотя, очевидно, что-то, что автоматизирует его, будет большой помощью.
Ответ 7
Одним из возможных подходов является использование условной компиляции (#if) для первой компиляции System.dll, которая не зависит от этих других сборок, затем компилирует другие сборки и, наконец, перекомпилирует System.dll для включения частей в зависимости от на Xml и Configuration.
Ответ 8
Технически, возможно, что они не были составлены вообще и собраны вручную. В конце концов, это библиотеки низкого уровня.