private DynamicMetaObject CallMethodReturnLast(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Expression value, Fallback fallback) {
//
// First, call fallback to do default binding
// This produces either an error or a call to a .NET member
//
DynamicMetaObject fallbackResult = fallback(null);
//
// Build a new expression like:
// {
// object result;
// TrySetMember(payload, result = value) ? result : fallbackResult
// }
//
var result = Expression.Parameter(typeof(object), null);
var callArgs = Expression.Parameter(typeof(object[]), null);
var callArgsValue = GetConvertedArgs(args);
var callDynamic = new DynamicMetaObject(
Expression.Block(
new[] { result, callArgs },
Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)),
Expression.Condition(
Expression.Call(
GetLimitedSelf(),
typeof(DynamicObject).GetMethod(methodName),
BuildCallArgs(
binder,
args,
callArgs,
Expression.Assign(result, Expression.Convert(value, typeof(object)))
)
),
Expression.Block(
ReferenceArgAssign(callArgs, args),
result
),
fallbackResult.Expression,
typeof(object)
)
),
GetRestrictions().Merge(fallbackResult.Restrictions)
);
//
// Now, call fallback again using our new MO as the error
// When we do this, one of two things can happen:
// 1. Binding will succeed, and it will ignore our call to
// the dynamic method, OR
// 2. Binding will fail, and it will use the MO we created
// above.
//
return fallback(callDynamic);
}