反射与特性 #
一、反射概述 #
1.1 什么是反射 #
反射是在运行时检查和操作类型的能力。
1.2 反射用途 #
- 类型检查
- 动态创建对象
- 动态调用方法
- 访问属性和字段
二、Type类 #
2.1 获取Type #
csharp
Type type1 = typeof(string);
Type type2 = "Hello".GetType();
Type type3 = Type.GetType("System.String");
Type listType = typeof(List<int>);
Type genericType = typeof(List<>);
2.2 类型信息 #
csharp
Type type = typeof(List<int>);
Console.WriteLine($"名称: {type.Name}");
Console.WriteLine($"全名: {type.FullName}");
Console.WriteLine($"命名空间: {type.Namespace}");
Console.WriteLine($"基类: {type.BaseType}");
Console.WriteLine($"是否泛型: {type.IsGenericType}");
Console.WriteLine($"是否数组: {type.IsArray}");
Console.WriteLine($"是否值类型: {type.IsValueType}");
三、反射成员 #
3.1 获取方法 #
csharp
Type type = typeof(string);
MethodInfo[] methods = type.GetMethods();
MethodInfo? method = type.GetMethod("Substring", new[] { typeof(int), typeof(int) });
foreach (var m in methods)
{
Console.WriteLine($"{m.ReturnType.Name} {m.Name}({string.Join(", ", m.GetParameters().Select(p => p.ParameterType.Name))})");
}
3.2 获取属性 #
csharp
Type type = typeof(Person);
PropertyInfo[] properties = type.GetProperties();
PropertyInfo? property = type.GetProperty("Name");
foreach (var p in properties)
{
Console.WriteLine($"{p.PropertyType.Name} {p.Name}");
}
3.3 获取字段 #
csharp
Type type = typeof(Person);
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo? field = type.GetField("_name", BindingFlags.NonPublic | BindingFlags.Instance);
3.4 获取构造函数 #
csharp
Type type = typeof(Person);
ConstructorInfo[] constructors = type.GetConstructors();
ConstructorInfo? constructor = type.GetConstructor(new[] { typeof(string), typeof(int) });
四、动态调用 #
4.1 创建对象 #
csharp
Type type = typeof(List<int>);
object? instance = Activator.CreateInstance(type);
object? instance2 = Activator.CreateInstance(type, new object[] { 100 });
4.2 调用方法 #
csharp
Type type = typeof(List<int>);
object? list = Activator.CreateInstance(type);
MethodInfo? addMethod = type.GetMethod("Add");
addMethod?.Invoke(list, new object[] { 42 });
MethodInfo? countProperty = type.GetProperty("Count")?.GetGetMethod();
int count = (int?)countProperty?.Invoke(list, null) ?? 0;
4.3 获取设置属性 #
csharp
Type type = typeof(Person);
object? person = Activator.CreateInstance(type);
PropertyInfo? nameProperty = type.GetProperty("Name");
nameProperty?.SetValue(person, "张三");
string? name = (string?)nameProperty?.GetValue(person);
五、特性 #
5.1 内置特性 #
csharp
[Obsolete("请使用新方法", true)]
public void OldMethod() { }
[Serializable]
public class Person { }
[Conditional("DEBUG")]
public void DebugMethod() { }
5.2 自定义特性 #
csharp
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class AuthorAttribute : Attribute
{
public string Name { get; }
public string? Email { get; set; }
public AuthorAttribute(string name)
{
Name = name;
}
}
[Author("张三", Email = "zhangsan@example.com")]
public class MyClass
{
[Author("李四")]
public void DoWork() { }
}
5.3 读取特性 #
csharp
Type type = typeof(MyClass);
var attributes = type.GetCustomAttributes<AuthorAttribute>();
foreach (var attr in attributes)
{
Console.WriteLine($"作者: {attr.Name}, 邮箱: {attr.Email}");
}
MethodInfo? method = type.GetMethod("DoWork");
var methodAttributes = method?.GetCustomAttributes<AuthorAttribute>();
六、实战示例 #
6.1 对象映射 #
csharp
public static TTarget Map<TSource, TTarget>(TSource source)
where TTarget : new()
{
var target = new TTarget();
var sourceType = typeof(TSource);
var targetType = typeof(TTarget);
foreach (var sourceProp in sourceType.GetProperties())
{
var targetProp = targetType.GetProperty(sourceProp.Name);
if (targetProp != null && targetProp.PropertyType == sourceProp.PropertyType)
{
var value = sourceProp.GetValue(source);
targetProp.SetValue(target, value);
}
}
return target;
}
6.2 验证特性 #
csharp
[AttributeUsage(AttributeTargets.Property)]
public class RequiredAttribute : Attribute
{
public string? ErrorMessage { get; set; }
}
[AttributeUsage(AttributeTargets.Property)]
public class RangeAttribute : Attribute
{
public int Min { get; }
public int Max { get; }
public RangeAttribute(int min, int max)
{
Min = min;
Max = max;
}
}
public static bool Validate(object obj, out List<string> errors)
{
errors = new List<string>();
var type = obj.GetType();
foreach (var prop in type.GetProperties())
{
var value = prop.GetValue(obj);
var required = prop.GetCustomAttribute<RequiredAttribute>();
if (required != null && value == null)
{
errors.Add(required.ErrorMessage ?? $"{prop.Name} 是必填项");
}
var range = prop.GetCustomAttribute<RangeAttribute>();
if (range != null && value is int intValue)
{
if (intValue < range.Min || intValue > range.Max)
{
errors.Add($"{prop.Name} 必须在 {range.Min} 和 {range.Max} 之间");
}
}
}
return errors.Count == 0;
}
七、总结 #
反射与特性要点:
| 要点 | 说明 |
|---|---|
| typeof | 获取Type |
| GetMethods | 获取方法 |
| GetProperties | 获取属性 |
| Invoke | 动态调用 |
| Attribute | 自定义特性 |
下一步,让我们学习扩展方法!
最后更新:2026-03-26