private object DelegateProxy(Type delegateType, ICallRouter callRouter)
        {
            var delegateMethodToProxy = delegateType.GetMethod("Invoke");

            var proxyParameterTypes = delegateMethodToProxy.GetParameters().Select(x => new ParameterInfoWrapper(x)).ToArray();

            var delegateCall         = new DelegateCall(callRouter, delegateMethodToProxy.ReturnType, proxyParameterTypes);
            var invokeOnDelegateCall = delegateCall.MethodToInvoke;

            ParameterExpression[] proxyParameters          = delegateMethodToProxy.GetParameters().Select(x => Expression.Parameter(x.ParameterType, x.Name)).ToArray();
            Expression[]          proxyParametersAsObjects = proxyParameters.Select(x => (Expression)Expression.Convert(x, typeof(object))).ToArray();

            Expression callInvokeOnDelegateCallInstance =
                Expression.Call(
                    Expression.Constant(delegateCall),
                    invokeOnDelegateCall,
                    new Expression[]
            {
                Expression.NewArrayInit(typeof(object), proxyParametersAsObjects)
            }
                    );

            if (delegateMethodToProxy.ReturnType != typeof(void))
            {
                callInvokeOnDelegateCallInstance =
                    Expression.Convert(callInvokeOnDelegateCallInstance, delegateMethodToProxy.ReturnType);
            }

            var proxyExpression = Expression.Lambda(delegateType, callInvokeOnDelegateCallInstance, proxyParameters);

            return(proxyExpression.Compile());
        }
        private object DelegateProxy(Type delegateType, ICallRouter callRouter)
        {
            var delegateMethodToProxy = delegateType.GetMethod("Invoke");

            var proxyParameterTypes  = delegateMethodToProxy.GetParameters().Select(x => new ParameterInfoWrapper(x)).ToArray();
            var delegateCall         = new DelegateCall(callRouter, delegateType, delegateMethodToProxy.ReturnType, proxyParameterTypes);
            var invokeOnDelegateCall = delegateCall.MethodToInvoke;

            ParameterExpression[] proxyParameters          = delegateMethodToProxy.GetParameters().Select(x => Expression.Parameter(x.ParameterType, x.Name)).ToArray();
            Expression[]          proxyParametersAsObjects = proxyParameters.Select(x => (Expression)Expression.Convert(x, typeof(object))).ToArray();
            var  bodyExpressions = new List <Expression>();
            bool isVoid          = delegateMethodToProxy.ReturnType == typeof(void);
            var  arguments       = Expression.Variable(typeof(object[]), "arguments");
            var  result          = isVoid ? null : Expression.Variable(delegateMethodToProxy.ReturnType, "result");

            bodyExpressions.Add(Expression.Assign(arguments, Expression.NewArrayInit(typeof(object), proxyParametersAsObjects)));

            Expression callInvokeOnDelegateCallInstance = Expression.Call(Expression.Constant(delegateCall), invokeOnDelegateCall, arguments);

            if (!isVoid)
            {
                callInvokeOnDelegateCallInstance = Expression.Assign(result, Expression.Convert(callInvokeOnDelegateCallInstance, delegateMethodToProxy.ReturnType));
            }

            bodyExpressions.Add(callInvokeOnDelegateCallInstance);

            for (var index = 0; index < proxyParameters.Length; index++)
            {
                var parameter = proxyParameters[index];
                if (parameter.IsByRef)
                {
                    var assignment = Expression.Assign(parameter, Expression.Convert(Expression.ArrayAccess(arguments, Expression.Constant(index)), parameter.Type));
                    bodyExpressions.Add(assignment);
                }
            }

            if (!isVoid)
            {
                bodyExpressions.Add(result);
            }

            var variables       = isVoid ? new[] { arguments } : new[] { arguments, result };
            var proxyExpression = Expression.Lambda(delegateType, Expression.Block(variables, bodyExpressions), proxyParameters);

            return(proxyExpression.Compile());
        }