/// <summary>
        /// Helper method for generating a MetaObject which calls a
        /// specific method on Dynamic that returns a result
        /// </summary>
        private DynamicMetaObject CallMethodWithResult(
            string methodName,
            DynamicMetaObjectBinder binder,
            IEnumerable <Expression> args,
            Fallback fallback,
            Fallback?fallbackInvoke = null
            )
        {
            //
            // First, call fallback to do default binding
            // This produces either an error or a call to a .NET member
            //
            DynamicMetaObject fallbackResult = fallback(null);

            return(BuildCallMethodWithResult(
                       methodName,
                       binder,
                       args,
                       fallbackResult,
                       fallbackInvoke
                       ));
        }
        private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, IEnumerable <Expression> args, DynamicMetaObject fallbackResult, Fallback?fallbackInvoke)
        {
            //
            // Build a new expression like:
            // {
            //   object result;
            //   TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult
            // }
            //
            ParameterExpression result = Expression.Parameter(typeof(object), null);

            IList <Expression> callArgs = new List <Expression>();

            callArgs.Add(Expression.Convert(Expression, typeof(T)));
            callArgs.Add(Constant(binder));
            callArgs.AddRange(args);
            callArgs.Add(result);

            DynamicMetaObject resultMetaObject = new DynamicMetaObject(result, BindingRestrictions.Empty);

            // Need to add a conversion if calling TryConvert
            if (binder.ReturnType != typeof(object))
            {
                UnaryExpression convert = Expression.Convert(resultMetaObject.Expression, binder.ReturnType);
                // will always be a cast or unbox

                resultMetaObject = new DynamicMetaObject(convert, resultMetaObject.Restrictions);
            }

            if (fallbackInvoke != null)
            {
                resultMetaObject = fallbackInvoke(resultMetaObject);
            }

            DynamicMetaObject callDynamic = new DynamicMetaObject(
                Expression.Block(
                    new[] { result },
                    Expression.Condition(
                        Expression.Call(
                            Expression.Constant(_proxy),
                            typeof(DynamicProxy <T>).GetMethod(methodName),
                            callArgs
                            ),
                        resultMetaObject.Expression,
                        fallbackResult.Expression,
                        binder.ReturnType
                        )
                    ),
                GetRestrictions().Merge(resultMetaObject.Restrictions).Merge(fallbackResult.Restrictions)
                );

            return(callDynamic);
        }