/// <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); }