private static Func <LightLambda, Delegate> GetRunDelegateCtor(Type delegateType) { lock (_runCache) { Func <LightLambda, Delegate> fastCtor; if (_runCache.TryGetValue(delegateType, out fastCtor)) { return(fastCtor); } return(MakeRunDelegateCtor(delegateType)); } }
/// <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 }