CustomAttributeData提供非侵入式读取特性的元数据,避免实例化带来的性能开销与异常风险,适用于程序集分析、代码生成等需安全高效解析特性的场景。

在.NET中,
CustomAttributeData
要使用
CustomAttributeData
CustomAttributeData
Type
MethodInfo
PropertyInfo
MemberInfo
GetCustomAttributesData()
这是一个基本的例子,展示了如何读取一个自定义特性的信息:
using System;
using System.Collections.Generic;
using System.Reflection;
// 定义一个简单的自定义特性
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class MyCustomAttribute : Attribute
{
public string Description { get; set; }
public int Version { get; }
public MyCustomAttribute(int version)
{
Version = version;
}
public MyCustomAttribute(int version, string description) : this(version)
{
Description = description;
}
}
// 应用特性的示例类
[MyCustom(1, Description = "这是一个类的特性")]
[MyCustom(2)]
public class MyClass
{
[MyCustom(10, Description = "这是一个方法的特性")]
public void MyMethod()
{
Console.WriteLine("Method executed.");
}
}
public class AttributeReader
{
public static void ReadAttributes()
{
Type targetType = typeof(MyClass);
Console.WriteLine($"--- 读取 {targetType.Name} 上的特性 ---");
// 获取类型上的所有CustomAttributeData
IList<CustomAttributeData> typeAttributes = CustomAttributeData.GetCustomAttributes(targetType);
foreach (var attrData in typeAttributes)
{
Console.WriteLine($" 特性类型: {attrData.AttributeType.Name}");
Console.WriteLine($" 构造函数: {attrData.Constructor.Name}");
// 解析构造函数参数
foreach (var arg in attrData.ConstructorArguments)
{
Console.WriteLine($" 构造参数: 类型={arg.ArgumentType.Name}, 值={arg.Value}");
}
// 解析命名参数
foreach (var namedArg in attrData.NamedArguments)
{
Console.WriteLine($" 命名参数: 名称={namedArg.MemberName}, 类型={namedArg.TypedValue.ArgumentType.Name}, 值={namedArg.TypedValue.Value}");
}
Console.WriteLine();
}
MethodInfo method = targetType.GetMethod(nameof(MyClass.MyMethod));
if (method != null)
{
Console.WriteLine($"--- 读取 {method.Name} 方法上的特性 ---");
IList<CustomAttributeData> methodAttributes = CustomAttributeData.GetCustomAttributes(method);
foreach (var attrData in methodAttributes)
{
Console.WriteLine($" 特性类型: {attrData.AttributeType.Name}");
Console.WriteLine($" 构造函数: {attrData.Constructor.Name}");
foreach (var arg in attrData.ConstructorArguments)
{
Console.WriteLine($" 构造参数: 类型={arg.ArgumentType.Name}, 值={arg.Value}");
}
foreach (var namedArg in attrData.NamedArguments)
{
Console.WriteLine($" 命名参数: 名称={namedArg.MemberName}, 类型={namedArg.TypedValue.ArgumentType.Name}, 值={namedArg.TypedValue.Value}");
}
Console.WriteLine();
}
}
}
}
// 在Main方法或其他地方调用 AttributeReader.ReadAttributes();
// AttributeReader.ReadAttributes();通过这种方式,你可以深入到特性的“蓝图”层面,获取所有必要的元数据,而无需实际构建一个特性实例。
这其实是一个关于“惰性加载”和“深度检查”的选择题。当我们谈论反射和特性时,
Type.GetCustomAttributes()
MemberInfo.GetCustomAttributes()
想象一下,如果你的特性构造函数执行了耗时的操作,比如连接数据库,或者它引用了一个当前程序集无法加载的类型,甚至是特意设计成会抛出异常的构造函数。在这种情况下,
GetCustomAttributes()
ReflectionTypeLoadException
CustomAttributeData
GetCustomAttributes()
CustomAttributeData
所以,如果你只是想“看一眼”某个特性长什么样,有什么参数,或者你正在构建一个需要分析大量程序集而不实际加载其所有依赖的工具,
CustomAttributeData
GetCustomAttributes()
解析
CustomAttributeData
ConstructorArguments
NamedArguments
1. 构造函数参数 (ConstructorArguments):
CustomAttributeData.ConstructorArguments
IList<CustomAttributeTypedArgument>
CustomAttributeTypedArgument
ArgumentType
Type
Value
object
解析时,你通常会遍历这个列表,然后根据
ArgumentType
Value
// 假设 attrData 是一个 CustomAttributeData 实例
foreach (var arg in attrData.ConstructorArguments)
{
Console.WriteLine($" 构造参数: 类型={arg.ArgumentType.Name}, 值={arg.Value}");
// 示例:如果参数是int类型
if (arg.ArgumentType == typeof(int))
{
int intValue = (int)arg.Value;
// ... 对intValue进行操作
}
// 示例:如果参数是枚举类型
else if (arg.ArgumentType.IsEnum)
{
// 枚举的Value通常是其底层整数类型,需要再次转换为枚举类型
object enumValue = Enum.ToObject(arg.ArgumentType, arg.Value);
// ... 对enumValue进行操作
}
// 示例:如果参数是数组类型 (这是个稍微复杂的情况)
else if (arg.ArgumentType.IsArray)
{
// Value会是一个ReadOnlyCollection<CustomAttributeTypedArgument>
var arrayValues = (System.Collections.ObjectModel.ReadOnlyCollection<CustomAttributeTypedArgument>)arg.Value;
Console.WriteLine(" 数组元素:");
foreach (var arrayItem in arrayValues)
{
Console.WriteLine($" 类型={arrayItem.ArgumentType.Name}, 值={arrayItem.Value}");
}
}
}2. 命名参数 (NamedArguments):
CustomAttributeData.NamedArguments
IList<CustomAttributeNamedArgument>
CustomAttributeNamedArgument
MemberName
string
IsField
bool
MemberName
TypedValue
CustomAttributeTypedArgument
CustomAttributeTypedArgument
ArgumentType
Value
解析命名参数时,你需要先获取
MemberName
TypedValue
// 假设 attrData 是一个 CustomAttributeData 实例
foreach (var namedArg in attrData.NamedArguments)
{
Console.WriteLine($" 命名参数: 名称={namedArg.MemberName}, 类型={namedArg.TypedValue.ArgumentType.Name}, 值={namedArg.TypedValue.Value}");
// 示例:如果命名参数是Description属性
if (namedArg.MemberName == "Description")
{
string description = (string)namedArg.TypedValue.Value;
// ... 对description进行操作
}
// 注意:这里的TypedValue.ArgumentType和TypedValue.Value的解析与构造函数参数类似
}需要特别注意的是,当参数是数组类型时,
Value
object[]
ReadOnlyCollection<CustomAttributeTypedArgument>
Value
CustomAttributeData
应用场景:
CustomAttributeData
CustomAttributeData
CustomAttributeData
CustomAttributeData
CustomAttributeData
局限性与注意事项:
CustomAttributeData
IsValid()
System.Type
CustomAttributeData
AttributeType
ArgumentType
TypeLoadException
CustomAttributeData
CustomAttributeTypedArgument
Value
GetCustomAttributesData()
GetCustomAttributes(true)
CustomAttributeData
总的来说,
CustomAttributeData
GetCustomAttributes()
以上就是.NET的CustomAttributeData类如何读取特性信息?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号