Определение пользовательских типов для использования со службами XAML .NETDefine custom types for use with .NET XAML Services

При определении пользовательских типов, которые являются бизнес-объектами или типами, не имеющими зависимости от конкретных платформ, можно следовать определенным рекомендациям по XAML.When you define custom types that are business objects or are types that do not have a dependency on specific frameworks, there are certain best practices for XAML you can follow. При соблюдении этих рекомендаций службы XAML .NET и их средства чтения и записи XAML могут обнаружить характеристики XAML вашего типа и присвоить ему соответствующее представление в потоке узлов XAML, используя систему типов XAML.If you follow these practices, .NET XAML Services and its XAML readers and XAML writers can discover the XAML characteristics of your type and give it appropriate representation in a XAML node stream using the XAML type system. В этом разделе описываются рекомендации по определениям типов, определениям членов и присвоению атрибутов типов или членов в среде CLR.This topic describes best practices for type definitions, member definitions, and CLR attributing of types or members.

Шаблоны конструктора и определения типов для XAMLConstructor Patterns and Type Definitions for XAML

Для создания экземпляра в виде объектного элемента в XAML пользовательский класс должен удовлетворять следующим требованиям.To be instantiated as an object element in XAML, a custom class must meet the following requirements:

  • Пользовательский класс должен быть открытым и должен предоставлять открытый конструктор без параметров.The custom class must be public and must expose a parameterless public constructor. (Примечания о структурах см. в следующем разделе.)(See following section for notes regarding structures.)

  • Пользовательский класс не должен быть вложенным классом.The custom class must not be a nested class. Дополнительный "точка" в пути Full-Name делает деление класса-пространства неоднозначным и влияет на другие функции XAML, такие как вложенные свойства.The extra "dot" in the full-name path makes the class-namespace division ambiguous, and interferes with other XAML features such as attached properties. Если объект может быть создан как объектный элемент, созданный объект может заполнить форму элемента свойства любых свойств, которые принимают объект в качестве базового типа.If an object can be instantiated as an object element, the created object can fill the property element form of any properties that take the object as their underlying type.

При включении преобразователя значений можно по-прежнему предоставлять значения объектов для типов, которые не соответствуют этим критериям.You can still provide object values for types that do not meet these criteria, if you enable a value converter. Дополнительные сведения см. в разделе преобразователи типов и расширения разметки для XAML.For more information, see Type Converters and Markup Extensions for XAML.

СтруктурыStructures

Структуры всегда могут быть построены в XAML, по определению среды CLR.Structures are always able to be constructed in XAML, by CLR definition. Это обусловлено тем, что компилятор CLR неявно создает конструктор без параметров для структуры.This is because a CLR compiler implicitly creates a parameterless constructor for a structure. Этот конструктор инициализирует все значения свойств значениями по умолчанию.This constructor initializes all property values to their defaults.

В некоторых случаях поведение конструирования по умолчанию для структуры не желательно.In some cases, the default construction behavior for a structure is not desirable. Это может быть вызвано тем, что структура предназначена для заполнения значений и концептуально работает как объединение.This might be because the structure is intended to fill values and function conceptually as a union. Как объединение, содержащиеся значения могут иметь взаимоисключающие интерпретации, поэтому ни одно из его свойств не может быть задано.As a union, the contained values might have mutually exclusive interpretations, and therefore, none of its properties are settable. Примером такой структуры в словаре WPF является GridLength .An example of such a structure in the WPF vocabulary is GridLength. Такие структуры должны реализовывать преобразователь типов, чтобы значения можно было выразить в форме атрибутов с помощью строковых соглашений, которые создают различные интерпретации или режимы значений структуры.Such structures should implement a type converter so that the values can be expressed in attribute form, by using string conventions that create the different interpretations or modes of the structure values. Структура должна также предоставлять аналогичное поведение для построения кода с помощью конструктора без параметров.The structure should also expose similar behavior for code construction through a non-parameterless constructor.

ИнтерфейсыInterfaces

Интерфейсы можно использовать в качестве базовых типов элементов.Interfaces can be used as underlying types of members. Система типов XAML проверяет присваиваемый список и ждет, что объект, предоставленный в качестве значения, может быть назначен интерфейсу.The XAML type system checks the assignable list and expects that the object that is provided as the value can be assigned to the interface. Не существует концепции того, как интерфейс должен быть представлен как тип XAML, если соответствующий назначаемый тип поддерживает требования к конструкции XAML.There is no concept of how the interface must be presented as a XAML type as long as a relevant assignable type supports the XAML construction requirements.

Фабричные методыFactory Methods

Заводские методы являются функцией XAML 2009.Factory methods are a XAML 2009 feature. Они изменяют принцип XAML, в котором объекты должны иметь конструкторы без параметров.They modify the XAML principle that objects must have parameterless constructors. В этой статье не описаны заводские методы.Factory methods are not documented in this article. См. раздел Директива x:FactoryMethod.See x:FactoryMethod Directive.

ПеречисленияEnumerations

Перечисления имеют поведение преобразования собственного типа XAML.Enumerations have XAML native type conversion behavior. Имена констант перечисления, указанные в XAML, разрешаются для базового типа перечисления и возвращают значение перечисления в средство записи объектов XAML.Enumeration constant names specified in XAML are resolved against the underlying enumeration type, and return the enumeration value to a XAML object writer.

XAML поддерживает использование флагов для перечислений с FlagsAttribute применением.XAML supports a flags-style usage for enumerations with FlagsAttribute applied. Дополнительные сведения см. в разделе Подробное описание синтаксиса XAML.For more information, see XAML Syntax In Detail. (Подробное описание синтаксиса XAML написано для аудитории WPF, но большая часть информации в этом разделе ОТНОСИТСЯ к XAML, который не относится к конкретной реализующей платформе.)(XAML Syntax In Detail is written for the WPF audience, but most of the information in that topic is relevant for XAML that is not specific to a particular implementing framework.)

Определения элементовMember Definitions

Типы могут определять элементы для использования XAML.Types can define members for XAML usage. Типы могут определять элементы, которые могут использоваться XAML, даже если этот конкретный тип не может использоваться в XAML.It's possible for types to define members that are XAML-usable even if that specific type is not XAML-usable. Это возможно благодаря наследованию CLR.This is possible because of CLR inheritance. До тех пор, пока какой-либо тип, наследующий член, поддерживает использование XAML в качестве типа, а член поддерживает использование XAML для базового типа или имеет доступ к собственному синтаксису XAML, этот член может использоваться в XAML.So long as some type that inherits the member supports XAML usage as a type, and the member supports XAML usage for its underlying type or has a native XAML syntax available, that member is XAML-usable.

Properties (Свойства)Properties

Если вы определяете свойства как общедоступное свойство CLR с помощью get стандартных set шаблонов CLR и методов доступа и ключевых слов, соответствующих языку, система типов XAML может сообщить о свойстве как члену с соответствующей информацией, предоставляемой для XamlMember свойств, таких как IsReadPublic и IsWritePublic .If you define properties as a public CLR property using the typical CLR get and set accessor patterns and language-appropriate keywording, the XAML type system can report the property as a member with appropriate information provided for XamlMember properties, such as IsReadPublic and IsWritePublic.

Определенные свойства могут включать текстовый синтаксис путем применения TypeConverterAttribute .Specific properties can enable a text syntax by applying TypeConverterAttribute. Дополнительные сведения см. в разделе преобразователи типов и расширения разметки для XAML.For more information, see Type Converters and Markup Extensions for XAML.

В отсутствие текстового синтаксиса или преобразования машинного кода XAML, а также при отсутствии дальнейших косвенных обращений, таких как использование расширения разметки, тип свойства ( TargetType в системе типов XAML) должен иметь возможность возвращать экземпляр в средство записи объектов XAML, рассматривая целевой тип как тип CLR.In the absence of a text syntax or native XAML conversion and in the absence of further indirection, such as a markup extension usage, the type of a property (TargetType in the XAML type system) must be able to return an instance to a XAML object writer by treating the target type as a CLR type.

Если используется XAML 2009, расширение разметки x:Reference можно использовать для предоставления значений, если предыдущие рекомендации не выполняются. Однако это является более частью проблемы использования, чем проблемы с определением типа.If using XAML 2009, x:Reference Markup Extension can be used to provide values if the previous considerations are not met; however, that is more of a usage issue than a type definition issue.

СобытияEvents

Если вы определяете события как общедоступное событие CLR, система типов XAML может сообщить о событии как члену с IsEvent именем true .If you define events as a public CLR event, the XAML type system can report the event as a member with IsEvent as true. Связывание обработчиков событий не входит в область возможностей служб XAML .NET. привязка оставлена конкретным платформам и реализациям.Wiring the event handlers is not within the scope of .NET XAML Services capabilities; wiring is left to specific frameworks and implementations.

МетодыMethods

Встроенный код для методов не является возможностью XAML по умолчанию.Inline code for methods is not a default XAML capability. В большинстве случаев не нужно напрямую ссылаться на члены методов из XAML, а роль методов в XAML — предоставить поддержку для конкретных шаблонов XAML.In most cases, you do not directly reference method members from XAML, and the role of methods in XAML is only to provide support for specific XAML patterns. Директива x:FactoryMethod является исключением.x:FactoryMethod Directive is an exception.

ПоляFields

Рекомендации по проектированию среды CLR не допустают нестатических полей.CLR design guidelines discourage nonstatic fields. Для статических полей доступ к значениям статических полей можно получить только с помощью расширения разметки x:Static. в этом случае не выполняется никаких специальных действий в определении CLR для предоставления поля для использования в x:Static .For static fields, you can access static field values only through x:Static Markup Extension; in this case you are not doing anything special in the CLR definition to expose a field for x:Static usages.

Присоединяемые членыAttachable Members

Присоединяемые члены предоставляются XAML через шаблон метода доступа для определяющего типа.Attachable members are exposed to XAML through an accessor method pattern on a defining type. Сам определяющий тип не обязательно должен быть доступен для использования в XAML как объект.The defining type itself does not need to be XAML-usable as an object. На самом деле, распространенным шаблоном является объявление класса службы, роль которого заключается в том, чтобы присоединить присоединяемый член и реализовать соответствующие поведения, но не обслуживает другие функции, такие как представление пользовательского интерфейса.In fact, a common pattern is to declare a service class whose role is to own the attachable member and implement the related behaviors, but serve no other function such as a UI representation. В следующих разделах местозаполнитель PropertyName представляет имя присоединяемого члена.For the following sections, the placeholder PropertyName represents the name of your attachable member. Это имя должно быть допустимым в грамматике имяxaml.That name must be valid in the XamlName Grammar.

Соблюдайте осторожность при конфликтах имен между этими шаблонами и другими методами типа.Be cautious of name collisions between these patterns and other methods of a type. Если существует элемент, совпадающий с одним из шаблонов, он может быть интерпретирован обработчиком XAML как присоединяемый путь использования члена, даже если это не ваша цель.If a member exists that matches one of the patterns, it can be interpreted as an attachable member usage pathway by a XAML processor even if that was not your intention.

Метод доступа ИмяСвойстваThe GetPropertyName Accessor

Сигнатура для GetPropertyName метода доступа должна быть такой:The signature for the GetPropertyName accessor must be:

public static object GetPropertyName(object target)

  • Объект target можно указать как более конкретный тип в реализации.The target object can be specified as a more specific type in your implementation. Его можно использовать для определения области использования присоединяемого члена; использование за пределами предполагаемой области действия приведет к созданию недопустимых исключений приведения, которые затем выводятся в результате ошибки синтаксического анализа XAML.You can use this to scope the usage of your attachable member; usages outside your intended scope will throw invalid cast exceptions that are then surfaced by a XAML parse error. Имя параметра target не является обязательным, но target в большинстве реализаций оно называется по соглашению.The parameter name target is not a requirement, but is named target by convention in most implementations.

  • Возвращаемое значение можно указать как более конкретный тип в реализации.The return value can be specified as a more specific type in your implementation.

Чтобы обеспечить поддержку TypeConverter синтаксиса текста для присоединяемого элемента, примените к нему доступ TypeConverterAttribute GetPropertyName .To support a TypeConverter enabled text syntax for attribute usage of the attachable member, apply TypeConverterAttribute to the GetPropertyName accessor. Применение к get вместо этого set может показаться не интуитивно понятным; однако это соглашение может поддерживать концепцию присоединяемых членов только для чтения, которые являются сериализуемыми, что полезно в сценариях конструктора.Applying to the get instead of the set may seem non-intuitive; however, this convention can support the concept of read-only attachable members that are serializable, which is useful in designer scenarios.

Метод доступа СетпропертинамеThe SetPropertyName Accessor

Сигнатура для SetPropertyName метода доступа должна быть такой:The signature for the SetPropertyName accessor must be:

public static void SetPropertyName(object target, object value)

  • targetОбъект может быть указан в реализации в качестве более конкретного типа с той же логикой и последствиями, как описано в предыдущем разделе.The target object can be specified as a more specific type in your implementation, with same logic and consequences as described in the previous section.

  • Объект value можно указать как более конкретный тип в реализации.The value object can be specified as a more specific type in your implementation.

Помните, что значение этого метода является входными данными, поступающими от использования XAML, обычно в форме атрибута.Remember that the value for this method is the input coming from the XAML usage, typically in attribute form. В форме атрибута должна быть поддержка преобразователя значений для текстового синтаксиса, и атрибут для GetPropertyName метода доступа s.From attribute form there must be value converter support for a text syntax, and you attribute on the GetPropertyNames accessor.

Хранилища присоединяемых членовAttachable Member Stores

Методы доступа обычно недостаточно для предоставления средств для размещения значений присоединяемых членов в графе объектов, а также для извлечения значений из графа объектов и их правильной сериализации.The accessor methods are typically not enough to provide a means to place attachable member values into an object graph, or to retrieve values out of the object graph and serialize them properly. Чтобы обеспечить эту функциональность, target объекты в предыдущих сигнатурах метода доступа должны иметь возможность хранить значения.To provide this functionality, the target objects in the previous accessor signatures must be capable of storing values. Механизм хранения должен соответствовать принципу присоединяемого члена, который прикрепляется к целевым объектам, в которых присоединяемый элемент отсутствует в списке членов.The storage mechanism should be consistent with the attachable member principle that the member is attachable to targets where the attachable member is not in the members list. Службы XAML .NET предоставляют метод реализации для присоединяемых хранилищ членов через API-интерфейсы IAttachedPropertyStore и AttachablePropertyServices ..NET XAML Services provides an implementation technique for attachable member stores through the APIs IAttachedPropertyStore and AttachablePropertyServices. IAttachedPropertyStore используется модулями записи XAML для обнаружения реализации хранилища и должен быть реализован в типе, который является методом target доступа.IAttachedPropertyStore is used by the XAML writers to discover the store implementation, and should be implemented on the type that is the target of the accessors. Статические AttachablePropertyServices API-интерфейсы используются в теле методов доступа и ссылаются на присоединяемый член по его свойству AttachableMemberIdentifier .The static AttachablePropertyServices APIs are used within the body of the accessors, and refer to the attachable member by its AttachableMemberIdentifier.

Правильное присвоение атрибутов типам, членам и сборкам важно для передачи сведений о системе типов XAML в службы .NET XAML.Correctly attributing your types, members, and assemblies is important in order to report XAML type system information to .NET XAML Services. Создание отчетов о системе типов XAML имеет смысл, если применяется одна из следующих ситуаций.Reporting XAML type system information is relevant if either of the following situations apply:

  • Вы планируете использовать типы для систем XAML, которые непосредственно основаны на средствах чтения XAML служб XAML .NET и модулях записи XAML.You intend your types for use with XAML systems that are directly based on .NET XAML Services XAML readers and XAML writers.
  • Вы определяете или используете платформу, использующую XAML, основанную на этих средствах чтения и записи XAML.You define or use a XAML-utilizing framework that's based on those XAML readers and XAML writers.

Список всех атрибутов, связанных с XAML, которые относятся к поддержке XAML пользовательских типов, см. в разделе связанные с XAML атрибуты среды CLR для пользовательских типов и библиотек.For a listing of each XAML-related attribute that's relevant for XAML support of your custom types, see XAML-Related CLR Attributes for Custom Types and Libraries.

ИспользованиеUsage

Для использования пользовательских типов необходимо, чтобы автор разметки сопоставлял префикс для сборки и пространство имен CLR, которое содержит пользовательский тип.Usage of custom types requires that the markup author must map a prefix for the assembly and CLR namespace that contain the custom type. Эта процедура не описана в этом разделе.This procedure is not documented in this topic.

Уровень доступаAccess Level

XAML предоставляет средства для загрузки и создания экземпляров типов, имеющих internal уровень доступа.XAML provides a means to load and instantiate types that have an internal access level. Эта возможность предоставляется, чтобы пользовательский код мог определять собственные типы, а затем создавать экземпляры этих классов из разметки, которая также является частью одной и той же области пользовательского кода.This capability is provided so that user code can define its own types, and then instantiate those classes from markup that is also part of the same user code scope.

Примером из WPF является каждый раз, когда пользовательский код определяет UserControl , который предназначен для оптимизации поведения пользовательского интерфейса, но не является частью любого возможного механизма расширения, который может быть подразумеваемым объявлением поддерживающего класса с public уровнем доступа.An example from WPF is whenever user code defines a UserControl that is intended as a way to refactor a UI behavior, but not as part of any possible extension mechanism that might be implied by declaring the supporting class with public access level. Такой объект UserControl может быть объявлен с internal доступом, если резервный код компилируется в ту же сборку, из которой он ссылается как на тип XAML.Such a UserControl can be declared with internal access if the backing code is compiled into the same assembly from which it is referenced as a XAML type.

Для приложения, которое загружает XAML в режиме полного доверия и использует XamlObjectWriter , Загрузка классов с internal уровнем доступа всегда включена.For an application that loads XAML under full trust and uses XamlObjectWriter, loading classes with internal access level is always enabled.

Для приложения, которое загружает XAML в режиме частичного доверия, можно управлять характеристиками уровня доступа с помощью XamlAccessLevel API.For an application that loads XAML under partial trust, you can control the access level characteristics by using the XamlAccessLevel API. Кроме того, механизмы отсрочки (например, система шаблонов WPF) должны иметь возможность распространять любые разрешения уровня доступа и сохранять их для выполнения в конечном итоге. Это осуществляется внутренним образом путем передачи XamlAccessLevel информации.Also, deferral mechanisms (such as the WPF template system) must be able to propagate any access level permissions and preserve them for the eventual run time evaluations; this is handled internally by passing the XamlAccessLevel information.

Реализация WPFWPF Implementation

XAML WPF использует модель доступа с частичным доверием, где при загрузке BAML в режиме частичного доверия доступ ограничен AssemblyAccessTo для сборки, являющейся источником BAML.WPF XAML uses a partial-trust access model where if BAML is loaded under partial trust, access is restricted to AssemblyAccessTo for the assembly that is the BAML source. Для РБП WPF использует IXamlObjectWriterFactory.GetParentSettings в качестве механизма для передачи сведений об уровне доступа.For deferral, WPF uses IXamlObjectWriterFactory.GetParentSettings as a mechanism for passing the access level information.

В терминологии WPF XAML внутренний тип — это тип, определяемый той же сборкой, которая также включает ссылающийся XAML.In WPF XAML terminology, an internal type is a type that is defined by the same assembly that also includes the referencing XAML. Такой тип можно сопоставить с помощью пространства имен XAML, которое намеренно опускает сборку = часть сопоставления, например xmlns:local="clr-namespace:WPFApplication1" .Such a type can be mapped through a XAML namespace that deliberately omits the assembly= portion of a mapping, for example, xmlns:local="clr-namespace:WPFApplication1". Если BAML ссылается на внутренний тип, а этот тип имеет internal уровень доступа, то создается GeneratedInternalTypeHelper класс для сборки.If BAML references an internal type and that type has internal access level, this generates a GeneratedInternalTypeHelper class for the assembly. Если вы хотите избежать GeneratedInternalTypeHelper , необходимо либо использовать public уровень доступа, либо отнести соответствующий класс к отдельной сборке и сделать ее зависимой.If you want to avoid GeneratedInternalTypeHelper, you either must use public access level, or must factor the relevant class into a separate assembly and make that assembly dependent.

См. такжеSee also