Example #1
0
        /// <summary>
        /// Creates a new ReflectedCaller which can be used to quickly invoke the provided MethodInfo.
        /// </summary>
        public static CallInstruction Create(MethodInfo info, ParameterInfo[] parameters)
        {
            int argumentCount = parameters.Length;

            if (!info.IsStatic)
            {
                argumentCount++;
            }

            // A workaround for CLR bug #796414 (Unable to create delegates for Array.Get/Set):
            // T[]::Address - not supported by ETs due to T& return value
            if (info.DeclaringType != null && info.DeclaringType.IsArray && (info.Name == "Get" || info.Name == "Set"))
            {
                return(GetArrayAccessor(info, argumentCount));
            }

            if (info is DynamicMethod || !info.IsStatic && info.DeclaringType.IsValueType)
            {
                return(new MethodInfoCallInstruction(info, argumentCount));
            }

            if (argumentCount >= MaxHelpers)
            {
                // no delegate for this size, fallback to reflection invoke
                return(new MethodInfoCallInstruction(info, argumentCount));
            }

            foreach (ParameterInfo pi in parameters)
            {
                if (pi.ParameterType.IsByRef)
                {
                    // we don't support ref args via generics.
                    return(new MethodInfoCallInstruction(info, argumentCount));
                }
            }

            // see if we've created one w/ a delegate
            CallInstruction res;

            if (ShouldCache(info))
            {
                lock (_cache) {
                    if (_cache.TryGetValue(info, out res))
                    {
                        return(res);
                    }
                }
            }

            // create it
            try {
                if (argumentCount < MaxArgs)
                {
                    res = FastCreate(info, parameters);
                }
                else
                {
                    res = SlowCreate(info, parameters);
                }
            } catch (TargetInvocationException tie) {
                if (!(tie.InnerException is NotSupportedException))
                {
                    throw;
                }

                res = new MethodInfoCallInstruction(info, argumentCount);
            } catch (NotSupportedException) {
                // if Delegate.CreateDelegate can't handle the method fallback to
                // the slow reflection version.  For example this can happen w/
                // a generic method defined on an interface and implemented on a class.
                res = new MethodInfoCallInstruction(info, argumentCount);
            }

            // cache it for future users if it's a reasonable method to cache
            if (ShouldCache(info))
            {
                lock (_cache) {
                    _cache[info] = res;
                }
            }

            return(res);
        }
Example #2
0
        /// <summary>
        /// Creates a new ReflectedCaller which can be used to quickly invoke the provided MethodInfo.
        /// </summary>
        internal static CallInstruction Create(MethodInfo info, ParameterInfo[] parameters) {
            int argumentCount = parameters.Length;
            if (!info.IsStatic) {
                argumentCount++;
            }

            // A workaround for CLR bug #796414 (Unable to create delegates for Array.Get/Set):
            // T[]::Address - not supported by ETs due to T& return value
            if (info.DeclaringType != null && info.DeclaringType.IsArray && (info.Name == "Get" || info.Name == "Set")) {
                return GetArrayAccessor(info, argumentCount);
            }

            if (info is DynamicMethod || !info.IsStatic && info.DeclaringType.IsValueType) {
                return new MethodInfoCallInstruction(info, argumentCount);
            }

            if (argumentCount >= MaxHelpers) {
                // no delegate for this size, fallback to reflection invoke
                return new MethodInfoCallInstruction(info, argumentCount);
            }

            foreach (ParameterInfo pi in parameters) {
                if (pi.ParameterType.IsByRef) {
                    // we don't support ref args via generics.
                    return new MethodInfoCallInstruction(info, argumentCount);
                }
            }

            // see if we've created one w/ a delegate
            CallInstruction res;
            if (ShouldCache(info)) {
                lock (_cache) {
                    if (_cache.TryGetValue(info, out res)) {
                        return res;
                    }
                }
            }

            // create it 
            try {
                if (argumentCount < MaxArgs) {
                    res = FastCreate(info, parameters);
                } else {
                    res = SlowCreate(info, parameters);
                }
            } catch (TargetInvocationException tie) {
                if (!(tie.InnerException is NotSupportedException)) {
                    throw;
                }

                res = new MethodInfoCallInstruction(info, argumentCount);
            } catch (NotSupportedException) {
                // if Delegate.CreateDelegate can't handle the method fallback to 
                // the slow reflection version.  For example this can happen w/ 
                // a generic method defined on an interface and implemented on a class.
                res = new MethodInfoCallInstruction(info, argumentCount);
            }

            // cache it for future users if it's a reasonable method to cache
            if (ShouldCache(info)) {
                lock (_cache) {
                    _cache[info] = res;
                }
            }

            return res;            
        }