Re[5]: есть
От: Quebecois Канада https://www.canada.ca/
Дата: 26.11.22 19:22
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

S>Ограничения, при которых можно безопасно использовать из сборки A сборку B после внесения в метаданные B изменений без перекомпиляции A, перечислить довольно сложно.

S>И изменение сигнатуры конструктора в них явно не входит.
S>Именно отсюда правило большого пальца: всегда перекомпилируем проект при изменении в любой из зависимостей.
По-моему, мы о разных вещах говорим. .Net позволяет UserAssembly инстанциировать класс из ChildAssembly, унаследованный от ParentAssembly, без ссылки UserAssembly->ParentAssembly.

S>Вот в вашем примере совершенно не нужно привлекать какую-то ParentAssembly.

S>Достаточно просто иметь ChildAssembly с классом ChildClass, отнаследованным напрямую от object.
S>Теперь мы заменяем сигнатуру конструктора в ChildClass c ChildClass(int x) на ChildClass(string x).
S>Совершенно неважно, сгенерирован ли этот конструктор автоматически языком или вручную пользователем. Результат будет одинаковым — MethodNotFound.
Точно о разных вещах. ParentAssembly позволяет получить такую диаграмму зависимостей (references из метаданных):

UserAssembly -> ChildAssembly
ChildAssembly -> ParentAssembly

Еще раз, прямой ссылки из UserAssembly на ParentAssembly нет, но это не мешает создавать класс, пронаследованный оттуда через ChildAssembly.

Реалистичный пример: ParentAssembly — внутренняя сборка продукта с внутренним функционалом. ChildAssembly — сборка с интерфейсами для плагинов. UserAssembly — плагин, не имеющий понятия о ParentAssembly.
Если разработчик продукта не хочет ломать обратную совместимость с UserAssembly, ему достаточно придерживаться простого правила: не менять/удалять ничего из ChildAssembly. Добавлять новые классы и интерфейсы — да. Менять/удалять — нет. Это легко соблюдать и легко проверять в процессе ревью. При этом, код внутри приватной ParentAssembly можно кромсать, как хочется — плагины на нее не ссылаются и изменения их не затронут.

Если мы добавляем сюда наследование конструкторов — получается, что поменяв конструктор в приватной ParentAssembly, мы неявно поменяли публичный интерфейс ChildAssembly, и сломали плагин. Ревью это не отловит, потому что исходники ChildAssembly мы не меняли.

На практике, ссылки из interface assemblies в private — это кривой паттерн, но текущая семантика его не ломает, а добавление наследования конструкторов — сломает. Или, выражаясь в Ваших терминах — это сделает нерекурсивное правило большого пальца рекурсивным.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.