C#使用扩展方法获取Description特性文本详解
在C#开发中,[Description] 特性常用于为枚举成员或属性提供人类可读的描述文本。由于原生的 System.ComponentModel.DescriptionAttribute 并不包含直接的便捷提取方法,我们通常借助扩展方法来封装反射逻辑。本文将详细解析如何构建一个通用的 DescriptionExtension 类,以实现优雅地获取枚举和属性的描述信息。
结果与目标
目标是创建一个静态工具类,允许开发人员通过简洁的调用链直接获取带有 System.ComponentModel.DescriptionAttribute 修饰对象的描述文本。这可以解决在UI显示、日志记录或配置映射时,需要频繁编写重复反射代码的问题。
准备条件
- 项目引用
System.Reflection命名空间。 - 目标对象(枚举或属性)必须已应用
[Description("...")]`特性。 - 建议使用 .NET Framework 4.0+ 或 .NET Core / .NET 5+ 环境。
真实操作顺序
第1步:创建扩展类与基础逻辑
目的:定义核心扩展方法,利用反射检索特性并返回文本值。
入口:新建一个名为 DescriptionExtension 的静态类。
动作:实现以下三个重载方法:
using System;
using System.ComponentModel;
using System.Reflection;
///
/// 描述特性的读取扩展类
///
public static class DescriptionExtension
{
///
/// 获取枚举值的描述信息
///
public static string GetDescription(this Enum em)
{
Type type = em.GetType();
FieldInfo fd = type.GetField(em.ToString());
string des = fd.GetDescription();
return des;
}
///
/// 获取类型的某个属性的描述信息
///
public static string GetDescription(this Type type, string proName)
{
PropertyInfo pro = type.GetProperty(proName);
string des = proName; // 默认回退值为属性名
if (pro != null)
{
des = pro.GetDescription();
}
return des;
}
///
/// 内部辅助方法:获取MemberInfo描述的文本
///
private static string GetDescription(this MemberInfo info)
{
var attrs = (DescriptionAttribute[])info.GetCustomAttributes(typeof(DescriptionAttribute), false);
string des = info.Name;
foreach (DescriptionAttribute attr in attrs)
{
des = attr.Description;
}
return des;
}
}
第2步:定义测试数据结构
目的:准备带有 Description 特性的枚举和类,用于验证扩展方法的有效性。
入口:在项目中新建测试文件或修改现有实体。
动作:为枚举和类添加特性标记:
[Description("测试枚举标题")]
enum TestEnum
{
[Description("测试子项1")]
Test1
}
[Description("测试类标题")]
class TestClass
{
[Description("这是Test1属性的描述")]
public int Test1 { get; set; }
}
第3步:调用扩展方法获取描述
目的:演示如何在实际业务代码中调用上述扩展类。
入口:在需要使用描述文本的地方调用。
动作:执行以下代码片段,分别获取枚举本身、枚举值以及类属性的描述:
// 获取枚举类型的描述特性
string strEnumTitle = typeof(TestEnum).GetDescription();
// 注意:上面的示例代码中 GetDescription(Type) 主要设计用于属性,若需获取枚举本身的描述,需额外处理或直接访问FieldInfo。这里展示获取枚举值的标准用法:
// 1. 获取枚举值的描述特性 (推荐方式)
string strEnumValueDesc = TestEnum.Test1.GetDescription();
// 2. 通过Type和字段名获取枚举值的描述
string strEnumValueDesc2 = typeof(TestEnum).GetDescription(nameof(TestEnum.Test1));
string strEnumValueDesc3 = typeof(TestEnum).GetDescription(TestEnum.Test1.ToString());
// 3. 获取类的描述特性
string strClassDesc = typeof(TestClass).GetDescription();
// 4. 获取类的特定属性描述
TestClass test = new TestClass();
string strPropDesc = typeof(TestClass).GetDescription(nameof(test.Test1));
第4步:替代方案(针对纯枚举场景)
目的:如果仅需要针对枚举的简化版获取方法,可以使用更精简的单方法扩展。
参数:nameInstead 布尔值。当找不到 Description 特性时,是否返回枚举原始名称,默认为 true。
///
/// 扩展方法,获得枚举的Description
///
public static string GetEnumDescription(this Enum value, Boolean nameInstead = true)
{
Type type = value.GetType();
string name = Enum.GetName(type, value);
if (name == null)
{
return null;
}
FieldInfo field = type.GetField(name);
DescriptionAttribute attribute = System.Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attribute == null && nameInstead == true)
{
return name;
}
return attribute?.Description;
}
使用示例:
public enum ModuleType
{
[Description("中国")]
ZH = 1,
[Description("美国")]
MG = 2
}
完成判断
运行测试代码后,strEnumValueDesc 应等于 "测试子项1",strPropDesc 应等于 "这是Test1属性的描述"。若在缺少特性的情况下且设置 nameInstead=false,则返回 null 或属性名,说明逻辑正确生效。
简要总结
通过反射机制结合C#扩展方法,我们可以极大地简化 System.ComponentModel.DescriptionAttribute 的读取流程。这不仅提升了代码的可读性,还避免了在每个需求点重复编写反射查找逻辑。掌握此技巧有助于规范项目中关于本地化描述或元数据展示的编码风格。
以上就是C#使用扩展方法获取Description特性文本的详细内容,更多关于C#获取枚举和属性的Description特性资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













