Ejemplo n.º 1
0
            private static ConstantExpression Constant(DynamicMetaObjectBinder binder)
            {
                Type t = binder.GetType();

                while (!t.IsVisible)
                {
                    t = t.BaseType;
                }
                return(Expression.Constant(binder, t));
            }
Ejemplo n.º 2
0
            /// <summary>
            /// Helper method for generating a MetaObject which calls a
            /// specific method on DynamicObject that returns a result.
            /// 
            /// args is either an array of arguments to be passed
            /// to the method as an object[] or NoArgs to signify that
            /// the target method takes no parameters.
            /// </summary>
            private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Fallback fallbackInvoke) {
                if (!IsOverridden(methodName)) {
                    return fallbackResult;
                }

                //
                // Build a new expression like:
                // {
                //   object result;
                //   TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult
                // }
                //
                var result = Expression.Parameter(typeof(object), null);
                ParameterExpression callArgs = methodName != "TryBinaryOperation" ? Expression.Parameter(typeof(object[]), null) : Expression.Parameter(typeof(object), null);
                var callArgsValue = GetConvertedArgs(args);

                var resultMO = new DynamicMetaObject(result, BindingRestrictions.Empty);

                // Need to add a conversion if calling TryConvert
                if (binder.ReturnType != typeof(object)) {
                    Debug.Assert(binder is ConvertBinder && fallbackInvoke == null);

                    var convert = Expression.Convert(resultMO.Expression, binder.ReturnType);
                    // will always be a cast or unbox
                    Debug.Assert(convert.Method == null);

#if !SILVERLIGHT
                    // Prepare a good exception message in case the convert will fail
                    string convertFailed = Strings.DynamicObjectResultNotAssignable(
                        "{0}",
                        this.Value.GetType(),
                        binder.GetType(),
                        binder.ReturnType
                    );

                    Expression condition;
                    // If the return type can not be assigned null then just check for type assignablity otherwise allow null.
                    if (binder.ReturnType.IsValueType && Nullable.GetUnderlyingType(binder.ReturnType) == null) {
                        condition = Expression.TypeIs(resultMO.Expression, binder.ReturnType);
                    }
                    else {
                        condition = Expression.OrElse(
                                        Expression.Equal(resultMO.Expression, Expression.Constant(null)),
                                        Expression.TypeIs(resultMO.Expression, binder.ReturnType));
                    }

                    var checkedConvert = Expression.Condition(
                        condition,
                        convert,
                        Expression.Throw(
                            Expression.New(typeof(InvalidCastException).GetConstructor(new Type[]{typeof(string)}),
                                Expression.Call(
                                    typeof(string).GetMethod("Format", new Type[] {typeof(string), typeof(object[])}),
                                    Expression.Constant(convertFailed),
                                    Expression.NewArrayInit(typeof(object), 
                                        Expression.Condition(
                                            Expression.Equal(resultMO.Expression, Expression.Constant(null)),
                                            Expression.Constant("null"),
                                            Expression.Call(
                                                resultMO.Expression,
                                                typeof(object).GetMethod("GetType")
                                            ),
                                            typeof(object)
                                        )
                                    )
                                )
                            ),
                            binder.ReturnType
                        ),
                        binder.ReturnType
                    );
#else
                    var checkedConvert = convert;
#endif

                    resultMO = new DynamicMetaObject(checkedConvert, resultMO.Restrictions);
                }

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

                var callDynamic = new DynamicMetaObject(
                    Expression.Block(
                        new[] { result, callArgs },
                        methodName != "TryBinaryOperation" ? Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)) : Expression.Assign(callArgs, callArgsValue[0]),
                        Expression.Condition(
                            Expression.Call(
                                GetLimitedSelf(),
                                typeof(DynamicObject).GetMethod(methodName),
                                BuildCallArgs(
                                    binder,
                                    args,
                                    callArgs,
                                    result
                                )
                            ),
                            Expression.Block(
                                methodName != "TryBinaryOperation" ? ReferenceArgAssign(callArgs, args) : Expression.Empty(),
                                resultMO.Expression
                            ),
                            fallbackResult.Expression,
                            binder.ReturnType
                        )
                    ),
                    GetRestrictions().Merge(resultMO.Restrictions).Merge(fallbackResult.Restrictions)
                );
                return callDynamic;
            }
Ejemplo n.º 3
0
 private static ConstantExpression Constant(DynamicMetaObjectBinder binder) {
     Type t = binder.GetType();
     while (!t.IsVisible) {
         t = t.BaseType;
     }
     return Expression.Constant(binder, t);
 }
Ejemplo n.º 4
0
            /// <summary>
            /// Helper method for generating a MetaObject which calls a
            /// specific method on DynamicObject that returns a result.
            ///
            /// args is either an array of arguments to be passed
            /// to the method as an object[] or NoArgs to signify that
            /// the target method takes no parameters.
            /// </summary>
            private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Fallback fallbackInvoke)
            {
                if (!IsOverridden(methodName))
                {
                    return(fallbackResult);
                }

                //
                // Build a new expression like:
                // {
                //   object result;
                //   TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult
                // }
                //
                var result = Expression.Parameter(typeof(object), null);
                ParameterExpression callArgs = methodName != "TryBinaryOperation" ? Expression.Parameter(typeof(object[]), null) : Expression.Parameter(typeof(object), null);
                var callArgsValue            = GetConvertedArgs(args);

                var resultMO = new DynamicMetaObject(result, BindingRestrictions.Empty);

                // Need to add a conversion if calling TryConvert
                if (binder.ReturnType != typeof(object))
                {
                    Debug.Assert(binder is ConvertBinder && fallbackInvoke == null);

                    var convert = Expression.Convert(resultMO.Expression, binder.ReturnType);
                    // will always be a cast or unbox
                    Debug.Assert(convert.Method == null);

                    // Prepare a good exception message in case the convert will fail
                    string convertFailed = Strings.DynamicObjectResultNotAssignable(
                        "{0}",
                        this.Value.GetType(),
                        binder.GetType(),
                        binder.ReturnType
                        );

                    var checkedConvert = Expression.Condition(
                        Expression.TypeIs(resultMO.Expression, binder.ReturnType),
                        convert,
                        Expression.Throw(
                            Expression.New(typeof(InvalidCastException).GetConstructor(new Type[] { typeof(string) }),
                                           Expression.Call(
                                               typeof(string).GetMethod("Format", new Type[] { typeof(string), typeof(object) }),
                                               Expression.Constant(convertFailed),
                                               Expression.Condition(
                                                   Expression.Equal(resultMO.Expression, Expression.Constant(null)),
                                                   Expression.Constant("null"),
                                                   Expression.Call(
                                                       resultMO.Expression,
                                                       typeof(object).GetMethod("GetType")
                                                       ),
                                                   typeof(object)
                                                   )
                                               )
                                           ),
                            binder.ReturnType
                            ),
                        binder.ReturnType
                        );

                    resultMO = new DynamicMetaObject(checkedConvert, resultMO.Restrictions);
                }

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

                var callDynamic = new DynamicMetaObject(
                    Expression.Block(
                        new[] { result, callArgs },
                        methodName != "TryBinaryOperation" ? Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)) : Expression.Assign(callArgs, callArgsValue[0]),
                        Expression.Condition(
                            Expression.Call(
                                GetLimitedSelf(),
                                typeof(DynamicObject).GetMethod(methodName),
                                BuildCallArgs(
                                    binder,
                                    args,
                                    callArgs,
                                    result
                                    )
                                ),
                            Expression.Block(
                                methodName != "TryBinaryOperation" ? ReferenceArgAssign(callArgs, args) : Expression.Empty(),
                                resultMO.Expression
                                ),
                            fallbackResult.Expression,
                            binder.ReturnType
                            )
                        ),
                    GetRestrictions().Merge(resultMO.Restrictions).Merge(fallbackResult.Restrictions)
                    );

                return(callDynamic);
            }
 private static ConstantExpression Constant(DynamicMetaObjectBinder binder)
 {
     Type baseType = binder.GetType();
     while (!baseType.IsVisible)
     {
         baseType = baseType.BaseType;
     }
     return Expression.Constant(binder, baseType);
 }