protected virtual Delegate GetMethodDelegateInternal(Type delegateType, MethodInfo method) { lock (InvokeMethodCacheDelegate) { var cacheKey = new MethodDelegateCacheKey(method, delegateType); Delegate value; if (!InvokeMethodCacheDelegate.TryGetValue(cacheKey, out value)) { GenerateInvokeMethodCode(method, delegateType); MethodInfo delegateMethod = delegateType.GetMethodEx(nameof(Action.Invoke)); if (delegateMethod == null) { throw new ArgumentException(string.Empty, nameof(delegateType)); } var delegateParams = delegateMethod.GetParameters().ToList(); ParameterInfo[] methodParams = method.GetParameters(); var expressions = new List <Expression>(); var parameters = new List <ParameterExpression>(); if (!method.IsStatic) { var thisParam = Expression.Parameter(delegateParams[0].ParameterType, "@this"); parameters.Add(thisParam); expressions.Add(ConvertIfNeed(thisParam, method.DeclaringType, false)); delegateParams.RemoveAt(0); } Should.BeValid("delegateType", delegateParams.Count == methodParams.Length); for (int i = 0; i < methodParams.Length; i++) { ParameterExpression parameter = Expression.Parameter(delegateParams[i].ParameterType, i.ToString()); parameters.Add(parameter); expressions.Add(ConvertIfNeed(parameter, methodParams[i].ParameterType, false)); } Expression callExpression; if (method.IsStatic) { callExpression = Expression.Call(null, method, expressions.ToArrayEx()); } else { Expression @this = expressions[0]; expressions.RemoveAt(0); callExpression = Expression.Call(@this, method, expressions.ToArrayEx()); } if (delegateMethod.ReturnType != typeof(void)) { callExpression = ConvertIfNeed(callExpression, delegateMethod.ReturnType, false); } var lambdaExpression = Expression.Lambda(delegateType, callExpression, parameters); value = lambdaExpression.Compile(); InvokeMethodCacheDelegate[cacheKey] = value; } return(value); } }
/// <summary> /// Gets a delegate to call the specified <see cref="MethodInfo" />. /// </summary> /// <param name="delegateType">The type of delegate.</param> /// <param name="method"> /// The specified <see cref="MethodInfo" /> /// </param> /// <returns> /// An instance of delegate. /// </returns> public virtual Delegate GetMethodDelegate(Type delegateType, MethodInfo method) { Should.NotBeNull(delegateType, "delegateType"); Should.BeOfType <Delegate>(delegateType, "delegateType"); Should.NotBeNull(method, "method"); lock (InvokeMethodCacheDelegate) { var cacheKey = new MethodDelegateCacheKey(method, delegateType); Delegate value; if (!InvokeMethodCacheDelegate.TryGetValue(cacheKey, out value)) { MethodInfo delegateMethod = delegateType.GetMethodEx("Invoke"); var delegateParams = delegateMethod.GetParameters().ToList(); ParameterInfo[] methodParams = method.GetParameters(); var expressions = new List <Expression>(); var parameters = new List <ParameterExpression>(); if (!method.IsStatic) { var thisParam = Expression.Parameter(delegateParams[0].ParameterType, "@this"); parameters.Add(thisParam); expressions.Add(ConvertIfNeed(thisParam, GetDeclaringType(method), false)); delegateParams.RemoveAt(0); } Should.BeValid("delegateType", delegateParams.Count == methodParams.Length); for (int i = 0; i < methodParams.Length; i++) { ParameterExpression parameter = Expression.Parameter(delegateParams[i].ParameterType, i.ToString()); parameters.Add(parameter); expressions.Add(ConvertIfNeed(parameter, methodParams[i].ParameterType, false)); } Expression callExpression; if (method.IsStatic) { callExpression = Expression.Call(null, method, expressions.ToArrayEx()); } else { Expression @this = expressions[0]; expressions.RemoveAt(0); callExpression = Expression.Call(@this, method, expressions.ToArrayEx()); } if (delegateMethod.ReturnType != typeof(void)) { callExpression = ConvertIfNeed(callExpression, delegateMethod.ReturnType, false); } var lambdaExpression = CreateLambdaExpressionByType(delegateType, callExpression, parameters); value = lambdaExpression.Compile(); InvokeMethodCacheDelegate[cacheKey] = value; } return(value); } }