.NET 反射

梦想航路發表於2024-05-20

.NET中的反射

反射是什麼?

反射(Reflection)是.NET框架提供的一種強大的機制,它允許程式在執行時查詢和操作物件的型別資訊。透過反射,我們能夠獲取型別的屬性、方法、建構函式等資訊,甚至可以動態地建立型別例項和呼叫方法。反射是.NET框架中實現諸如序列化、反序列化、動態代理、依賴注入等高階功能的基礎。

反射的具體應用場景

  1. 序列化與反序列化:在進行物件的序列化和反序列化時,反射可以用來訪問物件的私有欄位。
  2. 動態代理:在建立動態代理時,反射用於獲取介面或類的成員資訊。
  3. 依賴注入:在依賴注入框架中,反射用於自動解析類的依賴關係。
  4. 單元測試:在進行單元測試時,反射可以用來訪問和測試私有成員。
  5. 配置和繫結:在配置應用程式時,反射用於將配置資訊繫結到程式集的型別上。

常用的API

反射相關的主要類包括:

  • Type:表示一個型別,是反射操作的核心。
  • MethodInfo:表示一個方法。
  • PropertyInfo:表示一個屬性。
  • FieldInfo:表示一個欄位。
  • ConstructorInfo:表示一個建構函式。
  • Assembly:表示一個程式集,包含了一個或多個型別。

示例程式碼

以下是一些使用反射API的示例程式碼。

示例1:獲取型別資訊

using System;
using System.Reflection;

public class Person
{
    public string _name;
    public int _age;

    public string Name { get; set; }
    public int Age { get; set; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    public void IntroduceYourself()
    {
        Console.WriteLine($"Hello, Name: {Name} Age: {Age}");
    }
}

class ReflectionDemo
{
    static void Main(string[] args)
    {
        // 獲取Person型別的Type物件
        Type personType = typeof(Person);

        // 獲取型別名稱
        Console.WriteLine("Type Name: " + personType.Name);

        // 獲取建構函式資訊
        ConstructorInfo constructor = personType.GetConstructor(new Type[] { typeof(string), typeof(int) });
        Console.WriteLine("Constructor: " + constructor);

        // 建立Person例項
        object personInstance = constructor.Invoke(new object[] { "張三", 30 });

        // 獲取方法資訊並呼叫
        MethodInfo methodInfo = personType.GetMethod("IntroduceYourself");
        methodInfo.Invoke(personInstance, null);
    }
}

示例2:訪問屬性和欄位

// 假設Person類定義如上

class ReflectionDemo2
{
    static void Main(string[] args)
    {
            // 建立Person例項
          Person person = new Person("張三", 25);

          // 獲取Person型別的Type物件
          Type type = person.GetType();

          // 獲取屬性資訊
          PropertyInfo nameProperty = type.GetProperty("Name");
          PropertyInfo ageProperty = type.GetProperty("Age");

          // 讀取屬性值
          Console.WriteLine("Name: " + nameProperty.GetValue(person, null));
          Console.WriteLine("Age: " + ageProperty.GetValue(person, null));

          // 獲取欄位資訊
          FieldInfo nameField = type.GetField("_name", BindingFlags.Public | BindingFlags.Instance);
          FieldInfo ageField = type.GetField("_age", BindingFlags.Public | BindingFlags.Instance);

          // 設定欄位值
          nameField.SetValue(person, "李四");
          ageField.SetValue(person, 26);

          // 驗證欄位值更新
          Console.WriteLine("_name: " + nameField.GetValue(person));
          Console.WriteLine("_age: " + ageField.GetValue(person));
    }
}

結論

以上程式碼展示了反射的基本用法,包括型別資訊的獲取、例項的建立、方法的呼叫以及屬性的訪問。反射是一個非常強大的功能,但同時也要注意,過度使用反射可能會導致效能問題,因為反射操作通常比直接程式碼呼叫要慢。

相關文章