5.3 KiB
基础设施 API 参考
本文档介绍
AtomUI.Core/Reflection/命名空间中提供的反射工具方法,这些是所有反射扩展类的底层基础设施。
1. TypeMemberExtension
位置:src/AtomUI.Core/Reflection/TypeMemberExtension.cs
命名空间:AtomUI.Reflection
可见性:public static class
提供基于 Type 的成员查找方法,分为两类:TryGet 系列(安全查找)和 OrThrow 系列(快速失败)。
1.1 TryGet 系列
尝试查找成员,返回 bool 表示是否成功,通过 out 参数返回结果。
// 查找属性
bool TryGetPropertyInfo(this Type type, string name, out PropertyInfo? info, BindingFlags flags = ...)
// 查找字段
bool TryGetFieldInfo(this Type type, string name, out FieldInfo? info, BindingFlags flags = ...)
// 查找方法
bool TryGetMethodInfo(this Type type, string name, out MethodInfo? info, BindingFlags flags = ...)
// 查找事件
bool TryGetEventInfo(this Type type, string name, out EventInfo? info, BindingFlags flags = ...)
使用场景:当成员可能不存在时(如兼容多版本 Avalonia 的可选功能)。
1.2 OrThrow 系列
查找成员,找不到时抛出描述性异常。这是反射扩展类中的首选方法。
// 查找属性,失败抛 MissingMemberException
PropertyInfo GetPropertyInfoOrThrow(this Type type, string name, BindingFlags flags = ...)
// 查找字段,失败抛 MissingFieldException
FieldInfo GetFieldInfoOrThrow(this Type type, string name, BindingFlags flags = ...)
// 查找方法,失败抛 MissingMethodException
MethodInfo GetMethodInfoOrThrow(this Type type, string name, BindingFlags flags = ...)
// 查找事件,失败抛 MissingMemberException
EventInfo GetEventInfoOrThrow(this Type type, string name, BindingFlags flags = ...)
使用场景:反射扩展类中所有 Lazy<XxxInfo> 的初始化。
1.3 默认 BindingFlags
所有方法的默认 BindingFlags 均为:
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy
这意味着默认会搜索实例成员、公私有成员、以及继承链上的成员。如需精确控制,可显式传入 flags。
2. ObjectExtension
位置:src/AtomUI.Core/Reflection/ObjectExtension.cs
命名空间:AtomUI.Reflection
可见性:public static class
提供基于对象实例的反射操作方法,支持直接在对象上进行属性、字段的读写和方法调用。
2.1 属性操作
// 安全读取
bool TryGetProperty<T>(this object source, string name, out T? result, BindingFlags flags = ...)
bool TryGetProperty<T>(this object source, Type declareType, string name, out T? result, BindingFlags flags = ...)
bool TryGetProperty<T>(this object source, PropertyInfo info, out T? result)
// 快速失败读取
T? GetPropertyOrThrow<T>(this object source, string name, BindingFlags flags = ...)
T? GetPropertyOrThrow<T>(this object source, Type declareType, string name, BindingFlags flags = ...)
T? GetPropertyOrThrow<T>(this object source, PropertyInfo info)
// 安全写入
bool TrySetProperty<T>(this object source, Type declareType, string name, T? value, BindingFlags flags = ...)
2.2 字段操作
// 安全读取
bool TryGetField<T>(this object source, string name, out T? result, BindingFlags flags = ...)
bool TryGetField<T>(this object source, Type declareType, string name, out T? result, BindingFlags flags = ...)
bool TryGetField<T>(this object source, FieldInfo info, out T? result)
// 快速失败读取
T? GetFieldOrThrow<T>(this object source, string name, BindingFlags flags = ...)
T? GetFieldOrThrow<T>(this object source, Type declareType, string name, BindingFlags flags = ...)
// 安全写入
bool TrySetField<T>(this object source, Type declareType, string name, T? value, BindingFlags flags = ...)
2.3 方法调用
// 安全调用
bool TryInvokeMethod(this object source, Type declareType, string name, out object? result, params object[] parameters)
// 快速失败调用
object? InvokeMethodOrThrow(this object source, Type declareType, string name, params object[] parameters)
2.4 使用建议
ObjectExtension 中的方法适用于 一次性的、临时的 反射操作。对于需要反复调用的反射访问(即反射扩展类中的场景),应使用 TypeMemberExtension 获取 XxxInfo 并缓存到 Lazy<T> 字段中,然后通过 XxxInfo.GetValue() / XxxInfo.SetValue() / XxxInfo.Invoke() 直接操作,以获得更好的性能。
3. 方法选择决策树
需要反射访问 Avalonia 内部成员?
├─ 是否会被多次调用(如控件生命周期内反复触发)?
│ ├─ 是 → 创建 XxxReflectionExtensions 类
│ │ 使用 TypeMemberExtension.GetXxxInfoOrThrow 获取反射信息
│ │ 缓存到 Lazy<XxxInfo> 静态字段
│ │ 封装为扩展方法
│ └─ 否 → 是否是一次性初始化操作?
│ ├─ 是 → 可使用 ObjectExtension.GetPropertyOrThrow<T> 等
│ │ 但仍建议封装到扩展类中以保持一致性
│ └─ 否 → 封装到 XxxReflectionExtensions 扩展类
└─ 所有情况都必须标注 [DynamicDependency]