/// <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); }
/// <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; }