官方原文鏈接:https://ourpalm.github.io/ILRuntime/public/v1/guide/reflection.html
ILRuntime中的反射
用C#開發項目,很多時候會需要使用反射來實現某些功能。但是在腳本中使用反射其實是一個非常困難的事情。因爲這需要把ILRuntime中的類型轉換成一個真實的C#運行時類型,並把它們映射起來
默認情況下,System.Reflection命名空間中的方法,並不可能得知ILRuntime中定義的類型,因此無法通過Type.GetType等接口取得熱更DLL裏面的類型。而且ILRuntime裏的類型也並不是一個System.Type。
爲了解決這個問題,ILRuntime額外實現了幾個用於反射的輔助類:ILRuntimeType
,ILRuntimeMethodInfo
,ILRuntimeFieldInfo
等,來模擬系統的類型來提供部分反射功能
通過反射獲取Type
在熱更DLL
當中,直接調用Type.GetType(“TypeName”)或者typeof(TypeName)均可以得到有效System.Type類型實例
//在熱更DLL中,以下兩種方式均可以 Type t = typeof(TypeName); Type t2 = Type.GetType("TypeName"); |
在Unity主工程中
,無法通過Type.GetType來取得熱更DLL內部定義的類,而只能通過以下方式得到System.Type實例:
IType type = appdomain.LoadedTypes["TypeName"]; Type t = type.ReflectedType; |
通過反射創建實例
在熱更DLL
當中,可以直接通過Activator來創建實例:
Type t = Type.GetType("TypeName");//或者typeof(TypeName) //以下兩種方式均可以 object instance = Activator.CreateInstance(t); object instance = Activator.CreateInstance<TypeName>(); |
在Unity主工程中
,無法通過Activator來創建熱更DLL內類型的實例,必須通過AppDomain來創建實例:
object instance = appdomain.Instantiate("TypeName"); |
通過反射調用方法
在熱更DLL
當中,通過反射調用方法跟通常C#用法沒有任何區別
Type type = typeof(TypeName); object instance = Activator.CreateInstance(type); MethodInfo mi = type.GetMethod("foo"); mi.Invoke(instance, null); |
在Unity主工程中
,可以通過C#通常用法來調用,也可以通過ILRuntime自己的接口來調用,兩個方式是等效的:
IType t = appdomain.LoadedTypes["TypeName"]; Type type = t.ReflectedType; object instance = appdomain.Instantiate("TypeName"); //系統反射接口 MethodInfo mi = type.GetMethod("foo"); mi.Invoke(instance, null); //ILRuntime的接口 IMethod m = t.GetMethod("foo", 0); appdomain.Invoke(m, instance, null); |
通過反射獲取和設置Field的值
在熱更DLL和Unity主工程中獲取和設置Field的值跟通常C#用法沒有區別
Type t; FieldInfo fi = t.GetField("field"); object val = fi.GetValue(instance); fi.SetValue(instance, val); |
通過反射獲取Attribute標註
在熱更DLL和Unity主工程中獲取Attribute標註跟通常C#用法沒有區別
Type t; FieldInfo fi = t.GetField("field"); object[] attributeArr = fi.GetCustomAttributes(typeof(SomeAttribute), false); |
限制和注意事項
-
在Unity主工程中不能通過new T()的方式來創建熱更工程中的類型實例