/// <summary> /// Creates a new ReflectedCaller which can be used to quickly invoke the provided MethodInfo. /// </summary> public static ReflectedCaller Create(MethodInfo info) { if ((!info.IsStatic && info.DeclaringType.IsValueType) || info is System.Reflection.Emit.DynamicMethod) { return new SlowReflectedCaller(info); } ParameterInfo[] pis = info.GetParameters(); int argCnt = pis.Length; if (!info.IsStatic) argCnt++; if (argCnt >= MaxHelpers) { // no delegate for this size, fallback to reflection invoke return new SlowReflectedCaller(info); } foreach (ParameterInfo pi in pis) { if (pi.ParameterType.IsByRef) { // we don't support ref args via generics. return new SlowReflectedCaller(info); } } // see if we've created one w/ a delegate ReflectedCaller res; if (ShouldCache(info)) { lock (_cache) { if (_cache.TryGetValue(info, out res)) { return res; } } } // create it try { if (argCnt < MaxArgs) { res = FastCreate(info, pis); } else { res = SlowCreate(info, pis); } } catch (TargetInvocationException tie) { if (!(tie.InnerException is NotSupportedException)) { throw; } res = new SlowReflectedCaller(info); } 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 SlowReflectedCaller(info); } // 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> public static ReflectedCaller Create(MethodInfo info) { if ((!info.IsStatic && info.DeclaringType.IsValueType) || info is System.Reflection.Emit.DynamicMethod) { return(new SlowReflectedCaller(info)); } ParameterInfo[] pis = info.GetParameters(); int argCnt = pis.Length; if (!info.IsStatic) { argCnt++; } if (argCnt >= MaxHelpers) { // no delegate for this size, fallback to reflection invoke return(new SlowReflectedCaller(info)); } foreach (ParameterInfo pi in pis) { if (pi.ParameterType.IsByRef) { // we don't support ref args via generics. return(new SlowReflectedCaller(info)); } } // see if we've created one w/ a delegate ReflectedCaller res; if (ShouldCache(info)) { lock (_cache) { if (_cache.TryGetValue(info, out res)) { return(res); } } } // create it try { if (argCnt < MaxArgs) { res = FastCreate(info, pis); } else { res = SlowCreate(info, pis); } } catch (TargetInvocationException tie) { if (!(tie.InnerException is NotSupportedException)) { throw; } res = new SlowReflectedCaller(info); } 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 SlowReflectedCaller(info); } // cache it for future users if it's a reasonable method to cache if (ShouldCache(info)) { lock (_cache) { _cache[info] = res; } } return(res); }