2011-01-22 12 views
9

Supongamos que tenemos el class X en la versión 1 del conjunto de A.dll:C# interfaz de rotura, ABI

class X { 
    SomeType Property { set; get; } 
} 

y luego en la versión 2 del conjunto de A.dll:

class X { 
    SomeType Property { set; get; } 
    SomeType OtherProperty { set; get; } 
} 

Ahora supongamos que tenemos una segundo conjunto B.dll que carga A.dll y utiliza X. ¿La adición de la propiedad OtherProperty rompe el ABI? ¿No se usará B.dllA.dll/X? De no ser así, ¿el orden de las declaraciones haría alguna diferencia? Si las propiedades hubieran sido virtuales, ¿había hecho alguna diferencia?

Supongo que realmente estoy preguntando: ¿cuáles son las reglas generales de ABI? Sé que cambiar las interfaces después de que se han publicado es algo malo, pero realmente me gustaría poder agregar propiedades en algunas instancias, sin agregar subclases.

+1

Ver: una guía definitiva sobre los cambios de API en .NET http: // stackoverflow.com/questions/1456785/a-definite-guide-to-api-breaking-changes-in-net – Ani

+0

¿Cómo está cargando los archivos DLL? –

+0

@Mark: tengo clientes de terceros que hacen referencia a algunos de mis ensamblajes. Tengo un par de clases que quiero extender con algunas propiedades. Quiero hacerlo sin requerir que los terceros recompilen sus asambleas. Podría preguntarles amablemente, pero preferiría no hacerlo. Simplemente agrega más tiempo de respuesta ... –

Respuesta

6

Agregar propiedades debería estar bien.

Un caso que se romperá es si, por ejemplo, agrega algo al medio de una enumeración numerada automáticamente. Por ejemplo, si usted tiene este código en su biblioteca:

enum Foo 
{ 
    Bar, 
    Qux 
} 

y lo cambia a esto:

enum Foo 
{ 
    Bar, 
    Baz, 
    Qux 
} 

entonces también tendrá que volver a compilar cualquier código como este:

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

Supongamos que tengo un método que devuelve una clase concreta X. ¿Rompería el ABI si devolviera una interfaz rediseñada IX? Supongo que sí, porque IX no estaba presente en la primera versión del ensamblaje. –

+0

@ Jörgen Sigvardsson: Es * debería * estar bien en la mayoría de las situaciones, pero hay casos en las esquinas donde podría no funcionar. Por ejemplo, si están utilizando la reflexión para inspeccionar la clase, entonces podrán ver cualquier cambio en la ABI y, en teoría, podría romper su código. –

+0

@MarkByers ¿Puede proporcionar alguna referencia de su respuesta anterior? – erick2red

2

No romperá la compatibilidad si solo lo usa el ensamblaje B. Pero se romperá si el ensamblado B define una clase que implementa la interfaz, porque esa clase no implementa la propiedad recién introducida.

10

El compilador JIT espaciará una gran cantidad de esto, también la fuente del mensaje de error si el cambio se estaba rompiendo.

Sin embargo, estás jugando a un juego muy peligroso llamado DLL Hell. El problema no es que no recompilen su código, sino cuando hacen. Lo harán, eventualmente. Si luego hay un error sutil, alguien ejecutó una versión anterior de su instalador, copió el archivo incorrecto, etcétera, entonces todo el infierno se desata. El código no se ejecutará y tendrán un trabajo imposible averiguar por qué. Esto sucederá mucho después de que hayas realizado el cambio, no tendrás manera de adivinar qué salió mal y no podrás evitarlo.

No juegue con esto, aumente [AssemblyFileVersion] y [AssemblyVersion]. Sí, tendrán que volver a compilar cuando cambies el último. O use <bindingRedirect>, que también está bien, ahora hay un registro rastreable de él.

Btw: esto sucedió también en .NET Framework. WaitHandle.WaitOne (int) se agregó en un service pack pero sin un cambio [AssemblyVersion]. Los programadores apuntaban a .NET 2.0, pero su código no se ejecutaba cuando la máquina de destino tenía instalado el 2.0 original. Muy doloroso.