Преобразование типов данных
Вы можете использовать конвертер типов для преобразования типов данных между источником данных и UI. Это позволяет:
- Привязка типов данных, отличных от типа UI, например привязка к свойству
Texture2Dиз значенияint. - Преобразуйте типы данных, которые идентичны типу UI, если требуется другое представление данных, например, отображение угла в градусах вместо радиан.
Существуют две категории конвертеров типов: глобальные конвертер и конвертер по привязке.
Глобальные преобразователи
Глобальные преобразователи статически регистрируются и доступны для всех экземпляров привязки, независимо от режимов привязки. Система привязки предоставляет несколько предварительно зарегистрированных глобальных преобразователей для удобства, таких как преобразователи между значениями стиля и их базовым представлением данных. Вы можете использовать их для привязки обычного float или StyleKeyword к свойству StyleFloat, вместо использования StyleFloat в источнике данных.
Чтобы зарегистрировать глобальный конвертер, используйте методы ConverterGroups.RegisterGlobalConverter. Этот метод требует, чтобы делегат преобразовал тип источника в тип назначения. Чтобы разрешить двунаправленное использование, делегат должен быть делегатом ref. После регистрации глобальные конвертер автоматически применяются к любым экземплярам привязки, требующим этого конкретного типа преобразования, без дополнительной конфигурации.
Регистрируйте глобальные конвертеры при запуске приложения, чтобы они были доступны, когда понадобятся. Делать это можно в статических конструкторах, при инициализации сборки или в стартовых методах. В следующем примере регистрируется глобальный конвертер, преобразующий между Texture2D и a TextureHandle:
static class RegisterGlobalConverters
{
#if UNITY_EDITOR
[InitializeOnLoadMethod]
#endif
[RuntimeInitializeOnLoadMethod]
public static void Register()
{
// Register global converters here
ConverterGroups.RegisterGlobalConverter((ref TextureHandle handle) => TextureHandle.ResolveTexture(handle));
ConverterGroups.RegisterGlobalConverter((ref Texture2D texture) => TextureHandle.FromTexture(texture));
}
}
public struct TextureHandle
{
public static Texture2D ResolveTexture(TextureHandle handle)
{
return /* Actual texture */;
}
public static TextureHandle FromTexture(Texture2D texture)
{
return new TextureHandle { handle = /* Compute handle */ };
}
public int handle;
}
Преобразователи по связям
Преобразователи для каждой привязки применяются к конкретному экземпляру привязки. Можно зарегистрировать один или группу преобразователей для каждой привязки. Преобразователи для каждой привязки регистрируются там, где создается экземпляр привязки. Это обеспечивает доступность преобразователей при использовании привязки.
Индивидуальный конвертер
Чтобы зарегистрировать индивидуальный конвертер, используйте метод DataBinding.sourceToUiConverters.AddConverter или DataBinding.uiToSourceConverters.AddConverter. Эти методы требуют, чтобы делегат преобразовал тип источника в тип назначения. Для двунаправленного использования делегат должен быть делегатом ref.
В следующем примере регистрируются и применяются отдельные преобразователи для преобразования радианов и градусов для экземпляра привязки:
var binding = new DataBinding();
binding.sourceToUiConverters.AddConverter((ref float radian) => Mathf.RadToDeg * radian);
binding.uiToSourceConverters.AddConverter((ref float degree) => Mathf.DegToRad * degree);
Групповой конвертер
Чтобы зарегистрировать группу преобразователей и применить их к DataBinding например, используйте ConverterGroup класс. Регистрируйте группы конвертеров один раз при инициализации — так же, как глобальные конвертеры. Делать это можно в статических конструкторах, при инициализации сборки или в стартовых методах.
В следующем примере показано, как зарегистрировать группу преобразователей:
static class RegisterConverterGroup
{
#if UNITY_EDITOR
[InitializeOnLoadMethod]
#endif
[RuntimeInitializeOnLoadMethod]
public static void Register()
{
// Create a converter group.
var group = new ConverterGroup("Inverters");
// Add converters to the converter group.
group.AddConverter((ref int v) => -v);
group.AddConverter((ref float v) => -v);
group.AddConverter((ref double v) => -v);
// Register the converter group
ConverterGroups.RegisterConverterGroup(group);
// Add a converter to an existing converter group.
if (ConverterGroups.TryGetConverterGroup("Inverters", out var group))
{
group.AddConverter((ref short v) => -v);
}
}
}
Применение группы преобразования
После регистрации группы конвертера ее можно применить к экземпляру привязки. Группу конвертера можно применить к экземпляру привязки в C#, UI Builder или UXML.
Чтобы применить группу конвертера в C#, используйте метод DataBinding.ApplyConverterGroupToUI или DataBinding.ApplyConverterGroupToSource. Эти методы принимают в качестве параметра имя группы конвертера.
В следующем примере группа конвертера Inverters применяется к экземпляру привязки в C#:
var binding = new DataBinding();
if (ConverterGroups.TryGetConverterGroup("Inverters", out var group))
{
binding.ApplyConverterGroupToUI(group);
binding.ApplyConverterGroupToSource(group);
}
Примечание: Когда вы применяете группу преобразователей к другой группе, она работает в режиме «сжигания и забывания». Это означает, что когда вы применяете группу преобразователей, она самостоятельно выполняет свою предназначенную функцию без дополнительного постоянного мониторинга или управления с вашей стороны.
Следующий пример применяет группу конвертера Inverters к привязке в UXML:
<ui:DataBinding source-to-ui-converters="Inverters" ui-to-source-converters="Inverters" />
Дополнительные сведения о применении группы преобразования в UI Builder см. в Начало работы с привязкой времени выполнения.
Сделать конвертер доступным в UI Builder
Для того, чтобы конвертер появился и был выделен в UI Builder:
- Регистрировать группы конвертеров глобально: Только глобально зарегистрированные группы конвертеров доступны в раскрывающемся списке UI Builder.
- Уникальные имена: Убедитесь, что каждая группа конвертеров имеет уникальное имя, чтобы избежать конфликтов в UI Builder.
- Зарегистрироваться заранее: убедитесь, что группы конвертеров зарегистрированы до загрузки UI Builder — обычно это делают в статических конструкторах с соответствующими атрибутами.
UI Builder автоматически находит и перечисляет в своём интерфейсе все зарегистрированные группы конвертеров, позволяя выбирать их из выпадающих списков при настройке привязок данных.
Передовая практика
Для оптимизации производительности следуйте этим советам и рекомендациям:
- Минимизировать выделение памяти: По возможности избегайте записи делегатов преобразования, которые выделяют память, особенно при работе с типами
enum. Выделение памяти во время преобразования может привести к ненужным накладным расходам и повлиять на производительность. Вместо этого выбирайте эффективные и бережливые к памяти подходы к преобразованию. - Сохранение эффективности преобразователей: Важно, чтобы преобразователи были сосредоточены на выполнении быстрых и эффективных преобразований типов. Избегайте выполнения обширных задач или сложных операций в преобразователях, поскольку это может привести к снижению производительности и потенциально ввести ненужную сложность.
- Интеграция преобразования типов в источник данных: Вместо того, чтобы полагаться исключительно на преобразования по привязке, рассмотрите возможность включения преобразования типов непосредственно в источник данных. Обрабатывая преобразование в самом источнике данных, вы можете оптимизировать процесс и потенциально повысить общую производительность. Этот подход также может уменьшить сложность, связанную с управлением преобразованиями на основе привязки.
Известные ограничения
Типы источника и назначения должны полностью совпадать, если только они не являются типом UnityEngine.Object. Например, вы не можете преобразовать int в floatили float в int. Это может быть неудобно, особенно с типами enum. Это ограничение будет исправлено в будущем выпуске.