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