Reflection 使你能够获取有关加载的程序集和其中定义的类型的信息,如类、接口和值类型。 程序集包含模块、模块包含类型,而类型包含成员。反射提供封装程序集、模块和类型的对象。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了特性,可以利用反射来访问它们。

反射的基础用法如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Reflection;

public class Test : MonoBehaviour
{
    private void Start()
    {
        // 获取类型
        Type t = Type.GetType("Person");
        t = typeof(Person);

        // 所有成员
        MemberInfo[] all = t.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static
            | BindingFlags.Instance | BindingFlags.DeclaredOnly);

        // 字段
        FieldInfo[] fi = t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        foreach (var v in fi)
        {
            Debug.Log(v.Name);
        }

        // 属性
        PropertyInfo[] pi = t.GetProperties();
        foreach (var v in pi)
        {
            Debug.Log(v.Name);
        }

        // 方法
        MethodInfo[] mi = t.GetMethods();
        foreach (var v in mi)
        {
            Debug.Log(v.Name);
        }

        // 动态创建对象
        Person p = Activator.CreateInstance(t, new object[] { "sh" }) as Person;
        PropertyInfo ppi = t.GetProperty("Age");
        ppi.SetValue(p, 25, null);
        MethodInfo pmi = t.GetMethod("IsYong");
        Debug.Log("Age:" + p.Age + "  IsYong:" + pmi.Invoke(p, null));
    }
}

public class Person
{
    private string name;

    public int Age { get; set; }

    public Person(string name)
    {
        this.name = name;
    }

    [Obsolete("一个Obsolete特性的使用")]
    public bool IsYong()
    {
        return Age <= 18;
    }
}

在下面的例子中,使用反射动态向List中添加数据,代码在Unity中通过

BaseTable.cs

1
2
3
4
5
6
7
8
9
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BaseTable : MonoBehaviour
{
    public string excelPath;
    public string tableName;
}

ItemTable.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemTable : BaseTable
{
    public List<ItemData> dataList = new List<ItemData>();
}

[System.Serializable]
public class ItemData
{
    public int X;
    public int Y;
}

BaseTableEditor.cs 文件放在 Editor 目录下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using System.Reflection;

[CustomEditor(typeof(BaseTable), true)]
public class BaseTableEditor : Editor {

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        if (GUILayout.Button("Load"))
        {
            Type targetType = target.GetType();
            FieldInfo dataListField = targetType.GetField("dataList");

            Type listType = dataListField.FieldType;
            Type dataType = listType.GetGenericArguments()[0];

            object obj = Activator.CreateInstance(dataType, null);
            foreach (var v in dataType.GetFields())
            {
                v.SetValue(obj, 1);
            }

            listType.GetMethod("Add").Invoke(dataListField.GetValue(target), new object[] { obj });
        }
    }
}