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