反射与特性 #

一、反射概述 #

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