/// <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.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 (s_cache)
                {
                    if (s_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 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 (s_cache)
                {
                    s_cache[info] = res;
                }
            }

            return(res);
        }
Beispiel #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 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.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 (s_cache)
                {
                    if (s_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 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 (s_cache)
                {
                    s_cache[info] = res;
                }
            }

            return res;
        }
Beispiel #3
0
        public static CallInstruction Create(MethodInfo info, ParameterInfo[] parameters)
        {
            CallInstruction instruction;
            int             length = parameters.Length;

            if (!info.IsStatic)
            {
                length++;
            }
            if (((info.DeclaringType != null) && info.DeclaringType.IsArray) && ((info.Name == "Get") || (info.Name == "Set")))
            {
                return(GetArrayAccessor(info, length));
            }
            if ((info is DynamicMethod) || (!info.IsStatic && info.DeclaringType.IsValueType))
            {
                return(new MethodInfoCallInstruction(info, length));
            }
            if (length >= 10)
            {
                return(new MethodInfoCallInstruction(info, length));
            }
            foreach (ParameterInfo info2 in parameters)
            {
                if (info2.ParameterType.IsByRef)
                {
                    return(new MethodInfoCallInstruction(info, length));
                }
            }
            if (ShouldCache(info))
            {
                lock (_cache)
                {
                    if (_cache.TryGetValue(info, out instruction))
                    {
                        return(instruction);
                    }
                }
            }
            try
            {
                if (length < 3)
                {
                    instruction = FastCreate(info, parameters);
                }
                else
                {
                    instruction = SlowCreate(info, parameters);
                }
            }
            catch (TargetInvocationException exception)
            {
                if (!(exception.InnerException is NotSupportedException))
                {
                    throw;
                }
                instruction = new MethodInfoCallInstruction(info, length);
            }
            catch (NotSupportedException)
            {
                instruction = new MethodInfoCallInstruction(info, length);
            }
            if (ShouldCache(info))
            {
                lock (_cache)
                {
                    _cache[info] = instruction;
                }
            }
            return(instruction);
        }