1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. 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 Apache License, Version 2.0, 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 Apache License, Version 2.0.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
16 using System.Diagnostics;
17 using System.Reflection;
19 using System.Reflection.Emit;
23 namespace System.Dynamic.Utils {
25 // Extensions on System.Type and friends
26 internal static class TypeExtensions {
29 /// Creates a closed delegate for the given (dynamic)method.
31 internal static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType, object target) {
32 Debug.Assert(methodInfo != null && delegateType != null);
34 var dm = methodInfo as DynamicMethod;
36 return dm.CreateDelegate(delegateType, target);
38 return Delegate.CreateDelegate(delegateType, target, methodInfo);
41 internal static Type GetReturnType(this MethodBase mi) {
42 return (mi.IsConstructor) ? mi.DeclaringType : ((MethodInfo)mi).ReturnType;
45 private static readonly CacheDict<MethodBase, ParameterInfo[]> _ParamInfoCache = new CacheDict<MethodBase, ParameterInfo[]>(75);
47 internal static ParameterInfo[] GetParametersCached(this MethodBase method) {
49 lock (_ParamInfoCache) {
50 if (!_ParamInfoCache.TryGetValue(method, out pis)) {
51 pis = method.GetParameters();
53 Type t = method.DeclaringType;
54 if (t != null && TypeUtils.CanCache(t)) {
55 _ParamInfoCache[method] = pis;
62 // Expression trees/compiler just use IsByRef, why do we need this?
63 // (see LambdaCompiler.EmitArguments for usage in the compiler)
64 internal static bool IsByRefParameter(this ParameterInfo pi) {
65 // not using IsIn/IsOut properties as they are not available in Silverlight:
66 if (pi.ParameterType.IsByRef) return true;
68 return (pi.Attributes & (ParameterAttributes.Out)) == ParameterAttributes.Out;
71 // Returns the matching method if the parameter types are reference
72 // assignable from the provided type arguments, otherwise null.
73 internal static MethodInfo GetMethodValidated(
76 BindingFlags bindingAttr,
79 ParameterModifier[] modifiers) {
81 var method = type.GetMethod(name, bindingAttr, binder, types, modifiers);
83 return method.MatchesArgumentTypes(types) ? method : null;
87 /// Returns true if the method's parameter types are reference assignable from
88 /// the argument types, otherwise false.
90 /// An example that can make the method return false is that
91 /// typeof(double).GetMethod("op_Equality", ..., new[] { typeof(double), typeof(int) })
92 /// returns a method with two double parameters, which doesn't match the provided
95 /// <returns></returns>
96 private static bool MatchesArgumentTypes(this MethodInfo mi, Type[] argTypes) {
97 if (mi == null || argTypes == null) {
100 var ps = mi.GetParameters();
102 if (ps.Length != argTypes.Length) {
106 for (int i = 0; i < ps.Length; i++) {
107 if (!TypeUtils.AreReferenceAssignable(ps[i].ParameterType, argTypes[i])) {