Посетители недвижимости
Посетители свойств определяют логику посещения сумки свойств данного типа для выполнения операций на его свойствах. Если тип был инструментализован для раскрытия своих свойств через сумку свойств, то это позволяет создать дополнительную функциональность для него без дальнейшего изменения типа напрямую.
Вы можете создавать очень общие посетители для определения как самого алгоритма посещения, так и процесса посещения. Это отличается от классической реализации шаблона посетителей тем, что позволяет обрабатывать любой тип, а не только специфические типы. Это позволяет использовать такие возможности, как серийизация и Inspector-подобное генерирование UI для типов, обнаруженных во время выполнения.
Ниже приводится основополагающий поток посещения, который происходит на мешках свойства и их сопутствующих предметов:
- Экземпляр типа принимает посетителя.
- Посетитель посещает сумку свойств экземпляра.
- Мешок свойств может повторять свои свойства и принимать посетителей.
Создание посетителя свойства для получения свойств
Вы можете использовать следующие подходы для создания посетителей, чтобы получить свойства:
- Получить из
Unity.Properties.PropertyVisitorбазовый класс. Пример см. ИспользованиеPropertyVisitorчтобы создать посетителя недвижимости. - Реализуйте интерфейсы
IPropertyBagVisitorиIPropertyVisitor. Например, см. Используйте низкоуровневый интерфейс APIs для создания посетителя свойства.
Первый подход является самым простым способом начать работу. Однако для более подробной настройки поведения посещения как для сумок свойств, так и для свойств используйте второй подход, который обеспечивает большую гибкость и потенциал для повышения производительности.
В следующем примере используется PropertyVisitor класс, чтобы создать простой визитор, который получает свойства заданного типа, помеченные определённым атрибутом:
public class BindableAttribute
: Attribute
{
}
public class GatherBindablePropertiesVisitor
: PropertyVisitor
{
public List<PropertyPath> BindableProperties { get; set; }
protected override void VisitProperty<TContainer, TValue>(Property<TContainer, TValue> property, ref TContainer container, ref TValue value)
{
if (property.HasAttribute<BindableAttribute>())
BindableProperties.Add(PropertyPath.AppendProperty(default, property));
}
}
Ниже приводится эквивалентный пример, в котором используется IPropertyBagVisitor интерфейс, чтобы создать визитор:
public class BindableAttribute
: Attribute
{
}
public class GatherBindablePropertiesVisitor
: IPropertyBagVisitor
{
public List<PropertyPath> BindableProperties { get; set; }
void IPropertyBagVisitor.Visit<TContainer>(IPropertyBag<TContainer> propertyBag, ref TContainer container)
{
// Loop through the properties of the container object.
foreach (var property in propertyBag.GetProperties(ref container))
{
if (property.HasAttribute<BindableAttribute>())
BindableProperties.Add(PropertyPath.AppendProperty(default, property));
}
}
}
Низкоуровневый посетитель работает более эффективно, так как ему не нужно переходить через все свойства сумки свойств и извлекать их значения. Вы также можете использовать низкоуровневых посетителей для посещения свойств, которые не являются частью сумки свойств.
Соображения, касающиеся эффективности
Проприетарные сумки, свойства и посетители реализованы с использованием общих типов, чтобы сохранить код как можно более сильно типизированным и избежать выделения боксов во время посещения. Компромисс использования общих типов заключается в том, что компилятор JIT генерирует промежуточный язык (IL) для данного метода при первом его вызове. Это может привести к более медленному выполнению при первом принятии посетителя на объект.