2011-01-22 8 views
9

Предположим, что мы имеем class X в версии 1 сборки A.dll:C# интерфейс поломка, ABI

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? Will B.dll не используется A.dll/X? Если нет, будет ли порядок заявлений иметь какое-либо значение? Если свойства были виртуальными, если бы это имело какое-либо значение?

Наверное, я действительно спрашиваю: каковы общие правила ABI? Я знаю, что изменение интерфейсов после их публикации плохо, но я действительно хотел бы иметь возможность добавлять свойства в некоторых случаях без добавления подклассов.

+1

См.: Определенное руководство по изменению API-интерфейсов в .NET http: // stackoverflow.com/questions/1456785/a-definite-guide-to-api-break-changes-in-net – Ani

+0

Как вы загружаете библиотеки DLL? –

+0

@Mark: У меня есть сторонние клиенты, которые ссылаются на некоторые из моих сборок. У меня есть несколько классов, которые я хочу расширить с помощью нескольких свойств. Я хочу сделать это, не требуя от третьих сторон перекомпилировать свои сборки. Я мог бы попросить их красиво, но я бы предпочел. Он просто добавляет больше времени на поворот ... –

ответ

6

Добавление свойств должно быть прекрасным.

Один случай, который сломается, если вы, например, добавите что-то в середину автоматически пронумерованного перечисления. Например, если у вас есть этот код в вашей библиотеке:

enum Foo 
{ 
    Bar, 
    Qux 
} 

и изменить его к этому:

enum Foo 
{ 
    Bar, 
    Baz, 
    Qux 
} 

Тогда вам также потребуется перекомпилировать любой код вроде этого:

if (foo == Foo.Qux) 
{ 
    // ... 
} 
+0

Предположим, у меня есть метод, который возвращает конкретный класс X. Разве это сломает ABI, если я вернул рефакторизованный интерфейс IX? Я предполагаю, что это произойдет, потому что IX не присутствовал в первой версии сборки. –

+0

@ Jörgen Sigvardsson: В большинстве случаев он должен быть в порядке, но есть угловые случаи, когда это может не сработать. Например, если они используют рефлексию для проверки класса, тогда они смогут увидеть любые изменения в ABI, и теоретически это может нарушить их код. –

+0

@MarkByers Можете ли вы предоставить некоторую ссылку на свой ответ выше? – erick2red

2

Он не нарушит совместимость, если только используется сборкой B. Но он сломается, если сборка B определяет класс, который реализует интерфейс, потому что этот класс не реализует вновь введенное свойство.

10

JIT-компилятор будет распространять много этого, также источник сообщения об ошибке, если изменение было нарушено.

Вы, однако, играете в очень опасную игру под названием DLL Hell. Проблема не в том, что они не перекомпилируют свой код, это когда они делают. В конечном итоге они будут. Если тогда есть тонкая ошибка, кто-то запускал старую версию вашего установщика, скопировал неправильный файл и т. Д., Тогда все ад разрывается. Код не будет запущен, и у них будет невозможно задание выяснить почему. Это произойдет долго после того, как вы внесете изменения, у вас не будет никакого способа догадаться, что пошло не так и не может им помочь.

Не вмешивайтесь в это, натыкайтесь на [AssemblyFileVersion] и [AssemblyVersion]. Да, им придется перекомпилировать, когда вы измените последний. Или используйте <bindingRedirect>, что тоже хорошо, теперь есть прослеживаемая запись.

Btw: это произошло и в .NET Framework. WaitHandle.WaitOne (int) добавлен в пакет обновления, но без изменения [AssemblyVersion]. Программисты ориентировались на .NET 2.0, но их код не запускался, если на целевой машине был установлен исходный 2.0. Очень больно.

Смежные вопросы