Create() public static method

Creates a meta-object for the specified object.
public static Create ( object value, Expression expression ) : DynamicMetaObject
value object The object to get a meta-object for.
expression System.Linq.Expressions.Expression The expression representing this during the dynamic binding process.
return DynamicMetaObject
 private static DynamicMetaObject[] CreateArgumentMetaObjects(object[] args, ReadOnlyCollection <ParameterExpression> parameters)
 {
     if (args.Length != 1)
     {
         DynamicMetaObject[] objArray = new DynamicMetaObject[args.Length - 1];
         for (int i = 1; i < args.Length; i++)
         {
             objArray[i - 1] = DynamicMetaObject.Create(args[i], parameters[i]);
         }
         return(objArray);
     }
     return(DynamicMetaObject.EmptyMetaObjects);
 }
 private static DynamicMetaObject[] CreateArgumentMetaObjects(object[] args, ReadOnlyCollection<ParameterExpression> parameters)
 {
     DynamicMetaObject[] mos;
     if (args.Length != 1)
     {
         mos = new DynamicMetaObject[args.Length - 1];
         for (int i = 1; i < args.Length; i++)
         {
             mos[i - 1] = DynamicMetaObject.Create(args[i], parameters[i]);
         }
     }
     else
     {
         mos = DynamicMetaObject.EmptyMetaObjects;
     }
     return mos;
 }
Beispiel #3
0
        /// <summary>
        /// Performs the runtime binding of the dynamic operation on a set of arguments.
        /// </summary>
        /// <param name="args">An array of arguments to the dynamic operation.</param>
        /// <param name="parameters">The array of <see cref="ParameterExpression"/> instances that represent the parameters of the call site in the binding process.</param>
        /// <param name="returnLabel">A LabelTarget used to return the result of the dynamic binding.</param>
        /// <returns>
        /// An Expression that performs tests on the dynamic operation arguments, and
        /// performs the dynamic operation if the tests are valid. If the tests fail on
        /// subsequent occurrences of the dynamic operation, Bind will be called again
        /// to produce a new <see cref="Expression"/> for the new argument types.
        /// </returns>
        public sealed override Expression Bind(object[] args, ReadOnlyCollection <ParameterExpression> parameters, LabelTarget returnLabel)
        {
            ContractUtils.RequiresNotNull(args, nameof(args));
            ContractUtils.RequiresNotNull(parameters, nameof(parameters));
            ContractUtils.RequiresNotNull(returnLabel, nameof(returnLabel));
            if (args.Length == 0)
            {
                throw System.Linq.Expressions.Error.OutOfRange("args.Length", 1);
            }
            if (parameters.Count == 0)
            {
                throw System.Linq.Expressions.Error.OutOfRange("parameters.Count", 1);
            }
            if (args.Length != parameters.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(args));
            }

            // Ensure that the binder's ReturnType matches CallSite's return
            // type. We do this so meta objects and language binders can
            // compose trees together without needing to insert converts.
            Type expectedResult;

            if (IsStandardBinder)
            {
                expectedResult = ReturnType;

                if (returnLabel.Type != typeof(void) &&
                    !TypeUtils.AreReferenceAssignable(returnLabel.Type, expectedResult))
                {
                    throw System.Linq.Expressions.Error.BinderNotCompatibleWithCallSite(expectedResult, this, returnLabel.Type);
                }
            }
            else
            {
                // Even for non-standard binders, we have to at least make sure
                // it works with the CallSite's type to build the return.
                expectedResult = returnLabel.Type;
            }

            DynamicMetaObject target = DynamicMetaObject.Create(args[0], parameters[0]);

            DynamicMetaObject[] metaArgs = CreateArgumentMetaObjects(args, parameters);

            DynamicMetaObject binding = Bind(target, metaArgs);

            if (binding == null)
            {
                throw System.Linq.Expressions.Error.BindingCannotBeNull();
            }

            Expression          body         = binding.Expression;
            BindingRestrictions restrictions = binding.Restrictions;

            // Ensure the result matches the expected result type.
            if (expectedResult != typeof(void) &&
                !TypeUtils.AreReferenceAssignable(expectedResult, body.Type))
            {
                //
                // Blame the last person that handled the result: assume it's
                // the dynamic object (if any), otherwise blame the language.
                //
                if (target.Value is IDynamicMetaObjectProvider)
                {
                    throw System.Linq.Expressions.Error.DynamicObjectResultNotAssignable(body.Type, target.Value.GetType(), this, expectedResult);
                }
                else
                {
                    throw System.Linq.Expressions.Error.DynamicBinderResultNotAssignable(body.Type, this, expectedResult);
                }
            }

            // if the target is IDO, standard binders ask it to bind the rule so we may have a target-specific binding.
            // it makes sense to restrict on the target's type in such cases.
            // ideally IDO metaobjects should do this, but they often miss that type of "this" is significant.
            if (IsStandardBinder && args[0] as IDynamicMetaObjectProvider != null)
            {
                if (restrictions == BindingRestrictions.Empty)
                {
                    throw System.Linq.Expressions.Error.DynamicBindingNeedsRestrictions(target.Value.GetType(), this);
                }
            }

            // Add the return
            if (body.NodeType != ExpressionType.Goto)
            {
                body = Expression.Return(returnLabel, body);
            }

            // Finally, add restrictions
            if (restrictions != BindingRestrictions.Empty)
            {
                body = Expression.IfThen(restrictions.ToExpression(), body);
            }

            return(body);
        }
        /// <inheritdoc />
        /// <summary>
        ///     Performs the runtime binding of the dynamic operation on a set of arguments.
        /// </summary>
        /// <param name="args">An array of arguments to the dynamic operation.</param>
        /// <param name="parameters">
        ///     The array of <see cref="T:System.Linq.Expressions.ParameterExpression" /> instances that represent the parameters
        ///     of the
        ///     call site in the binding process.
        /// </param>
        /// <param name="returnLabel">A LabelTarget used to return the result of the dynamic binding.</param>
        /// <returns>
        ///     An Expression that performs tests on the dynamic operation arguments, and
        ///     performs the dynamic operation if the tests are valid. If the tests fail on
        ///     subsequent occurrences of the dynamic operation, Bind will be called again
        ///     to produce a new <see cref="T:System.Linq.Expressions.Expression" /> for the new argument types.
        /// </returns>
        public sealed override Expression Bind(object[] args, ReadOnlyCollection <ParameterExpression> parameters, LabelTarget returnLabel)
        {
            ContractUtils.RequiresNotNull(args, nameof(args));
            ContractUtils.RequiresNotNull(parameters, nameof(parameters));
            ContractUtils.RequiresNotNull(returnLabel, nameof(returnLabel));
            if (args.Length == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(args), "args.Length must be greater than or equal to 1");
            }

            if (parameters.Count == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(parameters), "parameters.Count must be greater than or equal to 1");
            }

            if (args.Length != parameters.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(args));
            }

            // Ensure that the binder's ReturnType matches CallSite's return
            // type. We do this so meta objects and language binders can
            // compose trees together without needing to insert converts.
            Type expectedResult;

            if (IsStandardBinder)
            {
                expectedResult = ReturnType;
                if (returnLabel.Type != typeof(void) && !returnLabel.Type.IsReferenceAssignableFromInternal(expectedResult))
                {
                    throw new InvalidOperationException($"The result type '{expectedResult}' of the binder '{this}' is not compatible with the result type '{returnLabel.Type}' expected by the call site.");
                }
            }
            else
            {
                // Even for non-standard binders, we have to at least make sure
                // it works with the CallSite's type to build the return.
                expectedResult = returnLabel.Type;
            }

            var target   = DynamicMetaObject.Create(args[0], parameters[0]);
            var metaArgs = CreateArgumentMetaObjects(args, parameters);

            var binding = Bind(target, metaArgs);

            if (binding == null)
            {
                throw new InvalidOperationException("Bind cannot return null.");
            }

            var body         = binding.Expression;
            var restrictions = binding.Restrictions;

            // Ensure the result matches the expected result type.
            if (expectedResult != typeof(void) && !expectedResult.IsReferenceAssignableFromInternal(body.Type))
            {
                //
                // Blame the last person that handled the result: assume it's
                // the dynamic object (if any), otherwise blame the language.
                //
                if (target.Value is IDynamicMetaObjectProvider)
                {
                    throw new InvalidCastException($"The result type '{body.Type}' of the dynamic binding produced by the object with type '{target.Value.GetType()}' for the binder '{this}' is not compatible with the result type '{expectedResult}' expected by the call site.");
                }

                throw new InvalidCastException($"The result type '{body.Type}' of the dynamic binding produced by binder '{this}' is not compatible with the result type '{expectedResult}' expected by the call site.");
            }

            // if the target is IDO, standard binders ask it to bind the rule so we may have a target-specific binding.
            // it makes sense to restrict on the target's type in such cases.
            // ideally IDO meta-objects should do this, but they often miss that type of "this" is significant.
            if (IsStandardBinder && args[0] is IDynamicMetaObjectProvider && restrictions == BindingRestrictions.Empty)
            {
                throw new InvalidOperationException($"The result of the dynamic binding produced by the object with type '{target.Value.GetType()}' for the binder '{this}' needs at least one restriction.");
            }

            // Add the return
            if (body.NodeType != ExpressionType.Goto)
            {
                body = Expression.Return(returnLabel, body);
            }

            // Finally, add restrictions
            if (restrictions != BindingRestrictions.Empty)
            {
                body = Expression.IfThen(restrictions.ToExpression(), body);
            }

            return(body);
        }
        public sealed override Expression Bind(object[] args, ReadOnlyCollection <ParameterExpression> parameters, LabelTarget returnLabel)
        {
            Type returnType;

            ContractUtils.RequiresNotNull(args, "args");
            ContractUtils.RequiresNotNull(parameters, "parameters");
            ContractUtils.RequiresNotNull(returnLabel, "returnLabel");
            if (args.Length == 0)
            {
                throw Error.OutOfRange("args.Length", 1);
            }
            if (parameters.Count == 0)
            {
                throw Error.OutOfRange("parameters.Count", 1);
            }
            if (args.Length != parameters.Count)
            {
                throw new ArgumentOutOfRangeException("args");
            }
            if (this.IsStandardBinder)
            {
                returnType = this.ReturnType;
                if ((returnLabel.Type != typeof(void)) && !TypeUtils.AreReferenceAssignable(returnLabel.Type, returnType))
                {
                    throw Error.BinderNotCompatibleWithCallSite(returnType, this, returnLabel.Type);
                }
            }
            else
            {
                returnType = returnLabel.Type;
            }
            DynamicMetaObject target = DynamicMetaObject.Create(args[0], parameters[0]);

            DynamicMetaObject[] objArray = CreateArgumentMetaObjects(args, parameters);
            DynamicMetaObject   obj3     = this.Bind(target, objArray);

            if (obj3 == null)
            {
                throw Error.BindingCannotBeNull();
            }
            Expression          expression   = obj3.Expression;
            BindingRestrictions restrictions = obj3.Restrictions;

            if ((returnType != typeof(void)) && !TypeUtils.AreReferenceAssignable(returnType, expression.Type))
            {
                if (target.Value is IDynamicMetaObjectProvider)
                {
                    throw Error.DynamicObjectResultNotAssignable(expression.Type, target.Value.GetType(), this, returnType);
                }
                throw Error.DynamicBinderResultNotAssignable(expression.Type, this, returnType);
            }
            if ((this.IsStandardBinder && (args[0] is IDynamicMetaObjectProvider)) && (restrictions == BindingRestrictions.Empty))
            {
                throw Error.DynamicBindingNeedsRestrictions(target.Value.GetType(), this);
            }
            restrictions = AddRemoteObjectRestrictions(restrictions, args, parameters);
            if (expression.NodeType != ExpressionType.Goto)
            {
                expression = Expression.Return(returnLabel, expression);
            }
            if (restrictions != BindingRestrictions.Empty)
            {
                expression = Expression.IfThen(restrictions.ToExpression(), expression);
            }
            return(expression);
        }