You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 15:12:56