C#的反射使用示例
C# 反射机制提供了在运行时动态获取类型信息、创建对象、调用方法等能力:
1. 插件式架构
在插件式架构中,主程序需要在运行时动态加载插件程序集,并调用其中的类型和方法。反射可以帮助实现这种动态加载和调用的功能。
示例代码
- 插件接口定义(PluginInterface.cs):
namespace PluginInterface
{
public interface IPlugin
{
void Execute();
}
}
- 插件实现(Plugin1.cs):
using PluginInterface;
namespace Plugin1
{
public class MyPlugin : IPlugin
{
public void Execute()
{
System.Console.WriteLine("Plugin1 is executed.");
}
}
}
- 主程序(MainProgram.cs):
using System;
using System.IO;
using System.Reflection;
using PluginInterface;
class MainProgram
{
static void Main()
{
// 加载插件程序集
Assembly assembly = Assembly.LoadFrom("Plugin1.dll");
// 获取实现 IPlugin 接口的类型
foreach (Type type in assembly.GetTypes())
{
if (typeof(IPlugin).IsAssignableFrom(type) && !type.IsInterface)
{
// 创建插件实例
IPlugin plugin = (IPlugin)Activator.CreateInstance(type);
// 调用插件方法
plugin.Execute();
}
}
}
}
2. 配置文件驱动的对象创建
当需要根据配置文件中的类型信息动态创建对象时,反射可以发挥作用。
示例代码
- 配置文件(config.txt):
plaintext
MyNamespace.MyClass
- 类定义(MyClass.cs):
namespace MyNamespace
{
public class MyClass
{
public void DoSomething()
{
System.Console.WriteLine("MyClass is doing something.");
}
}
}
- 主程序(MainProgram.cs):
using System;
using System.IO;
using System.Reflection;
class MainProgram
{
static void Main()
{
// 从配置文件中读取类型名称
string typeName = File.ReadAllText("config.txt").Trim();
// 获取类型
Type type = Type.GetType(typeName);
if (type != null)
{
// 创建对象实例
object obj = Activator.CreateInstance(type);
// 获取方法信息
MethodInfo method = type.GetMethod("DoSomething");
if (method != null)
{
// 调用方法
method.Invoke(obj, null);
}
}
}
}
3. 数据映射和转换
在数据处理中,可能需要将一个对象的属性值映射到另一个对象的属性上。反射可以帮助实现这种动态的数据映射。
示例代码
using System;
using System.Reflection;
class SourceClass
{
public string Name { get; set; }
public int Age { get; set; }
}
class TargetClass
{
public string Name { get; set; }
public int Age { get; set; }
}
class Program
{
static void Main()
{
SourceClass source = new SourceClass { Name = "John", Age = 30 };
TargetClass target = new TargetClass();
// 使用反射进行属性映射
Type sourceType = source.GetType();
Type targetType = target.GetType();
foreach (PropertyInfo sourceProperty in sourceType.GetProperties())
{
PropertyInfo targetProperty = targetType.GetProperty(sourceProperty.Name);
if (targetProperty != null && targetProperty.CanWrite &&
sourceProperty.PropertyType == targetProperty.PropertyType)
{
targetProperty.SetValue(target, sourceProperty.GetValue(source));
}
}
Console.WriteLine($"Name: {target.Name}, Age: {target.Age}");
}
}
具体分析
-
sourceType.GetProperties()
:这行代码会获取SourceClass
类型的所有公共属性。对于SourceClass
来说,它有两个公共属性Name
和Age
。 -
foreach (PropertyInfo sourceProperty in sourceType.GetProperties())
:这个foreach
循环会依次遍历SourceClass
的每个属性。在每次循环中,sourceProperty
代表当前正在处理的属性的信息,它是一个PropertyInfo
类型的对象。 -
sourceProperty.Name
:PropertyInfo
类的Name
属性用于获取属性的名称。当第一次循环时,sourceProperty
可能代表Name
属性,此时sourceProperty.Name
的值就是"Name"
;当第二次循环时,sourceProperty
代表Age
属性,sourceProperty.Name
的值就是"Age"
。 -
targetType.GetProperty(sourceProperty.Name)
:这行代码会根据sourceProperty.Name
的值,在TargetClass
类型中查找同名的属性。如果找到了同名属性,就将其赋值给targetProperty
。