Обрыв интерфейса C#, ABI
Предположим, у нас есть class X
в версии 1 сборки A.dll
:
class X {
SomeType Property { set; get; }
}
а потом в версии 2 сборки A.dll
:
class X {
SomeType Property { set; get; }
SomeType OtherProperty { set; get; }
}
Теперь предположим, что у нас есть вторая сборка B.dll
что загружает A.dll
и использует X. Будет ли добавление свойства OtherProperty
сломать ABI? Будет B.dll
не использовать A.dll
/X
? Если нет, будет ли порядок объявлений иметь какое-либо значение? Если свойства были виртуальными, имело ли это какое-то значение?
Наверное, я действительно спрашиваю: каковы общие правила ABI? Я знаю, что изменение интерфейсов после их публикации - это плохо, но я действительно хотел бы иметь возможность добавлять свойства в некоторых случаях без добавления подклассов.
3 ответа
Добавление свойств должно быть в порядке.
Один случай, который сломается, если вы, например, добавите что-то в середину автоматически нумерованного перечисления. Например, если у вас есть этот код в вашей библиотеке:
enum Foo
{
Bar,
Qux
}
и вы меняете это на это:
enum Foo
{
Bar,
Baz,
Qux
}
Затем вам также нужно будет перекомпилировать любой код, подобный этому:
if (foo == Foo.Qux)
{
// ...
}
JIT-компилятор разберется во многом с этим, а также с источником сообщения об ошибке, если изменение было нарушено.
Однако вы играете в очень опасную игру под названием DLL Hell. Проблема не в том, что они не перекомпилируют свой код, а в том, когда они это делают. Они будут, в конце концов. Если в этом есть небольшая ошибка, кто-то запустил старую версию вашего установщика, скопировал неверный файл и т. Д., И тогда весь ад провалился. Код не будет работать, и у них будет невозможная работа, выясняя почему. Это произойдет еще долго после того, как вы внесли изменения, у вас не будет возможности угадать, что пошло не так, и вы не сможете им помочь.
Не связывайтесь с этим, поднимите [AssemblyFileVersion] и [AssemblyVersion]. Да, им придется перекомпилировать, когда вы измените последний. Или использовать <bindingRedirect>
, что тоже хорошо, теперь есть прослеживаемая запись об этом.
Кстати, это произошло и в.NET Framework. WaitHandle.WaitOne(int) был добавлен в пакет обновления, но без изменения [AssemblyVersion]. Программисты ориентировались на.NET 2.0, но их код не запускался, когда на целевой машине была установлена оригинальная версия 2.0. Очень больно
Это не нарушит совместимость, если используется сборкой B
, Но это сломается, если сборка B
определяет класс, который реализует интерфейс, потому что этот класс не реализует недавно введенное свойство.