PageRenderTime 232ms CodeModel.GetById 40ms app.highlight 49ms RepoModel.GetById 102ms app.codeStats 11ms

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