跳到主要内容

C# 反射

本章将介绍 C# 中的反射(Reflection)机制,用于在运行时获取类型信息和操作对象。

反射概述

什么是反射?

反射允许程序在运行时检查和操作类型、成员,以及动态创建对象实例。

// 获取类型信息
Type type = typeof(string);
Console.WriteLine(type.FullName); // System.String

Type 类

获取 Type

// 方式1:通过 typeof
Type t1 = typeof(int);

// 方式2:通过对象
string str = "hello";
Type t2 = str.GetType();

// 方式3:通过完整名称
Type t3 = Type.GetType("System.Int32");

类型信息

Type type = typeof(Person);

Console.WriteLine(type.Name); // Person
Console.WriteLine(type.FullName); // Namespace.Person
Console.WriteLine(type.Namespace); // Namespace
Console.WriteLine(type.IsClass); // 是否为类
Console.WriteLine(type.IsValueType); // 是否为值类型
Console.WriteLine(type.IsInterface); // 是否为接口
Console.WriteLine(type.IsEnum); // 是否为枚举

// 获取基类
Type baseType = type.BaseType;

// 获取接口
Type[] interfaces = type.GetInterfaces();

// 获取成员
PropertyInfo[] properties = type.GetProperties();
MethodInfo[] methods = type.GetMethods();
FieldInfo[] fields = type.GetFields();

成员操作

获取属性

class Person
{
public string Name { get; set; }
public int Age { get; set; }
private string _secret = "秘密";
}

Type type = typeof(Person);

// 获取所有公共属性
PropertyInfo[] props = type.GetProperties();
foreach (var prop in props)
{
Console.WriteLine($"{prop.Name}: {prop.PropertyType.Name}");
}

// 获取特定属性
PropertyInfo? nameProp = type.GetProperty("Name");
if (nameProp != null)
{
Console.WriteLine($"可读: {nameProp.CanRead}, 可写: {nameProp.CanWrite}");
}

获取方法

Type type = typeof(Math);

// 获取所有公共方法
MethodInfo[] methods = type.GetMethods();

// 获取特定方法
MethodInfo? absMethod = type.GetMethod("Abs", new[] { typeof(int) });

动态创建对象

Activator

// 创建对象实例
object obj = Activator.CreateInstance(typeof(Person));

// 使用已知的类型
Person person = (Person)obj;

// 泛型版本
var person2 = Activator.CreateInstance<Person>();

// 带参数的构造函数
var person3 = Activator.CreateInstance<Person>("张三", 20);

动态调用

object person = Activator.CreateInstance<Person>();

// 设置属性
Type type = typeof(Person);
PropertyInfo? nameProp = type.GetProperty("Name");
nameProp?.SetValue(person, "张三");

PropertyInfo? ageProp = type.GetProperty("Age");
ageProp?.SetValue(person, 20);

// 获取属性值
string? name = nameProp?.GetValue(person)?.ToString();

// 调用方法
MethodInfo? method = type.GetMethod("Introduce");
method?.Invoke(person, null);

泛型类型

处理泛型

Type listType = typeof(List<>);
Console.WriteLine(listType.Name); // List`1

// 获取泛型参数
Type genericArg = listType.GetGenericArguments()[0]; // T

// 构造具体类型
Type constructedType = typeof(List<string>);

// 获取构造类型的泛型参数
Type[] args = constructedType.GetGenericArguments();

反射在开发中的应用

依赖注入容器

class SimpleContainer
{
private Dictionary<Type, Type> _registrations = new();

public void Register<TService, TImplementation>()
where TImplementation : TService
{
_registrations[typeof(TService)] = typeof(TImplementation);
}

public TService Resolve<TService>()
{
var type = _registrations[typeof(TService)];
return (TService)Activator.CreateInstance(type);
}
}

数据映射

class Mapper
{
public void Map<TFrom, TTo>(TFrom source, TTo target)
{
var fromType = typeof(TFrom);
var toType = typeof(TTo);

var toProps = toType.GetProperties()
.Where(p => p.CanWrite);

foreach (var prop in toProps)
{
var fromProp = fromType.GetProperty(prop.Name);
if (fromProp != null && fromProp.CanRead)
{
var value = fromProp.GetValue(source);
prop.SetValue(target, value);
}
}
}
}

序列化

class SimpleSerializer
{
public string Serialize(object obj)
{
var type = obj.GetType();
var props = type.GetProperties();

var pairs = props.Select(p =>
$"{p.Name}={p.GetValue(obj)}");

return string.Join(";", pairs);
}
}

小结

  1. Type:获取类型信息
  2. MemberInfo:获取成员信息
  3. Activator:动态创建实例
  4. 反射的应用:依赖注入、数据映射、序列化

练习

  1. 实现一个简单的属性拷贝工具
  2. 实现一个根据类名动态创建对象的工厂
  3. 实现一个读取对象属性并输出的工具