System.Dynamic.DynamicMetaObjectBinder.Bind C# (CSharp) Method

Bind() public final method

Performs the runtime binding of the dynamic operation on a set of arguments.
public final Bind ( object args, ReadOnlyCollection parameters, LabelTarget returnLabel ) : Expression
args object An array of arguments to the dynamic operation.
parameters ReadOnlyCollection The array of instances that represent the parameters of the call site in the binding process.
returnLabel System.Linq.Expressions.LabelTarget A LabelTarget used to return the result of the dynamic binding.
return System.Linq.Expressions.Expression
        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;
        }

Same methods

DynamicMetaObjectBinder::Bind ( DynamicMetaObject target, DynamicMetaObject args ) : DynamicMetaObject

Usage Example

Esempio n. 1
0
        private static Expression ApplyBinder(DynamicMetaObjectBinder binder, bool throwException, params Expression[] expressions)
        {
            var result = binder.Bind(DynamicMetaObject.Create(null, expressions[0]),
                expressions.Skip(1).Select(e =>
                    DynamicMetaObject.Create(null, e)).ToArray()
            );

            if (result.Expression.NodeType == ExpressionType.Convert)
            {
                var convert = (UnaryExpression)result.Expression;
                return convert.Operand;
            }
            if (result.Expression.NodeType == ExpressionType.Throw)
            {
                if (throwException)
                {
                    // throw the exception
                    Expression.Lambda(result.Expression).Compile().DynamicInvoke();
                }
                else return null;
            }
            return result.Expression;
        }