Поделиться через


System.Runtime.Versioning.ComponentGuaranteesAttribute class

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

ComponentGuaranteesAttribute используется разработчиками компонентов и библиотек классов, чтобы указать уровень совместимости, который потребители своих библиотек могут ожидать в нескольких версиях. Он указывает уровень гарантии того, что будущая версия библиотеки или компонента не прерывает существующий клиент. Затем клиенты могут использовать ComponentGuaranteesAttribute в качестве помощи в разработке собственных интерфейсов для обеспечения стабильности между версиями.

Примечание.

Общая языковая среда выполнения (CLR) никак не использует этот атрибут. Его значение заключается в формальном документировании намерений автора компонента. Средства на этапе компиляции также могут использовать эти объявления для обнаружения ошибок, которые в противном случае нарушают объявленную гарантию.

Уровни совместимости

The ComponentGuaranteesAttribute supports the following levels of compatibility, which are represented by members of the ComponentGuaranteesOptions enumeration:

  • Нет совместимости версий (ComponentGuaranteesOptions.None). Клиент может ожидать, что будущие версии нарушат работу существующего клиента. Дополнительные сведения см. в разделе Отсутствие совместимости далее в этой статье.

  • Совместимость версий, работающих параллельно (ComponentGuaranteesOptions.SideBySide). Компонент протестирован для работы, если в одном домене приложения загружается несколько версий сборки. Как правило, будущие версии могут нарушить совместимость. Однако при внесении критических изменений старая версия не изменяется, но существует вместе с новой версией. Side-by-side execution is the expected way to make existing clients work when breaking changes are made. Для получения дополнительной информации см. раздел о параллельной совместимости, который находится далее в этой статье.

  • Стабильная совместимость между версиями (ComponentGuaranteesOptions.Stable). Future versions should not break the client, and side-by-side execution should not be needed. Однако если клиент непреднамеренно разбит, возможно, можно использовать параллельное выполнение для устранения проблемы. Дополнительные сведения см. в разделе стабильной совместимости .

  • Совместимость между версиями Exchange (ComponentGuaranteesOptions.Exchange). Extraordinary care is taken to ensure that future versions will not break the client. Клиент должен использовать только эти типы в сигнатуре интерфейсов, которые используются для взаимодействия с другими сборками, развернутыми независимо друг от друга. Ожидается, что только одна версия этих типов находится в определенном домене приложения, что означает, что если клиент прерывает работу, параллельное выполнение не может устранить проблему совместимости. Дополнительные сведения см. в разделе о совместимости типов Exchange .

В следующих разделах подробно рассматриваются все уровни гарантии.

Без совместимости

Маркировка компонента как ComponentGuaranteesOptions.None указывает, что поставщик не гарантирует совместимость. Клиенты должны избегать принятия зависимостей от предоставляемых интерфейсов. Этот уровень совместимости полезен для типов, которые являются экспериментальными или общедоступными, но предназначены только для компонентов, которые всегда обновляются одновременно. None явно указывает, что этот компонент не должен использоваться внешними компонентами.

Одновременная совместимость

Пометка компонента как ComponentGuaranteesOptions.SideBySide указывает, что компонент протестирован для работы при загрузке нескольких версий сборки в тот же домен приложения. Breaking changes are allowed as long as they are made to the assembly that has the greater version number. Компоненты, привязанные к старой версии сборки, должны продолжать привязываться к старой версии, а другие компоненты могут привязаться к новой версии. Кроме того, можно обновить компонент, объявленный как SideBySide путем разрушительного изменения старой версии.

Стабильная совместимость

Пометка типа как ComponentGuaranteesOptions.Stable указывает, что тип должен оставаться стабильным в разных версиях. Однако можно также использовать параллельные версии стабильного типа, которые будут существовать в том же домене приложения.

Стабильные типы поддерживают высокий двоичный индикатор совместимости. Because of this, providers should avoid making breaking changes to stable types. Допустимы следующие типы изменений:

  • Adding private instance fields to, or removing fields from, a type, as long as this does not break the serialization format.
  • Изменение несериализируемого типа на сериализуемый тип. (Однако сериализуемый тип нельзя изменить на несериализируемый тип.)
  • Создание новых, более производных исключений из метода.
  • Повышение производительности метода.
  • Changing the range of return values, as long as the change does not adversely affect the majority of clients.
  • Исправление серьезных ошибок, если бизнес-обоснование является высоким, а количество пострадавших клиентов низко.

Так как новые версии стабильных компонентов не должны прерывать существующие клиенты, обычно в домене приложения требуется только одна версия стабильного компонента. Однако это не является обязательным требованием, так как стабильные типы не используются как известные типы обмена, на которые согласуются все компоненты. Таким образом, если новая версия стабильного компонента непреднамеренно прерывает некоторый компонент, и если другие компоненты нуждаются в новой версии, это может быть возможно, чтобы устранить проблему, загрузив старый и новый компонент.

Stable обеспечивает более надежную гарантию совместимости версий, чем None. Это обычное значение по умолчанию для компонентов с несколькими версиями.

Stable можно сочетать с SideBySide, что указывает, что компонент не прерывает совместимость, но проверяется для работы при загрузке нескольких версий в определенном домене приложения.

После того как тип или метод помечается как Stable, его можно обновить до Exchange. Однако его нельзя уменьшить до None.

Совместимость типов Exchange

Маркировка типа как ComponentGuaranteesOptions.Exchange обеспечивает более надежную гарантию совместимости версий, чем Stable, и следует применять к наиболее стабильной из всех типов. Эти типы предназначены для обмена между независимо построенными компонентами на всех границах компонентов во временном аспекте (любая версия среды CLR или любая версия компонента или приложения) и в пространственном аспекте (кросспроцессный обмен, кросс-CLR в одном процессе, обмен между доменами приложений в одной среде CLR). Если критическое изменение вносится в тип обмена, невозможно устранить проблему, загрузив несколько версий этого типа.

Типы Exchange должны изменяться только в том случае, если проблема очень серьезна (например, серьезная проблема безопасности) или вероятность поломки крайне мала (то есть, если поведение уже было нарушено случайным образом, и на него невозможно было бы положиться в коде). Вы можете внести следующие изменения в тип exchange:

  • Добавьте наследование новых определений интерфейса.

  • Добавьте новые частные методы, реализующие методы недавно унаследованных определений интерфейса.

  • Добавьте новые статические поля.

  • Добавьте новые статические методы.

  • Add new non-virtual instance methods.

The following are considered breaking changes and are not allowed for primitive types:

  • Изменение форматов сериализации. Version-tolerant serialization is required.

  • Adding or removing private instance fields. This risks changing the serialization format of the type and breaking client code that uses reflection.

  • Изменение сериализуемости типа. Несериализуемый тип не может стать сериализуемым, и наоборот.

  • Throwing different exceptions from a method.

  • Changing the range of a method's return values, unless the member definition raises this possibility and clearly indicates how clients should handle unknown values.

  • Исправление большинства ошибок. Потребители типа будут полагаться на существующее поведение.

After a component, type, or member is marked with the Exchange guarantee, it cannot be changed to either Stable or None.

Как правило, типы обмена — это базовые типы (например, Int32 и String в .NET) и интерфейсы (например, IList<T>, IEnumerable<T>и IComparable<T>), которые обычно используются в общедоступных интерфейсах.

Exchange types may publicly expose only other types that are also marked with Exchange compatibility. Кроме того, типы обмена не могут зависеть от поведения API Windows, подверженных изменению.

Гарантии компонентов

В следующей таблице показано, как характеристики и использование компонента влияют на ее гарантию совместимости.

Характеристики компонентов Обмен Стабильный Side-by-Side Нет
Можно использовать в интерфейсах между компонентами, которые обновляются независимо. Y N N N
Can be used (privately) by an assembly that versions independently. Y Y Y N
Может иметь несколько версий в одном домене приложения. N Y Y Y
Может вносить критические изменения N N Y Y
Протестировано, чтобы убедиться, что несколько версий сборки можно загрузить вместе. N N Y N
Can make breaking changes in place. N N N Y
Can make very safe non-breaking servicing changes in place. Y Y Y Y

Применение атрибута

Вы можете применить ComponentGuaranteesAttribute к сборке, типу или члену типа. Его приложение является иерархическим. То есть по умолчанию гарантия, определяемая свойством Guarantees атрибута на уровне сборки, определяет гарантию всех типов в сборке и всех членов этих типов. Аналогичным образом, если гарантия применяется к типу, по умолчанию она также применяется к каждому элементу типа.

This inherited guarantee can be overridden by applying the ComponentGuaranteesAttribute to individual types and type members. However, guarantees that override the default can only weaken the guarantee; they cannot strengthen it. Например, если сборка помечена гарантией None, его типы и члены не имеют гарантии совместимости, а другая гарантия, применяемая к типам или элементам в сборке, игнорируется.

Проверка гарантии

Свойство Guarantees возвращает элемент перечисления ComponentGuaranteesOptions, помеченный атрибутом FlagsAttribute. This means that you should test for the flag that you are interested in by masking away potentially unknown flags. Например, в следующем примере проверяется, помечен ли тип как Stable.

// Test whether guarantee is Stable.
if ((guarantee & ComponentGuaranteesOptions.Stable) == ComponentGuaranteesOptions.Stable)
   Console.WriteLine($"{typ.Name} is marked as {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

В следующем примере проверяется, помечен ли тип как Stable или Exchange.

// Test whether guarantee is Stable or Exchange.
if ((guarantee & (ComponentGuaranteesOptions.Stable | ComponentGuaranteesOptions.Exchange)) > 0)
   Console.WriteLine($"{typ.Name} is marked as Stable or Exchange.");
' 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

The following example tests whether a type is marked as None (that is, neither Stable nor Exchange).

// Test whether there is no guarantee (neither Stable nor Exchange).
if ((guarantee & (ComponentGuaranteesOptions.Stable | ComponentGuaranteesOptions.Exchange)) == 0)
   Console.WriteLine($"{typ.Name} has no compatibility 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