PageRenderTime 65ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/Merlin/Main/Runtime/Microsoft.Dynamic/Utils/ReflectionUtils.cs

https://github.com/xerxesb/ironruby
C# | 304 lines | 227 code | 45 blank | 32 comment | 61 complexity | f574e6c91428e595c116b7054c128cfe MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Microsoft Public License, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Diagnostics;
  18. using System.Reflection;
  19. using System.Reflection.Emit;
  20. using System.Runtime.CompilerServices;
  21. using System.Text;
  22. using Microsoft.Scripting.Generation;
  23. namespace Microsoft.Scripting.Utils {
  24. public static class ReflectionUtils {
  25. // Generic type names have the arity (number of generic type paramters) appended at the end.
  26. // For eg. the mangled name of System.List<T> is "List`1". This mangling is done to enable multiple
  27. // generic types to exist as long as they have different arities.
  28. public const char GenericArityDelimiter = '`';
  29. #if SILVERLIGHT
  30. public static bool IsNested(Type t) {
  31. return t.DeclaringType != null;
  32. }
  33. #else
  34. public static bool IsNested(Type t) { return t.IsNested; }
  35. #endif
  36. public static StringBuilder FormatSignature(StringBuilder result, MethodBase method) {
  37. return FormatSignature(result, method, (t) => t.FullName);
  38. }
  39. public static StringBuilder FormatSignature(StringBuilder result, MethodBase method, Func<Type, string> nameDispenser) {
  40. ContractUtils.RequiresNotNull(result, "result");
  41. ContractUtils.RequiresNotNull(method, "method");
  42. ContractUtils.RequiresNotNull(nameDispenser, "nameDispenser");
  43. MethodInfo methodInfo = method as MethodInfo;
  44. if (methodInfo != null) {
  45. FormatTypeName(result, methodInfo.ReturnType, nameDispenser);
  46. result.Append(' ');
  47. }
  48. MethodBuilder builder = method as MethodBuilder;
  49. if (builder != null) {
  50. result.Append(builder.Signature);
  51. return result;
  52. }
  53. ConstructorBuilder cb = method as ConstructorBuilder;
  54. if (cb != null) {
  55. result.Append(cb.Signature);
  56. return result;
  57. }
  58. FormatTypeName(result, method.DeclaringType, nameDispenser);
  59. result.Append("::");
  60. result.Append(method.Name);
  61. if (!method.IsConstructor) {
  62. FormatTypeArgs(result, method.GetGenericArguments(), nameDispenser);
  63. }
  64. result.Append("(");
  65. if (!method.ContainsGenericParameters) {
  66. ParameterInfo[] ps = method.GetParameters();
  67. for (int i = 0; i < ps.Length; i++) {
  68. if (i > 0) result.Append(", ");
  69. FormatTypeName(result, ps[i].ParameterType, nameDispenser);
  70. if (!System.String.IsNullOrEmpty(ps[i].Name)) {
  71. result.Append(" ");
  72. result.Append(ps[i].Name);
  73. }
  74. }
  75. } else {
  76. result.Append("?");
  77. }
  78. result.Append(")");
  79. return result;
  80. }
  81. public static StringBuilder FormatTypeName(StringBuilder result, Type type) {
  82. return FormatTypeName(result, type, (t) => t.FullName);
  83. }
  84. public static StringBuilder FormatTypeName(StringBuilder result, Type type, Func<Type, string> nameDispenser) {
  85. ContractUtils.RequiresNotNull(result, "result");
  86. ContractUtils.RequiresNotNull(type, "type");
  87. ContractUtils.RequiresNotNull(nameDispenser, "nameDispenser");
  88. if (type.IsGenericType) {
  89. Type genType = type.GetGenericTypeDefinition();
  90. string genericName = nameDispenser(genType).Replace('+', '.');
  91. int tickIndex = genericName.IndexOf('`');
  92. result.Append(tickIndex != -1 ? genericName.Substring(0, tickIndex) : genericName);
  93. Type[] typeArgs = type.GetGenericArguments();
  94. if (type.IsGenericTypeDefinition) {
  95. result.Append('<');
  96. result.Append(',', typeArgs.Length - 1);
  97. result.Append('>');
  98. } else {
  99. FormatTypeArgs(result, typeArgs, nameDispenser);
  100. }
  101. } else if (type.IsGenericParameter) {
  102. result.Append(type.Name);
  103. } else {
  104. string name = type.FullName;
  105. // cut namespace off:
  106. result.Append(nameDispenser(type).Replace('+', '.'));
  107. }
  108. return result;
  109. }
  110. public static StringBuilder FormatTypeArgs(StringBuilder result, Type[] types) {
  111. return FormatTypeArgs(result, types, (t) => t.FullName);
  112. }
  113. public static StringBuilder FormatTypeArgs(StringBuilder result, Type[] types, Func<Type, string> nameDispenser) {
  114. ContractUtils.RequiresNotNull(result, "result");
  115. ContractUtils.RequiresNotNullItems(types, "types");
  116. ContractUtils.RequiresNotNull(nameDispenser, "nameDispenser");
  117. if (types.Length > 0) {
  118. result.Append("<");
  119. for (int i = 0; i < types.Length; i++) {
  120. if (i > 0) result.Append(", ");
  121. FormatTypeName(result, types[i], nameDispenser);
  122. }
  123. result.Append(">");
  124. }
  125. return result;
  126. }
  127. /// <summary>
  128. /// Creates an open delegate for the given (dynamic)method.
  129. /// </summary>
  130. public static Delegate CreateDelegate(MethodInfo methodInfo, Type delegateType) {
  131. ContractUtils.RequiresNotNull(delegateType, "delegateType");
  132. ContractUtils.RequiresNotNull(methodInfo, "methodInfo");
  133. DynamicMethod dm = methodInfo as DynamicMethod;
  134. if (dm != null) {
  135. return dm.CreateDelegate(delegateType);
  136. } else {
  137. return Delegate.CreateDelegate(delegateType, methodInfo);
  138. }
  139. }
  140. /// <summary>
  141. /// Creates a closed delegate for the given (dynamic)method.
  142. /// </summary>
  143. public static Delegate CreateDelegate(MethodInfo methodInfo, Type delegateType, object target) {
  144. ContractUtils.RequiresNotNull(methodInfo, "methodInfo");
  145. ContractUtils.RequiresNotNull(delegateType, "delegateType");
  146. DynamicMethod dm = methodInfo as DynamicMethod;
  147. if (dm != null) {
  148. return dm.CreateDelegate(delegateType, target);
  149. } else {
  150. return Delegate.CreateDelegate(delegateType, target, methodInfo);
  151. }
  152. }
  153. public static void GetDelegateSignature(Type delegateType, out ParameterInfo[] parameterInfos, out ParameterInfo returnInfo) {
  154. ContractUtils.RequiresNotNull(delegateType, "delegateType");
  155. MethodInfo invokeMethod = delegateType.GetMethod("Invoke");
  156. ContractUtils.Requires(invokeMethod != null, "delegateType", Strings.InvalidDelegate);
  157. parameterInfos = invokeMethod.GetParameters();
  158. returnInfo = invokeMethod.ReturnParameter;
  159. }
  160. public static MethodInfo[] GetMethodInfos(Delegate[] delegates) {
  161. MethodInfo[] result = new MethodInfo[delegates.Length];
  162. for (int i = 0; i < delegates.Length; i++) result[i] = delegates[i].Method;
  163. return result;
  164. }
  165. public static MethodBase[] GetMethodInfos(MemberInfo[] members) {
  166. return ArrayUtils.ConvertAll<MemberInfo, MethodBase>(
  167. members,
  168. delegate(MemberInfo inp) { return (MethodBase)inp; });
  169. }
  170. public static Type[] GetParameterTypes(ParameterInfo[] parameterInfos) {
  171. Type[] result = new Type[parameterInfos.Length];
  172. for (int i = 0; i < parameterInfos.Length; i++) {
  173. result[i] = parameterInfos[i].ParameterType;
  174. }
  175. return result;
  176. }
  177. public static bool SignatureEquals(MethodInfo method, params Type[] requiredSignature) {
  178. ContractUtils.RequiresNotNull(method, "method");
  179. Type[] actualTypes = ReflectionUtils.GetParameterTypes(method.GetParameters());
  180. Debug.Assert(actualTypes.Length == requiredSignature.Length - 1);
  181. int i = 0;
  182. while (i < actualTypes.Length) {
  183. if (actualTypes[i] != requiredSignature[i]) return false;
  184. i++;
  185. }
  186. return method.ReturnType == requiredSignature[i];
  187. }
  188. internal static string ToValidTypeName(string str) {
  189. if (String.IsNullOrEmpty(str)) {
  190. return "_";
  191. }
  192. StringBuilder sb = new StringBuilder(str);
  193. for (int i = 0; i < str.Length; i++) {
  194. if (str[i] == '\0' || str[i] == '.' || str[i] == '*' || str[i] == '+' || str[i] == '[' || str[i] == ']' || str[i] == '\\') {
  195. sb[i] = '_';
  196. }
  197. }
  198. return sb.ToString();
  199. }
  200. /// <summary>
  201. /// Like Type.GetInterfaces, but only returns the interfaces implemented by this type
  202. /// and not its parents.
  203. /// </summary>
  204. public static List<Type> GetDeclaredInterfaces(Type type) {
  205. IList<Type> baseInterfaces = (type.BaseType != null) ? type.BaseType.GetInterfaces() : Type.EmptyTypes;
  206. List<Type> interfaces = new List<Type>();
  207. foreach (Type iface in type.GetInterfaces()) {
  208. if (!baseInterfaces.Contains(iface)) {
  209. interfaces.Add(iface);
  210. }
  211. }
  212. return interfaces;
  213. }
  214. public static string GetNormalizedTypeName(Type type) {
  215. string name = type.Name;
  216. if (type.IsGenericType) {
  217. return GetNormalizedTypeName(name);
  218. }
  219. return name;
  220. }
  221. public static string GetNormalizedTypeName(string typeName) {
  222. Debug.Assert(typeName.IndexOf(Type.Delimiter) == -1); // This is the simple name, not the full name
  223. int backtick = typeName.IndexOf(ReflectionUtils.GenericArityDelimiter);
  224. if (backtick != -1) return typeName.Substring(0, backtick);
  225. return typeName;
  226. }
  227. /// <summary>
  228. /// Gets a Func of CallSite, object * paramCnt, object delegate type
  229. /// that's suitable for use in a non-strongly typed call site.
  230. /// </summary>
  231. public static Type GetObjectCallSiteDelegateType(int paramCnt) {
  232. switch (paramCnt) {
  233. case 0: return typeof(Func<CallSite, object, object>);
  234. case 1: return typeof(Func<CallSite, object, object, object>);
  235. case 2: return typeof(Func<CallSite, object, object, object, object>);
  236. case 3: return typeof(Func<CallSite, object, object, object, object, object>);
  237. case 4: return typeof(Func<CallSite, object, object, object, object, object, object>);
  238. case 5: return typeof(Func<CallSite, object, object, object, object, object, object, object>);
  239. case 6: return typeof(Func<CallSite, object, object, object, object, object, object, object, object>);
  240. case 7: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object>);
  241. case 8: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object>);
  242. case 9: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object>);
  243. case 10: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object>);
  244. case 11: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object, object>);
  245. case 12: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object, object, object>);
  246. case 13: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object>);
  247. case 14: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object>);
  248. default:
  249. Type[] paramTypes = new Type[paramCnt + 2];
  250. paramTypes[0] = typeof(CallSite);
  251. paramTypes[1] = typeof(object);
  252. for (int i = 0; i < paramCnt; i++) {
  253. paramTypes[i + 2] = typeof(object);
  254. }
  255. return Snippets.Shared.DefineDelegate("InvokeDelegate" + paramCnt, typeof(object), paramTypes);
  256. }
  257. }
  258. }
  259. }