Обрыв интерфейса 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 определяет класс, который реализует интерфейс, потому что этот класс не реализует недавно введенное свойство.

Другие вопросы по тегам