GetCustomAttributes无输出问题咨询:Enum与自定义类场景下的排查及优化方案
咱们先把核心概念理清楚,再逐个解决你的问题哈~
先澄清一个关键混淆点:类的ID、Tests不是自定义属性!
你提到的ID和Tests是类的实例属性(Property),用来存储对象的业务数据;而.NET里的「自定义属性(Custom Attribute)」是一种元数据机制——需要继承自Attribute类,用来给类型、方法、属性等添加额外的描述信息,比如系统自带的[Obsolete]、[DisplayName],或者你自己定义的特性,这俩完全是不同的东西~
问题1:Enum调用GetCustomAttributes无输出
出现这种情况大概率是你的枚举类型/枚举成员根本没添加自定义属性,或者调用方式不对。举个正确的示例:
步骤1:先定义自定义属性和带属性的枚举
// 自定义一个枚举可用的属性 [AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field)] public class EnumDescAttribute : Attribute { public string Description { get; } public EnumDescAttribute(string description) => Description = description; } // 给枚举类型和成员添加自定义属性 [EnumDesc("这是一个测试枚举")] public enum TestEnum { [EnumDesc("选项A的描述")] OptionA, [EnumDesc("选项B的描述")] OptionB }
步骤2:正确调用GetCustomAttributes
// 获取枚举类型本身的自定义属性 var enumTypeAttrs = typeof(TestEnum).GetCustomAttributes(true); foreach (var attr in enumTypeAttrs) { Console.WriteLine(attr.ToString()); } // 获取枚举成员的自定义属性 var memberAttrs = typeof(TestEnum).GetMember(nameof(TestEnum.OptionA))[0].GetCustomAttributes(true); foreach (var attr in memberAttrs) { Console.WriteLine(attr.ToString()); }
如果你的枚举没加任何[XXX]标记,GetCustomAttributes自然返回空集合,也就没有输出啦~
问题2:TryMe类重写ToString()无输出也无报错
原因和上面一样:你的TryMe类本身没有添加任何自定义属性!你看代码里的TryMe类,上面没有[XXXAttribute]这样的标记,所以this.GetType().GetCustomAttributes()返回的是空集合,ToString()最终返回空字符串,运行自然没输出(也没报错,因为代码逻辑本身是对的)。
给TryMe加个自定义属性试试,马上就能看到输出:
// 自定义一个类用的属性 public class ClassInfoAttribute : Attribute { public string Info { get; } public ClassInfoAttribute(string info) => Info = info; } // 给TryMe类添加自定义属性 [ClassInfo("这是一个测试类")] public class TryMe { // 原代码不变... }
这时候调用new TryMe(1, new List<string>()).ToString()就会输出ClassInfoAttribute,了。
你的额外疑问解答
1. 复杂结构下有没有更简便的枚举自定义属性的方法?
当然有,你可以封装通用的反射工具类,减少重复代码:
public static class AttributeHelper { // 获取类型的指定类型自定义属性 public static IEnumerable<T> GetCustomAttributes<T>(this Type type, bool inherit = true) where T : Attribute { return type.GetCustomAttributes(typeof(T), inherit).Cast<T>(); } // 获取类属性(Property)的指定类型自定义属性 public static IEnumerable<T> GetCustomAttributes<T>(this PropertyInfo prop, bool inherit = true) where T : Attribute { return prop.GetCustomAttributes(typeof(T), inherit).Cast<T>(); } // 可以继续扩展到字段、方法、枚举成员等场景 }
如果需要遍历类的所有实例属性,并获取它们的自定义属性,可以这样用:
var tryMeProps = typeof(TryMe).GetProperties(); foreach (var prop in tryMeProps) { var attrs = prop.GetCustomAttributes(true); Console.WriteLine($"属性【{prop.Name}】的自定义属性:"); foreach (var attr in attrs) { Console.WriteLine($" - {attr.ToString()}"); } }
如果是嵌套的复杂对象(比如类里包含其他类的属性),可以写递归遍历的逻辑,但要注意处理循环引用的情况~
内容的提问来源于stack exchange,提问作者user3732793

