Ejemplo n.º 1
0
            /// <summary>
            /// Adds a dynamic test which checks if the version has changed.  The test is only necessary for
            /// performance as the methods will do the correct thing if called with an incorrect version.
            /// </summary>
            private Expression AddDynamicTestAndDefer(MetaObjectBinder binder, MetaObject[] args, ExpandoClass klass, ExpandoClass originalClass, Expression ifTestSucceeds)
            {
                if (originalClass != null)
                {
                    // we are accessing a member which has not yet been defined on this class.
                    // We force a class promotion after the type check.  If the class changes the
                    // promotion will fail and the set/delete will do a full lookup using the new
                    // class to discover the name.
                    Debug.Assert(originalClass != klass);

                    ifTestSucceeds = Expression.Block(
                        Expression.Call(
                            null,
                            typeof(RuntimeOps).GetMethod("ExpandoPromoteClass"),
                            GetLimitedSelf(),
                            Expression.Constant(originalClass),
                            Expression.Constant(klass)
                            ),
                        ifTestSucceeds
                        );
                }

                return(Expression.Condition(
                           Expression.Call(
                               null,
                               typeof(RuntimeOps).GetMethod("ExpandoCheckVersion"),
                               GetLimitedSelf(),
                               Expression.Constant(originalClass ?? klass)
                               ),
                           ifTestSucceeds,
                           binder.Defer(args).Expression
                           ));
            }
Ejemplo n.º 2
0
            /// <summary>
            /// Helper method for generating a MetaObject which calls a
            /// specific method on Dynamic, but uses one of the arguments for
            /// the result.
            /// </summary>
            private MetaObject CallMethodNoResult(string methodName, MetaObjectBinder binder, Expression[] args, Fallback fallback)
            {
                //
                // First, call fallback to do default binding
                // This produces either an error or a call to a .NET member
                //
                MetaObject fallbackResult = fallback(null);

                //
                // Build a new expression like:
                //   TryDeleteMember(payload) ? null : fallbackResult
                //
                var callDynamic = new MetaObject(
                    Expression.Condition(
                        Expression.Call(
                            GetLimitedSelf(),
                            typeof(DynamicObject).GetMethod(methodName),
                            args.AddFirst(Constant(binder))
                            ),
                        Expression.Constant(null),
                        Expression.Convert(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));
            }
Ejemplo n.º 3
0
            private static ConstantExpression Constant(MetaObjectBinder 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 Dynamic that returns a result
            /// </summary>
            private MetaObject CallMethodWithResult(string methodName, MetaObjectBinder binder, Expression[] args, Fallback fallback)
            {
                //
                // First, call fallback to do default binding
                // This produces either an error or a call to a .NET member
                //
                MetaObject fallbackResult = fallback(null);

                //
                // Build a new expression like:
                // {
                //   object result;
                //   TryGetMember(payload, out result) ? result : fallbackResult
                // }
                //
                var result = Expression.Parameter(typeof(object), null);

                var callArgs = new Expression[args.Length + 2];

                Array.Copy(args, 0, callArgs, 1, args.Length);
                callArgs[0] = Constant(binder);
                callArgs[callArgs.Length - 1] = result;

                var callDynamic = new MetaObject(
                    Expression.Block(
                        new[] { result },
                        Expression.Condition(
                            Expression.Call(
                                GetLimitedSelf(),
                                typeof(DynamicObject).GetMethod(methodName),
                                callArgs
                                ),
                            result,
                            Expression.Convert(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));
            }
Ejemplo n.º 5
0
        internal MetaObject/*!*/ CreateMetaObject(MetaObjectBinder/*!*/ action, MetaObject/*!*/[]/*!*/ siteArgs) {
            var expr = _error ? Ast.Throw(_result) : _result;

            Restrictions restrictions;
            if (_condition != null) {
                var deferral = action.Defer(siteArgs);
                expr = Ast.Condition(_condition, AstUtils.Convert(expr, typeof(object)), deferral.Expression);
                restrictions = deferral.Restrictions;
            } else {
                restrictions = Restrictions.Empty;
            }

            if (_temps != null) {
                expr = Ast.Block(_temps, expr);
            }

            if (_restriction != null) {
                restrictions = restrictions.Merge(Restrictions.GetExpressionRestriction(_restriction));
            }

            return new MetaObject(expr, restrictions);
        }
Ejemplo n.º 6
0
            /// <summary>
            /// Adds a dynamic test which checks if the version has changed.  The test is only necessary for
            /// performance as the methods will do the correct thing if called with an incorrect version.
            /// </summary>
            private Expression AddDynamicTestAndDefer(MetaObjectBinder binder, MetaObject[] args, ExpandoClass klass, ExpandoClass originalClass, Expression ifTestSucceeds) {
                if (originalClass != null) {
                    // we are accessing a member which has not yet been defined on this class.
                    // We force a class promotion after the type check.  If the class changes the 
                    // promotion will fail and the set/delete will do a full lookup using the new
                    // class to discover the name.
                    Debug.Assert(originalClass != klass);

                    ifTestSucceeds = Expression.Block(
                        Expression.Call(
                            null,
                            typeof(RuntimeOps).GetMethod("ExpandoPromoteClass"),
                            GetLimitedSelf(),
                            Expression.Constant(originalClass),
                            Expression.Constant(klass)
                        ),
                        ifTestSucceeds
                    );
                }

                return Expression.Condition(
                    Expression.Call(
                        null,
                        typeof(RuntimeOps).GetMethod("ExpandoCheckVersion"),
                        GetLimitedSelf(),
                        Expression.Constant(originalClass ?? klass)
                    ),
                    ifTestSucceeds,
                    binder.Defer(args).Expression
                );
            }
Ejemplo n.º 7
0
 public BinderMappingInfo(MetaObjectBinder binder, params ParameterMappingInfo[] mappingInfos)
     : this(binder, (IList<ParameterMappingInfo>)mappingInfos) {
 }
Ejemplo n.º 8
0
 public BinderMappingInfo(MetaObjectBinder binder, IList<ParameterMappingInfo> mappingInfo) {
     Binder = binder;
     MappingInfo = mappingInfo;
 }
Ejemplo n.º 9
0
            /// <summary>
            /// Helper method for generating a MetaObject which calls a
            /// specific method on Dynamic, but uses one of the arguments for
            /// the result.
            /// </summary>
            private MetaObject CallMethodNoResult(string methodName, MetaObjectBinder binder, Expression[] args, Fallback fallback) {
                //
                // First, call fallback to do default binding
                // This produces either an error or a call to a .NET member
                //
                MetaObject fallbackResult = fallback(null);

                //
                // Build a new expression like:
                //   TryDeleteMember(payload) ? null : fallbackResult
                //
                var callDynamic = new MetaObject(
                    Expression.Condition(
                        Expression.Call(
                            GetLimitedSelf(),
                            typeof(DynamicObject).GetMethod(methodName),
                            args.AddFirst(Constant(binder))
                        ),
                        Expression.Constant(null),
                        Expression.Convert(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);
            }
Ejemplo n.º 10
0
            /// <summary>
            /// Helper method for generating a MetaObject which calls a
            /// specific method on Dynamic that returns a result
            /// </summary>
            private MetaObject CallMethodWithResult(string methodName, MetaObjectBinder binder, Expression[] args, Fallback fallback) {
                //
                // First, call fallback to do default binding
                // This produces either an error or a call to a .NET member
                //
                MetaObject fallbackResult = fallback(null);

                //
                // Build a new expression like:
                // {
                //   object result;
                //   TryGetMember(payload, out result) ? result : fallbackResult
                // }
                //
                var result = Expression.Parameter(typeof(object), null);

                var callArgs = new Expression[args.Length + 2];
                Array.Copy(args, 0, callArgs, 1, args.Length);
                callArgs[0] = Constant(binder);
                callArgs[callArgs.Length - 1] = result;

                var callDynamic = new MetaObject(
                    Expression.Block(
                        new[] { result },
                        Expression.Condition(
                            Expression.Call(
                                GetLimitedSelf(),
                                typeof(DynamicObject).GetMethod(methodName),
                                callArgs
                            ),
                            result,
                            Expression.Convert(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);
            }
Ejemplo n.º 11
0
 private static ConstantExpression Constant(MetaObjectBinder binder) {
     Type t = binder.GetType();
     while (!t.IsVisible) {
         t = t.BaseType;
     }
     return Expression.Constant(binder, t);
 }
Ejemplo n.º 12
0
 internal MetaObject/*!*/ CreateMetaObject(MetaObjectBinder/*!*/ action, MetaObject/*!*/ context, MetaObject/*!*/[]/*!*/ args) {
     return CreateMetaObject(action, ArrayUtils.Insert(context, args));
 }