定义泛型的脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyClass<T>
{
public T value;
}
public class MyIntClass : MyClass<int>
{
}
1.不能使用 fields[i].FieldType == typeof(MyClass)
用于测试的 Mono 脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
using System.Linq;
public class TestMono : MonoBehaviour
{
private MyIntClass myIntIns = new MyIntClass();
void Start()
{
var fields = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Debug.LogError(fields[0].FieldType);
Debug.LogError(typeof(MyClass<int>));
Debug.LogError(fields[0].FieldType == typeof(MyClass<int>));
}
}
Log
MyIntClass
UnityEngine.Debug:LogError (object)
TestMono:Start () (at Assets/Scenes/TestMono.cs:18)
MyClass`1[System.Int32]
UnityEngine.Debug:LogError (object)
TestMono:Start () (at Assets/Scenes/TestMono.cs:19)
False
UnityEngine.Debug:LogError (object)
TestMono:Start () (at Assets/Scenes/TestMono.cs:20)
可见,直接使用 typeof(MyClass<XXX>) 与反射得到的 MyClass<XXX> 类型的变量的 FieldType 相比较是不行的
2.不能使用 typeof(MyClass<>).IsAssignableFrom(fields[i].FieldType)
用于测试的 Mono 脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
using System.Linq;
public class TestMono : MonoBehaviour
{
private MyIntClass myIntIns = new MyIntClass();
void Start()
{
var fields = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Debug.LogError(typeof(MyClass<>));
Debug.LogError(fields[0].FieldType);
Debug.LogError(typeof(MyClass<>).IsAssignableFrom(fields[0].FieldType));
}
}
Log
MyClass`1[T]
UnityEngine.Debug:LogError (object)
TestMono:Start () (at Assets/Scenes/TestMono.cs:18)
MyIntClass
UnityEngine.Debug:LogError (object)
TestMono:Start () (at Assets/Scenes/TestMono.cs:19)
False
UnityEngine.Debug:LogError (object)
TestMono:Start () (at Assets/Scenes/TestMono.cs:20)
3.可以用 fields[0].FieldType.BaseType.GetGenericTypeDefinition() == typeof(MyClass<>)
用于测试的 Mono 脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
using System.Linq;
public class TestMono : MonoBehaviour
{
private MyIntClass myIntIns = new MyIntClass();
void Start()
{
var fields = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Debug.LogError(typeof(MyClass<>));
Debug.LogError(fields[0].FieldType.BaseType.GetGenericTypeDefinition());
Debug.LogError(fields[0].FieldType.BaseType.GetGenericTypeDefinition() == typeof(MyClass<>));
}
}
Log
MyClass`1[T]
UnityEngine.Debug:LogError (object)
TestMono:Start () (at Assets/Scenes/TestMono.cs:18)
MyClass`1[T]
UnityEngine.Debug:LogError (object)
TestMono:Start () (at Assets/Scenes/TestMono.cs:19)
True
UnityEngine.Debug:LogError (object)
TestMono:Start () (at Assets/Scenes/TestMono.cs:20)
但是 GetGenericArguments() 只能用于泛型的 type
如果用于非泛型的 type 就会报错
InvalidOperationException: This operation is only valid on generic types.
System.RuntimeType.GetGenericTypeDefinition () (at <75633565436c42f0a6426b33f0132ade>:0)
TestMono+<>c.<Start>b__2_0 (System.Reflection.FieldInfo field) (at Assets/Scenes/TestMono.cs:19)
System.Linq.Enumerable+WhereArrayIterator`1[TSource].MoveNext () (at <1c318258bf0843289b0e2cbe692fee39>:0)
TestMono.Start () (at Assets/Scenes/TestMono.cs:19)
所以要先加一个是否是泛型的判断
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
public class TestMono : MonoBehaviour
{
private MyIntClass myIntIns = new MyIntClass();
private int testint = 0;
// Start is called before the first frame update
void Start()
{
var fields = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
myIntIns.value = 114514;
foreach (var field in fields)
{
if (field.FieldType.BaseType is not { IsGenericType: true }) continue;
if (field.FieldType.BaseType.GetGenericTypeDefinition() == typeof(MyClass<>))
{
var var_reflected = (MyClass<int>)field.GetValue(this);
Debug.LogError(var_reflected.value);
}
}
}
}