private Expression BuildMethodCall(MethodBase method, Type type, ParameterExpression targetParameterExpression, ParameterExpression argsParameterExpression) { ParameterInfo[] parametersInfo = method.GetParameters(); Expression[] argsExpression; IList<ByRefParameter> refParameterMap; if (parametersInfo.Length == 0) { argsExpression = CollectionUtils.ArrayEmpty<Expression>(); refParameterMap = CollectionUtils.ArrayEmpty<ByRefParameter>(); } else { argsExpression = new Expression[parametersInfo.Length]; refParameterMap = new List<ByRefParameter>(); for (int i = 0; i < parametersInfo.Length; i++) { ParameterInfo parameter = parametersInfo[i]; Type parameterType = parameter.ParameterType; bool isByRef = false; if (parameterType.IsByRef) { parameterType = parameterType.GetElementType(); isByRef = true; } Expression indexExpression = Expression.Constant(i); Expression paramAccessorExpression = Expression.ArrayIndex(argsParameterExpression, indexExpression); Expression argExpression = EnsureCastExpression(paramAccessorExpression, parameterType, !isByRef); if (isByRef) { ParameterExpression variable = Expression.Variable(parameterType); refParameterMap.Add(new ByRefParameter {Value = argExpression, Variable = variable, IsOut = parameter.IsOut}); argExpression = variable; } argsExpression[i] = argExpression; } } Expression callExpression; if (method.IsConstructor) { callExpression = Expression.New((ConstructorInfo)method, argsExpression); } else if (method.IsStatic) { callExpression = Expression.Call((MethodInfo)method, argsExpression); } else { Expression readParameter = EnsureCastExpression(targetParameterExpression, method.DeclaringType); callExpression = Expression.Call(readParameter, (MethodInfo)method, argsExpression); } if (method is MethodInfo m) { if (m.ReturnType != typeof(void)) { callExpression = EnsureCastExpression(callExpression, type); } else { callExpression = Expression.Block(callExpression, Expression.Constant(null)); } } else { callExpression = EnsureCastExpression(callExpression, type); } if (refParameterMap.Count > 0) { IList<ParameterExpression> variableExpressions = new List<ParameterExpression>(); IList<Expression> bodyExpressions = new List<Expression>(); foreach (ByRefParameter p in refParameterMap) { if (!p.IsOut) { bodyExpressions.Add(Expression.Assign(p.Variable, p.Value)); } variableExpressions.Add(p.Variable); } bodyExpressions.Add(callExpression); callExpression = Expression.Block(variableExpressions, bodyExpressions); } return callExpression; }