コード例 #1
0
        private static bool TryBindToMethod(SyntaxTreeNode node, object methodName, ArgumentsTree arguments, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError)
        {
            boundExpression = null;
            bindingError    = null;

            var constructorDescription = default(MemberDescription);

            if (bindingContext.TryResolveMember(methodName, out constructorDescription) == false || constructorDescription.IsConstructor == false)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDCONSTRUCTOR, methodName), node);
                return(false);
            }

            var typeDescription = TypeDescription.GetTypeDescription(constructorDescription.DeclaringType);

            // feature: lambda building via new Func()
            var lambdaArgument = default(SyntaxTreeNode);

            if (typeDescription.IsDelegate && arguments.Count == 1 && (lambdaArgument = arguments.Values.Single()).GetExpressionType(throwOnError: true) == Constants.EXPRESSION_TYPE_LAMBDA)
            {
                return(LambdaBinder.TryBind(lambdaArgument, bindingContext, typeDescription, out boundExpression, out bindingError));
            }

            var constructorQuality = MemberDescription.QUALITY_INCOMPATIBLE;

            if (constructorDescription.TryMakeCall(null, arguments, bindingContext, out boundExpression, out constructorQuality))
            {
                return(true);
            }

            bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDCONSTRUCTOR, constructorDescription.DeclaringType), node);
            return(false);
        }
コード例 #2
0
        private static bool TryBindToType(SyntaxTreeNode node, object typeName, ArgumentsTree arguments, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError)
        {
            boundExpression = null;
            bindingError    = null;

            var type = default(Type);

            if (bindingContext.TryResolveType(typeName, out type) == false)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeName), node);
                return(false);
            }

            var typeDescription = TypeDescription.GetTypeDescription(type);

            // feature: lambda building via new Func()
            var lambdaArgument = default(SyntaxTreeNode);

            if (typeDescription.IsDelegate && arguments.Count == 1 && (lambdaArgument = arguments.Values.Single()).GetExpressionType(throwOnError: true) == Constants.EXPRESSION_TYPE_LAMBDA)
            {
                return(LambdaBinder.TryBind(lambdaArgument, bindingContext, typeDescription, out boundExpression, out bindingError));
            }

            var selectedConstructorQuality = MemberDescription.QUALITY_INCOMPATIBLE;

            foreach (var constructorDescription in typeDescription.Constructors)
            {
                var constructorQuality = MemberDescription.QUALITY_INCOMPATIBLE;
                var constructorCall    = default(Expression);
                if (constructorDescription.TryMakeCall(null, arguments, bindingContext, out constructorCall, out constructorQuality) == false)
                {
                    continue;
                }

                if (float.IsNaN(constructorQuality) || constructorQuality <= selectedConstructorQuality)
                {
                    continue;
                }

                boundExpression            = constructorCall;
                selectedConstructorQuality = constructorQuality;

                if (Math.Abs(constructorQuality - MemberDescription.QUALITY_EXACT_MATCH) < float.Epsilon)
                {
                    break;                     // best match
                }
            }

            if (boundExpression == null)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDCONSTRUCTOR, type), node);
                return(false);
            }

            return(true);
        }
コード例 #3
0
        private static void RenderArguments(ArgumentsTree arguments, StringBuilder builder, bool checkedScope)
        {
            if (arguments == null)
            {
                throw new ArgumentNullException("arguments");
            }
            if (builder == null)
            {
                throw new ArgumentNullException("builder");
            }

            var firstArgument = true;

            foreach (var argumentName in arguments.Keys)
            {
                var positionalArguments = new SortedDictionary <int, SyntaxTreeNode>();
                var namedArguments      = new SortedDictionary <string, SyntaxTreeNode>();
                var position            = default(int);
                if (int.TryParse(argumentName, out position))
                {
                    positionalArguments[position] = arguments[argumentName];
                }
                else
                {
                    namedArguments[argumentName] = arguments[argumentName];
                }

                foreach (var argument in positionalArguments.Values)
                {
                    if (!firstArgument)
                    {
                        builder.Append(", ");
                    }
                    Render(argument, builder, true, checkedScope);
                    firstArgument = false;
                }
                foreach (var argumentKv in namedArguments)
                {
                    if (!firstArgument)
                    {
                        builder.Append(", ");
                    }
                    builder.Append(argumentKv.Key).Append(": ");
                    Render(argumentKv.Value, builder, true, checkedScope);
                    firstArgument = false;
                }
            }
        }
コード例 #4
0
        public bool TryMakeCall(Expression target, ArgumentsTree argumentsTree, BindingContext bindingContext, out Expression expression, out float expressionQuality)
        {
            if (argumentsTree == null)
            {
                throw new ArgumentNullException("argumentsTree");
            }
            if (bindingContext == null)
            {
                throw new ArgumentNullException("bindingContext");
            }
            if (!this.IsStatic && !this.IsConstructor && target == null)
            {
                throw new ArgumentNullException("target");
            }

            expression        = null;
            expressionQuality = QUALITY_INCOMPATIBLE;

            if (this.parameters == null)             // not a method, constructor, indexer
            {
                return(false);
            }

            // check argument count
            if (argumentsTree.Count > this.parameters.Length)
            {
                return(false);                // not all arguments are bound to parameters
            }
            var requiredParametersCount = this.parameters.Length - this.parameters.Count(p => p.IsOptional);

            if (argumentsTree.Count < requiredParametersCount)
            {
                return(false);                // not all required parameters has values
            }
            // bind arguments
            var parametersQuality = 0.0f;
            var arguments         = default(Expression[]);

            foreach (var argumentName in argumentsTree.Keys)
            {
                var parameter      = default(ParameterInfo);
                var parameterIndex = 0;
                if (HasDigitsOnly(argumentName))
                {
                    parameterIndex = int.Parse(argumentName, Constants.DefaultFormatProvider);
                    if (parameterIndex >= this.parameters.Length)
                    {
                        return(false);                        // position out of range
                    }
                    parameter = this.parameters[parameterIndex];

                    if (argumentsTree.ContainsKey(parameter.Name))
                    {
                        return(false);                        // positional intersects named
                    }
                }
                else
                {
                    if (this.parametersByName.TryGetValue(argumentName, out parameter) == false)
                    {
                        return(false);                        // parameter is not found
                    }
                    parameterIndex = parameter.Position;
                }

                var expectedType = TypeDescription.GetTypeDescription(parameter.ParameterType);
                var argValue     = default(Expression);
                var bindingError = default(Exception);
                if (AnyBinder.TryBindInNewScope(argumentsTree[argumentName], bindingContext, expectedType, out argValue, out bindingError) == false)
                {
                    return(false);
                }

                Debug.Assert(argValue != null, "argValue != null");

                var quality = 0.0f;
                if (ExpressionUtils.TryMorphType(ref argValue, expectedType, out quality) == false || quality <= 0)
                {
                    return(false);                   // failed to bind parameter
                }
                parametersQuality += quality;        // casted
                if (arguments == null)
                {
                    arguments = new Expression[this.parameters.Length];
                }
                arguments[parameterIndex] = argValue;
            }

            if (this.parameters.Length > 0)
            {
                if (arguments == null)
                {
                    arguments = new Expression[this.parameters.Length];
                }
                for (var i = 0; i < arguments.Length; i++)
                {
                    if (arguments[i] != null)
                    {
                        continue;
                    }
                    var parameter = this.parameters[i];
                    if (parameter.IsOptional == false)
                    {
                        return(false);                        // missing required parameter
                    }
                    var typeDescription = TypeDescription.GetTypeDescription(parameter.ParameterType);
                    arguments[i]       = typeDescription.DefaultExpression;
                    parametersQuality += TypeConversion.QUALITY_SAME_TYPE;
                }

                expressionQuality = parametersQuality / this.parameters.Length;
            }
            else
            {
                expressionQuality = QUALITY_EXACT_MATCH;
            }


            if (this.member is MethodInfo)
            {
                if (this.IsStatic)
                {
                    expression = Expression.Call(this, arguments);
                }
                else if (this.Name == Constants.DELEGATE_INVOKE_NAME && this.DeclaringType.IsDelegate)
                {
                    expression = Expression.Invoke(target, arguments);
                }
                else
                {
                    expression = Expression.Call(target, this, arguments);
                }
                return(true);
            }
            else if (this.member is ConstructorInfo)
            {
                expression = Expression.New((ConstructorInfo)this.member, arguments);
                return(true);
            }
            else if (this.member is PropertyInfo)
            {
                if (this.IsStatic)
                {
                    expression = Expression.Call(this, arguments);
                }
                else
                {
                    expression = Expression.Call(target, this, arguments);
                }
                return(true);
            }
            expressionQuality = QUALITY_INCOMPATIBLE;
            return(false);
        }