通过一个C#的反射编程源码让你了解C#反射编程原理
以下是一个 C# 反射(Reflection)编程的实用案例,演示如何通过反射动态加载类型、创建对象、调用方法及访问属性。本示例分为三个部分:动态创建对象、调用私有方法、以及动态操作泛型类型。
1. 动态创建对象并调用方法
假设有一个 Person 类,通过反射创建其实例并调用方法。
定义类
public class Person
{
public string Name { get; set; }
private int _age;
public Person() { }
public Person(string name, int age)
{
Name = name;
_age = age;
}
private void SayHello()
{
Console.WriteLine($"Hello, I'm {Name}, {_age} years old.");
}
}
反射操作代码
using System;
using System.Reflection;
class Program
{
static void Main()
{
// 1. 动态创建对象(使用带参数的构造函数)
Type type = typeof(Person);
object person = Activator.CreateInstance(type, new object[] { "Alice", 30 });
// 2. 获取并设置属性
PropertyInfo nameProp = type.GetProperty("Name");
nameProp.SetValue(person, "Bob"); // 修改 Name 属性
// 3. 调用私有方法
MethodInfo sayHelloMethod = type.GetMethod("SayHello", BindingFlags.NonPublic | BindingFlags.Instance);
sayHelloMethod.Invoke(person, null); // 输出: Hello, I'm Bob, 30 years old.
// 4. 访问私有字段
FieldInfo ageField = type.GetField("_age", BindingFlags.NonPublic | BindingFlags.Instance);
int age = (int)ageField.GetValue(person);
Console.WriteLine($"实际年龄: {age}"); // 输出: 实际年龄: 30
}
}
2. 动态操作泛型类型
反射可以处理泛型类或方法。以下示例通过反射调用 List<T> 的 Add 方法。
using System;
using System.Collections.Generic;
using System.Reflection;
class Program
{
static void Main()
{
// 1. 创建泛型 List<int> 类型
Type listType = typeof(List<>);
Type genericListType = listType.MakeGenericType(typeof(int));
// 2. 创建 List<int> 实例
object list = Activator.CreateInstance(genericListType);
// 3. 获取 Add 方法并调用
MethodInfo addMethod = genericListType.GetMethod("Add");
addMethod.Invoke(list, new object[] { 10 });
addMethod.Invoke(list, new object[] { 20 });
// 4. 输出列表内容
Console.WriteLine(string.Join(", ", (List<int>)list)); // 输出: 10, 20
}
}
3. 动态加载外部程序集并调用方法
假设有一个外部 DLL 文件 MyLibrary.dll,其中包含以下类:
namespace MyLibrary
{
public class Calculator
{
public int Add(int a, int b) => a + b;
}
}
反射加载并调用
using System;
using System.Reflection;
class Program
{
static void Main()
{
// 1. 动态加载程序集
Assembly assembly = Assembly.LoadFrom("MyLibrary.dll");
// 2. 获取 Calculator 类型
Type calculatorType = assembly.GetType("MyLibrary.Calculator");
// 3. 创建实例
object calculator = Activator.CreateInstance(calculatorType);
// 4. 调用 Add 方法
MethodInfo addMethod = calculatorType.GetMethod("Add");
int result = (int)addMethod.Invoke(calculator, new object[] { 5, 3 });
Console.WriteLine($"5 + 3 = {result}"); // 输出: 5 + 3 = 8
}
}
反射的核心用途
动态加载类型:无需在编译时引用程序集。
突破访问限制:访问私有方法、字段或属性。
泛型处理:动态构建泛型类型(如 List<T>)。
插件系统:通过反射加载外部插件。
注意事项
性能开销:反射比直接代码调用慢,需谨慎在高性能场景使用。
安全性:反射可能绕过访问修饰符限制,需确保代码安全。
异常处理:需处理 TypeNotFound、MethodNotFound 等异常。
总结
反射是 C# 中强大的元编程工具,适用于框架开发、插件系统或需要高度动态行为的场景。通过上述案例,可以掌握反射的基本操作,并根据需求扩展使用。
查看更多关于通过一个C#的反射编程源码让你了解C#反射编程原理的详细内容...