Clase System.Runtime.Versioning.ComponentGuaranteesAttribute
En este artículo se proporcionan comentarios adicionales a la documentación de referencia de esta API.
ComponentGuaranteesAttribute Lo usan los desarrolladores de componentes y bibliotecas de clases para indicar el nivel de compatibilidad que los consumidores de sus bibliotecas pueden esperar en varias versiones. Indica el nivel de garantía de que una versión futura de la biblioteca o componente no interrumpirá un cliente existente. Después, los clientes pueden usar ComponentGuaranteesAttribute como ayuda para diseñar sus propias interfaces para garantizar la estabilidad entre versiones.
Nota:
Common Language Runtime (CLR) no usa este atributo de ninguna manera. Su valor radica en documentar formalmente la intención del autor del componente. Las herramientas en tiempo de compilación también pueden usar estas declaraciones para detectar errores en tiempo de compilación que interrumpirían la garantía declarada.
Niveles de compatibilidad
ComponentGuaranteesAttribute admite los siguientes niveles de compatibilidad, que se representan mediante miembros de la ComponentGuaranteesOptions enumeración:
No hay compatibilidad de versión a versión (ComponentGuaranteesOptions.None). El cliente puede esperar que las versiones futuras interrumpan el cliente existente. Para obtener más información, consulte la sección Sin compatibilidad más adelante en este artículo.
Compatibilidad de versión a versión en paralelo (ComponentGuaranteesOptions.SideBySide). El componente se ha probado para funcionar cuando se carga más de una versión del ensamblado en el mismo dominio de aplicación. En general, las versiones futuras pueden interrumpir la compatibilidad. Sin embargo, cuando se realizan cambios importantes, la versión anterior no se modifica, pero existe junto con la nueva versión. La ejecución en paralelo es la forma esperada de hacer que los clientes existentes funcionen cuando se realizan cambios importantes. Para obtener más información, consulte la sección Compatibilidad en paralelo más adelante en este artículo.
Compatibilidad estable de versión a versión (ComponentGuaranteesOptions.Stable). Las versiones futuras no deben interrumpir el cliente y no debe ser necesaria la ejecución en paralelo. Sin embargo, si el cliente se interrumpe accidentalmente, es posible usar la ejecución en paralelo para corregir el problema. Para obtener más información, consulte la sección Compatibilidad estable.
Compatibilidad de versiones a versión de Exchange (ComponentGuaranteesOptions.Exchange). Se tiene especial cuidado para asegurarse de que las versiones futuras no interrumpirán el cliente. El cliente solo debe usar estos tipos en la firma de interfaces que se usan para la comunicación con otros ensamblados que se implementan independientemente entre sí. Solo se espera que una versión de estos tipos esté en un dominio de aplicación determinado, lo que significa que si un cliente se interrumpe, la ejecución en paralelo no puede corregir el problema de compatibilidad. Para obtener más información, consulte la sección Compatibilidad de tipos de Exchange.
En las secciones siguientes se describe cada nivel de garantía con mayor detalle.
Sin compatibilidad
Marcar un componente como ComponentGuaranteesOptions.None indica que el proveedor no garantiza la compatibilidad. Los clientes deben evitar tomar dependencias en las interfaces expuestas. Este nivel de compatibilidad es útil para los tipos que son experimentales o que se exponen públicamente, pero están diseñados solo para componentes que siempre se actualizan al mismo tiempo. None indica explícitamente que los componentes externos no deben usar este componente.
Compatibilidad en paralelo
Marcar un componente como ComponentGuaranteesOptions.SideBySide indica que el componente se ha probado para funcionar cuando se carga más de una versión del ensamblado en el mismo dominio de aplicación. Los cambios importantes se permiten siempre y cuando se realicen en el ensamblado que tenga el número de versión mayor. Se espera que los componentes enlazados a una versión anterior del ensamblado sigan enlazando a la versión anterior y otros componentes pueden enlazar a la nueva versión. También es posible actualizar un componente declarado para que SideBySide sea modificando de forma destructiva la versión anterior.
Compatibilidad estable
Marcar un tipo como ComponentGuaranteesOptions.Stable indica que el tipo debe permanecer estable entre versiones. Sin embargo, también puede ser posible que existan versiones en paralelo de un tipo estable en el mismo dominio de aplicación.
Los tipos estables mantienen una barra de compatibilidad binaria alta. Por este motivo, los proveedores deben evitar realizar cambios importantes en tipos estables. Los siguientes tipos de cambios son aceptables:
- Agregar campos de instancia privada a, o quitar campos de, un tipo, siempre y cuando esto no interrumpa el formato de serialización.
- Cambiar un tipo no serializable a un tipo serializable. (Sin embargo, un tipo serializable no se puede cambiar a un tipo no serializable).
- Iniciar excepciones nuevas y derivadas de un método.
- Mejora del rendimiento de un método.
- Cambiar el intervalo de valores devueltos, siempre y cuando el cambio no afecte negativamente a la mayoría de los clientes.
- Corregir errores graves, si la justificación comercial es alta y el número de clientes afectados negativamente es bajo.
Dado que no se espera que las nuevas versiones de componentes estables interrumpan los clientes existentes, normalmente solo se necesita una versión de un componente estable en un dominio de aplicación. Sin embargo, esto no es un requisito, ya que los tipos estables no se usan como tipos de intercambio conocidos que todos los componentes coinciden. Por lo tanto, si una nueva versión de un componente estable interrumpe accidentalmente algún componente y, si otros componentes necesitan la nueva versión, puede ser posible corregir el problema cargando el componente antiguo y nuevo.
Stable proporciona una garantía de compatibilidad de versiones más sólida que None. Es un valor predeterminado común para los componentes de varias versiones.
Stable se puede combinar con SideBySide, que indica que el componente no interrumpirá la compatibilidad, pero se prueba para funcionar cuando se carga más de una versión en un dominio de aplicación determinado.
Después de marcar un tipo o método como Stable, se puede actualizar a Exchange. Sin embargo, no se puede degradar a None.
Compatibilidad de tipos de Exchange
Marcar un tipo como ComponentGuaranteesOptions.Exchange proporciona una garantía de compatibilidad de versiones más sólida que Stable, y se debe aplicar al más estable de todos los tipos. Estos tipos están diseñados para usarse para el intercambio entre componentes creados de forma independiente en todos los límites de componentes en ambos momentos (cualquier versión de CLR o cualquier versión de un componente o aplicación) y espacio (entre procesos, cross-CLR en un proceso, dominio entre aplicaciones en un CLR). Si se realiza un cambio importante en un tipo de intercambio, es imposible corregir el problema cargando varias versiones del tipo.
Los tipos de Exchange solo deben cambiarse cuando un problema es muy grave (por ejemplo, un problema de seguridad grave) o la probabilidad de interrupción es muy baja (es decir, si el comportamiento ya se interrumpió de forma aleatoria en que el código no podía haber tomado una dependencia). Puede realizar los siguientes tipos de cambios en un tipo de intercambio:
Agregue la herencia de nuevas definiciones de interfaz.
Agregue nuevos métodos privados que implementen los métodos de las definiciones de interfaz recién heredadas.
Agregue nuevos campos estáticos.
Agregue nuevos métodos estáticos.
Agregue nuevos métodos de instancia que no son virtuales.
A continuación se consideran cambios importantes y no se permiten para tipos primitivos:
Cambiar los formatos de serialización. Se requiere la serialización tolerante a versiones.
Agregar o quitar campos de instancia privada. Esto corre el riesgo de cambiar el formato de serialización del tipo y el código de cliente importante que usa la reflexión.
Cambiar la serialización de un tipo. Un tipo no serializable puede no ser serializable y viceversa.
Iniciar excepciones diferentes a partir de un método .
Cambiar el intervalo de valores devueltos de un método, a menos que la definición de miembro genere esta posibilidad e indique claramente cómo los clientes deben controlar valores desconocidos.
Corregir la mayoría de los errores. Los consumidores del tipo se basarán en el comportamiento existente.
Después de marcar un componente, un tipo o un miembro con la Exchange garantía, no se puede cambiar a Stable ni Nonea .
Normalmente, los tipos de intercambio son los tipos básicos (como Int32 y String en .NET) e interfaces (como IList<T>, IEnumerable<T>y IComparable<T>) que se usan normalmente en interfaces públicas.
Los tipos de Exchange pueden exponer públicamente solo otros tipos que también están marcados con Exchange compatibilidad. Además, los tipos de intercambio no pueden depender del comportamiento de las API de Windows que son propensas a cambiar.
Garantías de componentes
En la tabla siguiente se indica cómo afectan las características y el uso de un componente a su garantía de compatibilidad.
Características de componentes | Exchange | Stable | En paralelo | None |
---|---|---|---|---|
Se puede usar en interfaces entre los componentes que versiones son independientes. | Y | N | N | N |
Un ensamblado que se puede usar (de forma privada) puede usarse de forma independiente. | Y | Y | Y | No |
Puede tener varias versiones en un solo dominio de aplicación. | N | Y | Y | Y |
Puede realizar cambios importantes | N | N | Y | Y |
Se ha probado para que se puedan cargar varias versiones del ensamblado juntas. | N | N | Y | No |
Puede realizar cambios importantes en su lugar. | N | N | N | Y |
Puede realizar cambios de mantenimiento muy seguros y no importantes en su lugar. | Y | Y | Y | Y |
Aplicación del atributo
Puede aplicar a ComponentGuaranteesAttribute un ensamblado, un tipo o un miembro de tipo. Su aplicación es jerárquica. Es decir, de forma predeterminada, la garantía definida por la Guarantees propiedad del atributo en el nivel de ensamblado define la garantía de todos los tipos del ensamblado y de todos los miembros de esos tipos. De forma similar, si la garantía se aplica al tipo, de forma predeterminada también se aplica a cada miembro del tipo.
Esta garantía heredada se puede invalidar aplicando a ComponentGuaranteesAttribute tipos individuales y miembros de tipo. Sin embargo, garantiza que invalidar el valor predeterminado solo puede debilitar la garantía; no pueden fortalecerlo. Por ejemplo, si un ensamblado está marcado con la None garantía, sus tipos y miembros no tienen ninguna garantía de compatibilidad, y se omite cualquier otra garantía que se aplique a los tipos o miembros del ensamblado.
Prueba de la garantía
La Guarantees propiedad devuelve un miembro de la ComponentGuaranteesOptions enumeración, que está marcado con el FlagsAttribute atributo . Esto significa que debe probar la marca que le interesa enmascarando las marcas potencialmente desconocidas. Por ejemplo, en el ejemplo siguiente se comprueba si un tipo está marcado como Stable.
// Test whether guarantee is Stable.
if ((guarantee & ComponentGuaranteesOptions.Stable) == ComponentGuaranteesOptions.Stable)
Console.WriteLine("{0} is marked as {1}.", typ.Name, guarantee);
' Test whether guarantee is Stable.
If (guarantee And ComponentGuaranteesOptions.Stable) = ComponentGuaranteesOptions.Stable Then
Console.WriteLine("{0} is marked as {1}.", typ.Name, guarantee)
End If
En el ejemplo siguiente se comprueba si un tipo está marcado como Stable o Exchange.
// Test whether guarantee is Stable or Exchange.
if ((guarantee & (ComponentGuaranteesOptions.Stable | ComponentGuaranteesOptions.Exchange)) > 0)
Console.WriteLine("{0} is marked as Stable or Exchange.", typ.Name, guarantee);
' Test whether guarantee is Stable or Exchange.
If (guarantee And (ComponentGuaranteesOptions.Stable Or ComponentGuaranteesOptions.Exchange)) > 0 Then
Console.WriteLine("{0} is marked as Stable or Exchange.", typ.Name, guarantee)
End If
En el ejemplo siguiente se prueba con un tipo marcado como None (es decir, ni StableExchange).
// Test whether there is no guarantee (neither Stable nor Exchange).
if ((guarantee & (ComponentGuaranteesOptions.Stable | ComponentGuaranteesOptions.Exchange)) == 0)
Console.WriteLine("{0} has no compatibility guarantee.", typ.Name, guarantee);
' Test whether there is no guarantee (neither Stable nor Exchange).
If (guarantee And (ComponentGuaranteesOptions.Stable Or ComponentGuaranteesOptions.Exchange)) = 0 Then
Console.WriteLine("{0} has no compatibility guarantee.", typ.Name, guarantee)
End If