Example #1
0
        private Func <DynamicOperations, CallSiteBinder, object, object[], object> GetInvoker(int paramCount)
        {
            Func <DynamicOperations, CallSiteBinder, object, object[], object> invoker;

            lock (_invokers) {
                if (!_invokers.TryGetValue(paramCount, out invoker))
                {
                    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.GetObjectCallSiteDelegateType(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();
                    _invokers[paramCount] = invoker = 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();
                }
            }
            return(invoker);
        }