C#特性能否获取其标注属性对应的PropertyInfo?
C#特性能否直接获取标注的PropertyInfo?
结论:特性本身无法直接获取它所标注的PropertyInfo,必须通过遍历类的属性来匹配对应的特性,.NET没有内置的反向引用机制。
为什么特性无法直接获取标注的PropertyInfo?
特性的构造函数在编译阶段执行,而PropertyInfo是运行时反射才会生成的对象——编译时根本不存在对应的属性反射实例。而且特性实例是独立于标注成员的对象,没有内置逻辑让它反向关联到自己所标注的成员,所以你代码里的//magic部分没有可行的直接实现方式。
示例代码与正确实现方式
首先定义特性:
[AttributeUsage(AttributeTargets.Property)] public class ComputedCacheAttribute : Attribute { // 记录该计算属性依赖的其他字段/属性 public string[] Dependencies { get; } public ComputedCacheAttribute(params string[] dependencies) { Dependencies = dependencies; // 这里不存在能直接获取当前标注PropertyInfo的逻辑 // var propertyInfo = /* 没有这样的magic代码 */; } // 若要操作属性信息,只能由外部传入 public void PrintPropertyDetails(PropertyInfo propertyInfo) { Console.WriteLine($"计算缓存属性:{propertyInfo.Name},依赖字段:{string.Join(", ", Dependencies)}"); } }
使用特性的业务类:
public class Order { public int Quantity { get; set; } public decimal UnitPrice { get; set; } // 标记该属性是基于其他字段计算的缓存结果 [ComputedCache(nameof(Quantity), nameof(UnitPrice))] public decimal TotalAmount => Quantity * UnitPrice; }
正确的匹配方式:通过反射遍历类的属性,找到标注了特性的项,同时获取PropertyInfo和特性实例:
public static class ComputedCacheHandler { // 缓存遍历结果,避免重复反射开销 private static readonly Dictionary<Type, List<(PropertyInfo, ComputedCacheAttribute)>> _cachedProps = new(); public static IEnumerable<(PropertyInfo Property, ComputedCacheAttribute Attribute)> GetComputedProperties(Type type) { if (_cachedProps.TryGetValue(type, out var cached)) { return cached; } var result = new List<(PropertyInfo, ComputedCacheAttribute)>(); foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { var attr = property.GetCustomAttribute<ComputedCacheAttribute>(); if (attr != null) { result.Add((property, attr)); } } _cachedProps[type] = result; return result; } // 泛型版本,调用更简洁 public static IEnumerable<(PropertyInfo Property, ComputedCacheAttribute Attribute)> GetComputedProperties<T>() { return GetComputedProperties(typeof(T)); } } // 使用示例 var computedProps = ComputedCacheHandler.GetComputedProperties<Order>(); foreach (var (prop, attr) in computedProps) { attr.PrintPropertyDetails(prop); }
补充说明
如果需要频繁处理这类计算缓存属性,上面的缓存逻辑可以有效降低反射带来的性能开销。另外也可以结合源代码生成器,在编译阶段提前收集这些信息,彻底避免运行时反射,但实现复杂度会更高。
内容的提问来源于stack exchange,提问作者user2015635
相关产品推荐
相关产品推荐

