Exemplo n.º 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 behavior (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);
            }

            return new MethodInfoCallInstruction(info, argumentCount);
#if FEATURE_DLG_INVOKE

            if (!info.IsStatic && info.DeclaringType.GetTypeInfo().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 FEATURE_FAST_CREATE
                if (argumentCount < MaxArgs)
                {
                    res = FastCreate(info, parameters);
                }
                else
#endif
                {
                    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 or 
                // a virtual generic method.
                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;
#endif
        }
Exemplo n.º 2
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 behavior (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 !FEATURE_DLG_INVOKE
            return(new MethodInfoCallInstruction(info, argumentCount));
#else
            if (!info.IsStatic && info.DeclaringType !.IsValueType)
            {
                return(new MethodInfoCallInstruction(info, argumentCount));
            }

            if (argumentCount >= MaxHelpers)
            {
                // no delegate for this size, fall back 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))
            {
                if (s_cache.TryGetValue(info, out res))
                {
                    return(res);
                }
            }

            // create it
            try
            {
#if FEATURE_FAST_CREATE
                if (argumentCount < MaxArgs)
                {
                    res = FastCreate(info, parameters);
                }
                else
#endif
                {
                    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 fall back to
                // the slow reflection version.  For example this can happen w/
                // a generic method defined on an interface and implemented on a class or
                // a virtual generic method.
                res = new MethodInfoCallInstruction(info, argumentCount);
            }

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

            return(res);
#endif
        }