PageRenderTime 53ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/Microsoft.Scripting/Utils/ReflectionUtils.cs

https://bitbucket.org/stefanrusek/xronos
C# | 304 lines | 220 code | 48 blank | 36 comment | 64 complexity | 272a14a22e344ba99760a3883296db7c 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. #if CODEPLEX_40
  16. using System;
  17. #else
  18. using System; using Microsoft;
  19. #endif
  20. using System.Collections.Generic;
  21. using System.Diagnostics;
  22. #if CODEPLEX_40
  23. using System.Linq.Expressions;
  24. #else
  25. using Microsoft.Linq.Expressions;
  26. #endif
  27. using System.Reflection;
  28. using System.Reflection.Emit;
  29. using System.Text;
  30. #if CODEPLEX_40
  31. using System.Dynamic;
  32. #else
  33. using Microsoft.Scripting;
  34. #endif
  35. namespace Microsoft.Scripting.Utils {
  36. public static class ReflectionUtils {
  37. // Generic type names have the arity (number of generic type paramters) appended at the end.
  38. // For eg. the mangled name of System.List<T> is "List`1". This mangling is done to enable multiple
  39. // generic types to exist as long as they have different arities.
  40. public const char GenericArityDelimiter = '`';
  41. #if SILVERLIGHT
  42. public static bool IsNested(Type t) {
  43. return t.DeclaringType != null;
  44. }
  45. #else
  46. public static bool IsNested(Type t) { return t.IsNested; }
  47. #endif
  48. public static StringBuilder FormatSignature(StringBuilder result, MethodBase method) {
  49. ContractUtils.RequiresNotNull(result, "result");
  50. ContractUtils.RequiresNotNull(method, "method");
  51. MethodInfo methodInfo = method as MethodInfo;
  52. if (methodInfo != null) {
  53. FormatTypeName(result, methodInfo.ReturnType);
  54. result.Append(' ');
  55. }
  56. MethodBuilder builder = method as MethodBuilder;
  57. if (builder != null) {
  58. result.Append(builder.Signature);
  59. return result;
  60. }
  61. ConstructorBuilder cb = method as ConstructorBuilder;
  62. if (cb != null) {
  63. result.Append(cb.Signature);
  64. return result;
  65. }
  66. FormatTypeName(result, method.DeclaringType);
  67. result.Append("::");
  68. result.Append(method.Name);
  69. if (!method.IsConstructor) {
  70. FormatTypeArgs(result, method.GetGenericArguments());
  71. }
  72. result.Append("(");
  73. if (!method.ContainsGenericParameters) {
  74. ParameterInfo[] ps = method.GetParameters();
  75. for (int i = 0; i < ps.Length; i++) {
  76. if (i > 0) result.Append(", ");
  77. FormatTypeName(result, ps[i].ParameterType);
  78. if (!System.String.IsNullOrEmpty(ps[i].Name)) {
  79. result.Append(" ");
  80. result.Append(ps[i].Name);
  81. }
  82. }
  83. } else {
  84. result.Append("?");
  85. }
  86. result.Append(")");
  87. return result;
  88. }
  89. public static StringBuilder FormatTypeName(StringBuilder result, Type type) {
  90. Assert.NotNull(result, type);
  91. if (type.IsGenericType) {
  92. string genericName = type.GetGenericTypeDefinition().FullName.Replace('+', '.');
  93. int tickIndex = genericName.IndexOf('`');
  94. result.Append(tickIndex != -1 ? genericName.Substring(0, tickIndex) : genericName);
  95. FormatTypeArgs(result, type.GetGenericArguments());
  96. } else if (type.IsGenericParameter) {
  97. result.Append(type.Name);
  98. } else {
  99. result.Append(type.FullName.Replace('+', '.'));
  100. }
  101. return result;
  102. }
  103. public static StringBuilder FormatTypeArgs(StringBuilder result, Type[] types) {
  104. Assert.NotNull(result, types);
  105. if (types.Length > 0) {
  106. result.Append("<");
  107. for (int i = 0; i < types.Length; i++) {
  108. if (i > 0) result.Append(", ");
  109. FormatTypeName(result, types[i]);
  110. }
  111. result.Append(">");
  112. }
  113. return result;
  114. }
  115. public static T CreateInstance<T>(Type actualType, params object[] args) {
  116. Type type = typeof(T);
  117. Debug.Assert(type.IsAssignableFrom(actualType));
  118. try {
  119. return (T)Activator.CreateInstance(actualType, args);
  120. } catch (TargetInvocationException e) {
  121. throw new InvalidImplementationException(Strings.InvalidCtorImplementation(actualType, e.InnerException.Message), e.InnerException);
  122. } catch (Exception e) {
  123. throw new InvalidImplementationException(Strings.InvalidCtorImplementation(actualType, e.Message), e);
  124. }
  125. }
  126. public static object InvokeDelegate(Delegate d, params object[] args) {
  127. #if SILVERLIGHT
  128. // delegates:
  129. // - close (target != null)
  130. // - static (target becomes the first argument)
  131. // - instance (no argument shuffling)
  132. // - open (target == null)
  133. // - static (no argument shuffling)
  134. // - instance (first argument becomes the target)
  135. object target = d.Target;
  136. if (d.Method.IsStatic && target != null) {
  137. // closed static -> target needs to be passed as the first arg:
  138. object[] new_args = new object[args.Length + 1];
  139. args.CopyTo(new_args, 1);
  140. new_args[0] = d.Target;
  141. target = null;
  142. args = new_args;
  143. } else if (!d.Method.IsStatic && target == null) {
  144. // open instance -> the first arg is the target:
  145. object[] new_args = new object[args.Length - 1];
  146. System.Array.Copy(args, 1, new_args, 0, new_args.Length);
  147. target = args[0];
  148. args = new_args;
  149. }
  150. return d.Method.Invoke(target, args);
  151. #else
  152. return d.DynamicInvoke(args);
  153. #endif
  154. }
  155. /// <summary>
  156. /// Creates an open delegate for the given (dynamic)method.
  157. /// </summary>
  158. public static Delegate CreateDelegate(MethodInfo methodInfo, Type delegateType) {
  159. ContractUtils.RequiresNotNull(delegateType, "delegateType");
  160. ContractUtils.RequiresNotNull(methodInfo, "methodInfo");
  161. DynamicMethod dm = methodInfo as DynamicMethod;
  162. if (dm != null) {
  163. return dm.CreateDelegate(delegateType);
  164. } else {
  165. return Delegate.CreateDelegate(delegateType, methodInfo);
  166. }
  167. }
  168. /// <summary>
  169. /// Creates a closed delegate for the given (dynamic)method.
  170. /// </summary>
  171. public static Delegate CreateDelegate(MethodInfo methodInfo, Type delegateType, object target) {
  172. ContractUtils.RequiresNotNull(methodInfo, "methodInfo");
  173. ContractUtils.RequiresNotNull(delegateType, "delegateType");
  174. DynamicMethod dm = methodInfo as DynamicMethod;
  175. if (dm != null) {
  176. return dm.CreateDelegate(delegateType, target);
  177. } else {
  178. return Delegate.CreateDelegate(delegateType, target, methodInfo);
  179. }
  180. }
  181. public static void GetDelegateSignature(Type delegateType, out ParameterInfo[] parameterInfos, out ParameterInfo returnInfo) {
  182. ContractUtils.RequiresNotNull(delegateType, "delegateType");
  183. MethodInfo invokeMethod = delegateType.GetMethod("Invoke");
  184. ContractUtils.Requires(invokeMethod != null, "delegateType", Strings.InvalidDelegate);
  185. parameterInfos = invokeMethod.GetParameters();
  186. returnInfo = invokeMethod.ReturnParameter;
  187. }
  188. public static MethodInfo[] GetMethodInfos(Delegate[] delegates) {
  189. MethodInfo[] result = new MethodInfo[delegates.Length];
  190. for (int i = 0; i < delegates.Length; i++) result[i] = delegates[i].Method;
  191. return result;
  192. }
  193. public static MethodBase[] GetMethodInfos(MemberInfo[] members) {
  194. return ArrayUtils.ConvertAll<MemberInfo, MethodBase>(
  195. members,
  196. delegate(MemberInfo inp) { return (MethodBase)inp; });
  197. }
  198. public static Type[] GetParameterTypes(ParameterInfo[] parameterInfos) {
  199. Type[] result = new Type[parameterInfos.Length];
  200. for (int i = 0; i < parameterInfos.Length; i++) {
  201. result[i] = parameterInfos[i].ParameterType;
  202. }
  203. return result;
  204. }
  205. public static bool SignatureEquals(MethodInfo method, params Type[] requiredSignature) {
  206. ContractUtils.RequiresNotNull(method, "method");
  207. Type[] actualTypes = ReflectionUtils.GetParameterTypes(method.GetParameters());
  208. Debug.Assert(actualTypes.Length == requiredSignature.Length - 1);
  209. int i = 0;
  210. while (i < actualTypes.Length) {
  211. if (actualTypes[i] != requiredSignature[i]) return false;
  212. i++;
  213. }
  214. return method.ReturnType == requiredSignature[i];
  215. }
  216. internal static string ToValidTypeName(string str) {
  217. if (String.IsNullOrEmpty(str)) {
  218. return "_";
  219. }
  220. StringBuilder sb = new StringBuilder(str);
  221. for (int i = 0; i < str.Length; i++) {
  222. if (str[i] == '\0' || str[i] == '.' || str[i] == '*' || str[i] == '+' || str[i] == '[' || str[i] == ']' || str[i] == '\\') {
  223. sb[i] = '_';
  224. }
  225. }
  226. return sb.ToString();
  227. }
  228. /// <summary>
  229. /// Like Type.GetInterfaces, but only returns the interfaces implemented by this type
  230. /// and not its parents.
  231. /// </summary>
  232. public static List<Type> GetDeclaredInterfaces(Type type) {
  233. IList<Type> baseInterfaces = (type.BaseType != null) ? type.BaseType.GetInterfaces() : Type.EmptyTypes;
  234. List<Type> interfaces = new List<Type>();
  235. foreach (Type iface in type.GetInterfaces()) {
  236. if (!baseInterfaces.Contains(iface)) {
  237. interfaces.Add(iface);
  238. }
  239. }
  240. return interfaces;
  241. }
  242. public static string GetNormalizedTypeName(Type type) {
  243. string name = type.Name;
  244. if (type.IsGenericType) {
  245. return GetNormalizedTypeName(name);
  246. }
  247. return name;
  248. }
  249. public static string GetNormalizedTypeName(string typeName) {
  250. Debug.Assert(typeName.IndexOf(Type.Delimiter) == -1); // This is the simple name, not the full name
  251. int backtick = typeName.IndexOf(ReflectionUtils.GenericArityDelimiter);
  252. if (backtick != -1) return typeName.Substring(0, backtick);
  253. return typeName;
  254. }
  255. }
  256. }