private Func<DynamicOperations, CallSiteBinder, object, object[], object> EmitInvoker(int paramCount) {
ParameterExpression dynOps = Expression.Parameter(typeof(DynamicOperations));
ParameterExpression callInfo = Expression.Parameter(typeof(CallSiteBinder));
ParameterExpression target = Expression.Parameter(typeof(object));
ParameterExpression args = Expression.Parameter(typeof(object[]));
Type funcType = DelegateUtils.EmitCallSiteDelegateType(paramCount);
ParameterExpression site = Expression.Parameter(typeof(CallSite<>).MakeGenericType(funcType));
Expression[] siteArgs = new Expression[paramCount + 2];
siteArgs[0] = site;
siteArgs[1] = target;
for (int i = 0; i < paramCount; i++) {
siteArgs[i + 2] = Expression.ArrayIndex(args, Expression.Constant(i));
}
var getOrCreateSiteFunc = new Func<CallSiteBinder, CallSite<Func<object>>>(GetOrCreateSite<Func<object>>).Method.GetGenericMethodDefinition();
return Expression.Lambda<Func<DynamicOperations, CallSiteBinder, object, object[], object>>(
Expression.Block(
new[] { site },
Expression.Assign(
site,
Expression.Call(dynOps, getOrCreateSiteFunc.MakeGenericMethod(funcType), callInfo)
),
Expression.Invoke(
Expression.Field(
site,
site.Type.GetField("Target")
),
siteArgs
)
),
new[] { dynOps, callInfo, target, args }
).Compile();
}