ToLuaInjectionHelper.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. #if ENABLE_LUA_INJECTION
  2. using System;
  3. using System.Collections.Generic;
  4. using Mono.Cecil;
  5. using Mono.Cecil.Cil;
  6. using Unity.CecilTools;
  7. using System.Linq;
  8. [Flags]
  9. public enum InjectFilter
  10. {
  11. IgnoreConstructor = 1,
  12. IgnoreProperty = 1 << 1,
  13. IgnoreGeneric = 1 << 2,
  14. IgnoreNoToLuaAttr = 1 << 3,
  15. }
  16. public static class ToLuaInjectionHelper
  17. {
  18. public static string GetArrayRank(TypeReference t)
  19. {
  20. ArrayType type = t as ArrayType;
  21. int count = type.Rank;
  22. if (count == 1)
  23. {
  24. return "[]";
  25. }
  26. using (CString.Block())
  27. {
  28. CString sb = CString.Alloc(64);
  29. sb.Append('[');
  30. for (int i = 1; i < count; i++)
  31. {
  32. sb.Append(',');
  33. }
  34. sb.Append(']');
  35. return sb.ToString();
  36. }
  37. }
  38. public static string GetTypeName(TypeReference t, bool bFull = false)
  39. {
  40. if (t.IsArray)
  41. {
  42. string str = GetTypeName(ElementType.For(t));
  43. str += GetArrayRank(t);
  44. return str;
  45. }
  46. else if (t.IsByReference)
  47. {
  48. //t = t.GetElementType();
  49. return GetTypeName(ElementType.For(t)) + "&";
  50. }
  51. else if (t.IsGenericInstance)
  52. {
  53. return GetGenericName(t, bFull);
  54. }
  55. else if (t.MetadataType == MetadataType.Void)
  56. {
  57. return "void";
  58. }
  59. else
  60. {
  61. string name = GetPrimitiveTypeStr(t, bFull);
  62. return name.Replace('+', '.');
  63. }
  64. }
  65. public static string[] GetGenericName(Mono.Collections.Generic.Collection<TypeReference> types, int offset, int count, bool bFull)
  66. {
  67. string[] results = new string[count];
  68. for (int i = 0; i < count; i++)
  69. {
  70. int pos = i + offset;
  71. if (types[pos].IsGenericInstance)
  72. {
  73. results[i] = GetGenericName(types[pos], bFull);
  74. }
  75. else
  76. {
  77. results[i] = GetTypeName(types[pos]);
  78. }
  79. }
  80. return results;
  81. }
  82. public static MethodReference GetBaseMethodInstance(this MethodDefinition target)
  83. {
  84. MethodDefinition baseMethodDef = null;
  85. var baseType = target.DeclaringType.BaseType;
  86. while (baseType != null)
  87. {
  88. if (baseType.MetadataToken.TokenType == TokenType.TypeRef)
  89. {
  90. break;
  91. }
  92. var baseTypeDef = baseType.Resolve();
  93. baseMethodDef = MetadataResolver.GetMethod(baseTypeDef.Methods, target);
  94. if (baseMethodDef != null && !baseMethodDef.IsAbstract)
  95. {
  96. if (baseType.IsGenericInstance)
  97. {
  98. MethodReference baseMethodRef = baseType.Module.Import(baseMethodDef);
  99. var baseTypeInstance = (GenericInstanceType)baseType;
  100. return baseMethodRef.MakeGenericMethod(baseTypeInstance.GenericArguments.ToArray());
  101. }
  102. break;
  103. }
  104. else baseMethodDef = null;
  105. baseType = baseTypeDef.BaseType;
  106. }
  107. return baseMethodDef;
  108. }
  109. public static bool IsGenericTypeDefinition(this TypeReference type)
  110. {
  111. if (type.HasGenericParameters)
  112. {
  113. return true;
  114. }
  115. else if (type.IsByReference || type.IsArray)
  116. {
  117. return ElementType.For(type).IsGenericTypeDefinition();
  118. }
  119. else if (type.IsNested)
  120. {
  121. var parent = type.DeclaringType;
  122. while (parent != null)
  123. {
  124. if (parent.IsGenericTypeDefinition())
  125. {
  126. return true;
  127. }
  128. if (parent.IsNested)
  129. {
  130. parent = parent.DeclaringType;
  131. }
  132. else
  133. {
  134. break;
  135. }
  136. }
  137. }
  138. return type.IsGenericParameter;
  139. }
  140. public static bool IsGenericMethodDefinition(this MethodDefinition md)
  141. {
  142. if (md.HasGenericParameters
  143. #if UNITY_5_2 || UNITY_5_3 || UNITY_5_3_OR_NEWER
  144. || md.ContainsGenericParameter
  145. #endif
  146. )
  147. {
  148. return true;
  149. }
  150. if (md.DeclaringType != null && md.DeclaringType.IsGenericTypeDefinition())
  151. {
  152. return true;
  153. }
  154. if (md.ReturnType.IsGenericTypeDefinition())
  155. {
  156. return true;
  157. }
  158. foreach (var param in md.Parameters)
  159. {
  160. if (param.ParameterType.IsGenericTypeDefinition())
  161. {
  162. return true;
  163. }
  164. }
  165. return false;
  166. }
  167. public static bool GotPassedByReferenceParam(this MethodReference md)
  168. {
  169. return md.Parameters.Any(param => param.ParameterType.IsByReference);
  170. }
  171. public static TypeReference MakeGenericType(this TypeReference self, params TypeReference[] arguments)
  172. {
  173. if (self.GenericParameters.Count != arguments.Length)
  174. {
  175. throw new ArgumentException();
  176. }
  177. var instance = new GenericInstanceType(self);
  178. foreach (var argument in arguments)
  179. {
  180. instance.GenericArguments.Add(argument);
  181. }
  182. return instance;
  183. }
  184. public static MethodReference MakeGenericMethod(this MethodReference self, params TypeReference[] arguments)
  185. {
  186. if (self.DeclaringType.IsGenericTypeDefinition())
  187. {
  188. return self.CloneMethod(self.DeclaringType.MakeGenericType(arguments));
  189. }
  190. else
  191. {
  192. var genericInstanceMethod = new GenericInstanceMethod(self.CloneMethod());
  193. foreach (var argument in arguments)
  194. {
  195. genericInstanceMethod.GenericArguments.Add(argument);
  196. }
  197. return genericInstanceMethod;
  198. }
  199. }
  200. public static MethodReference CloneMethod(this MethodReference self, TypeReference declaringType = null)
  201. {
  202. var reference = new MethodReference(self.Name, self.ReturnType, declaringType ?? self.DeclaringType)
  203. {
  204. HasThis = self.HasThis,
  205. ExplicitThis = self.ExplicitThis,
  206. CallingConvention = self.CallingConvention,
  207. };
  208. foreach (ParameterDefinition parameterDef in self.Parameters)
  209. {
  210. reference.Parameters.Add(new ParameterDefinition(parameterDef.Name, parameterDef.Attributes, parameterDef.ParameterType));
  211. }
  212. foreach (GenericParameter genParamDef in self.GenericParameters)
  213. {
  214. reference.GenericParameters.Add(new GenericParameter(genParamDef.Name, reference));
  215. }
  216. return reference;
  217. }
  218. public static bool IsEnumerator(this MethodDefinition md)
  219. {
  220. return md.ReturnType.FullName == "System.Collections.IEnumerator";
  221. }
  222. public static bool ReturnVoid(this MethodDefinition target)
  223. {
  224. return target.ReturnType.FullName == "System.Void";
  225. }
  226. public static bool HasFlag(this LuaInterface.InjectType flag, LuaInterface.InjectType destFlag)
  227. {
  228. return (flag & destFlag) == destFlag;
  229. }
  230. public static bool HasFlag(this LuaInterface.InjectType flag, byte destFlag)
  231. {
  232. return ((byte)flag & destFlag) == destFlag;
  233. }
  234. public static bool HasFlag(this InjectFilter flag, InjectFilter destFlag)
  235. {
  236. return (flag & destFlag) == destFlag;
  237. }
  238. public static string GetPrimitiveTypeStr(TypeReference t, bool bFull)
  239. {
  240. switch (t.MetadataType)
  241. {
  242. case MetadataType.Single:
  243. return "float";
  244. case MetadataType.String:
  245. return "string";
  246. case MetadataType.Int32:
  247. return "int";
  248. case MetadataType.Double:
  249. return "double";
  250. case MetadataType.Boolean:
  251. return "bool";
  252. case MetadataType.UInt32:
  253. return "uint";
  254. case MetadataType.SByte:
  255. return "sbyte";
  256. case MetadataType.Byte:
  257. return "byte";
  258. case MetadataType.Int16:
  259. return "short";
  260. case MetadataType.UInt16:
  261. return "ushort";
  262. case MetadataType.Char:
  263. return "char";
  264. case MetadataType.Int64:
  265. return "long";
  266. case MetadataType.UInt64:
  267. return "ulong";
  268. case MetadataType.Object:
  269. return "object";
  270. default:
  271. return bFull ? t.FullName.Replace("/", "+") : t.Name;
  272. }
  273. }
  274. static string CombineTypeStr(string space, string name)
  275. {
  276. if (string.IsNullOrEmpty(space))
  277. {
  278. return name;
  279. }
  280. else
  281. {
  282. return space + "." + name;
  283. }
  284. }
  285. static string GetGenericName(TypeReference t, bool bFull)
  286. {
  287. GenericInstanceType type = t as GenericInstanceType;
  288. var gArgs = type.GenericArguments;
  289. string typeName = bFull ? t.FullName.Replace("/", "+") : t.Name;
  290. int count = gArgs.Count;
  291. int pos = typeName.IndexOf("[");
  292. if (pos > 0)
  293. {
  294. typeName = typeName.Substring(0, pos);
  295. }
  296. string str = null;
  297. string name = null;
  298. int offset = 0;
  299. pos = typeName.IndexOf("+");
  300. while (pos > 0)
  301. {
  302. str = typeName.Substring(0, pos);
  303. typeName = typeName.Substring(pos + 1);
  304. pos = str.IndexOf('`');
  305. if (pos > 0)
  306. {
  307. count = (int)(str[pos + 1] - '0');
  308. str = str.Substring(0, pos);
  309. str += "<" + string.Join(",", GetGenericName(gArgs, offset, count, bFull)) + ">";
  310. offset += count;
  311. }
  312. name = CombineTypeStr(name, str);
  313. pos = typeName.IndexOf("+");
  314. }
  315. str = typeName;
  316. if (offset < gArgs.Count)
  317. {
  318. pos = str.IndexOf('`');
  319. count = (int)(str[pos + 1] - '0');
  320. str = str.Substring(0, pos);
  321. str += "<" + string.Join(",", GetGenericName(gArgs, offset, count, bFull)) + ">";
  322. }
  323. return CombineTypeStr(name, str);
  324. }
  325. public static void Foreach<T>(this IEnumerable<T> source, Action<T> callback)
  326. {
  327. foreach (var val in source)
  328. {
  329. callback(val);
  330. }
  331. }
  332. }
  333. #endif