文档

Unity Engine

Unity Engine

属性访问者

Understand the role of property visitors and the performance considerations when using them.
阅读时间4 分钟最后更新于 1 个月前

属性访问者是在 Properties API 的基础上构建的算法。

概念

可使用访问者向类型添加功能,而无需直接修改。可以创建高度通用的访问者来控制算法本身和访问过程。这与访问者模式的典型实现方式不同,后者的访问过程通常发生在一个事先已知的类型结构上。它支持序列化、类似于检视视图的 UI 生成等功能。
以下是访问者的基本模式。它发生在属性包和属性伴生对象上。
  1. 一个类型的实例接受一个访问者。
  2. 该访问者访问该实例的属性包。
  3. 属性包可以循环访问其属性并接受访问者。

创建属性访问者以获取属性

可以使用以下方法来创建访问者以获取属性:
第一种方法是最简单的入门方法。但是,为了更广泛地自定义属性包和属性的访问行为,请使用第二种方法,这种方法具有更大的灵活性和改进性能的潜力。
以下示例使用
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。这可能导致第一次接受对象的访问者时执行速度变慢。

其他资源