好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

通过一个C#的反射编程源码让你了解C#反射编程原理

通过一个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#反射编程原理的详细内容...

  阅读:27次