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);
}
}
小结
- Type:获取类型信息
- MemberInfo:获取成员信息
- Activator:动态创建实例
- 反射的应用:依赖注入、数据映射、序列化
练习
- 实现一个简单的属性拷贝工具
- 实现一个根据类名动态创建对象的工厂
- 实现一个读取对象属性并输出的工具