Exemplo n.º 1
0
        internal Type ReadType(string typeName = null, bool ignoreException = false)
        {
            Type          type    = null;
            StringBuilder sbValue = new StringBuilder(string.IsNullOrEmpty(typeName) ? spResult.Next().Text : typeName);

            do
            {
                // 读取参数
                if (spResult.IsGenericType())
                {
                    spResult.Skip();
                    List <Type> types = new List <Type>();
                    while (true)
                    {
                        types.Add(ReadType());
                        if (spResult.PeekNext().Is(OperatorWord.Comma))
                        {
                            spResult.Skip();
                        }
                        else
                        {
                            break;
                        }
                    }
                    spResult.Next().Is(OperatorWord.RightAngleBracket, true);

                    sbValue.AppendFormat("`{0}[{1}]", types.Count, string.Join(",", types.Select(p => "[" + p.AssemblyQualifiedName + "]").ToArray()));
                }

                type = GetType(sbValue.ToString());
                if (type == null)
                {
                    var token = spResult.Next();
                    if (!token.Is(OperatorWord.Dot))
                    {
                        if (ignoreException)
                        {
                            break;
                        }

                        throw new ArgumentException(string.Format("Unsupported {0}", token.Text));
                    }
                    sbValue.Append(".");
                    sbValue.Append(spResult.Next().Text);
                }
            } while (type == null);

            return(type);
        }
        /// <summary>
        /// 读取下一个表达式
        /// </summary>
        /// <param name="level">优先级别</param>
        /// <param name="previousResult">已读取的表达式</param>
        /// <returns>ReadResult</returns>
        private ReadResult ReadNextExpression(int level, ReadResult previousResult)
        {
            var   result = previousResult;
            Token token  = spResult.Next();

            switch (token.Type)
            {
            case TokenType.End:
                result.IsClosedWrap = true;
                break;

            case TokenType.Identifier:
                if (OperatorWord.TypeExpressions.ContainsKey(token.Text))
                {
                    result.Expression = OperatorWord.TypeExpressions[token.Text](result.Expression, typeParser.ReadType());
                }
                else
                {
                    throw new ArgumentException(string.Format("Unsupported Identifier Operator {0}", token.Text));
                }
                break;

            case TokenType.Operator:
                if (token.Is(OperatorWord.RightBracket) || token.Is(OperatorWord.RightSquareBracket) || token.Is(OperatorWord.RightBigBracket))
                {
                    result.IsClosedWrap = true;
                }
                else if (token.Is(OperatorWord.LeftSquareBracket))
                {
                    if (result.Expression.Type.IsArray)
                    {
                        result.Expression = Expression.ArrayIndex(result.Expression, ReadExpression(level).Expression);
                    }
                    else
                    {
                        string indexerName = "Item";

                        var indexerNameAtt = result.Expression.Type.GetCustomAttributes(typeof(DefaultMemberAttribute), true).Cast <DefaultMemberAttribute>().SingleOrDefault();
                        if (indexerNameAtt != null)
                        {
                            indexerName = indexerNameAtt.MemberName;
                        }

                        var methodInfo = result.Expression.Type.GetProperty(indexerName).GetGetMethod();
                        var @params    = GetCollectionInits(true).ToArray();

                        result.Expression = Expression.Call(result.Expression, methodInfo, @params);
                    }
                }
                else if (token.Is(OperatorWord.Dot))
                {
                    token = spResult.Next();
                    if (token.Type != TokenType.Identifier)
                    {
                        throw new ArgumentException("Behind the dot should be Identifier");
                    }

                    // 获取尖括号 <> 中的类型数据
                    Type[] types = Type.EmptyTypes;
                    if (spResult.IsGenericType())
                    {
                        types = GetTypes();
                    }

                    if (spResult.PeekNext().Is(OperatorWord.LeftBracket))
                    {
                        var @params = GetCollectionInits().ToArray();
                        var method  = FindBestMethod(result.Expression.Type, token.Text, @params, false, types);
                        result.Expression = Expression.Call(result.Expression, method, @params);
                    }
                    else
                    {
                        var member = result.Expression.Type.GetMember(token.Text)[0];
                        if (member.MemberType == MemberTypes.Property)
                        {
                            result.Expression = Expression.Property(result.Expression, (PropertyInfo)member);
                        }
                        else
                        {
                            result.Expression = Expression.Field(result.Expression, (FieldInfo)member);
                        }
                    }
                }
                else
                {
                    var right = ReadExpression(level);
                    // 字符串拼接
                    if (token.Is(OperatorWord.Plus) && (result.Expression.Type == typeof(string) || right.Expression.Type == typeof(string)))
                    {
                        var type = typeof(object);
                        result.Expression = Expression.Convert(result.Expression, type);
                        right.Expression  = Expression.Convert(right.Expression, type);
                        result.Expression = Expression.Call(typeof(string).GetMethod("Concat", new Type[] { type, type }), result.Expression, right.Expression);
                    }
                    else if (OperatorWord.BinaryExpressions.ContainsKey(token.Text))
                    {
                        ImplicitConvert(ref result, ref right);
                        result.Expression = OperatorWord.BinaryExpressions[token.Text](result.Expression, right.Expression);
                    }
                    else if (token.Is(OperatorWord.Question))
                    {
                        var next = spResult.Next();
                        if (next.Is(OperatorWord.Colon))
                        {
                            var third = ReadExpression(level);
                            result.Expression   = Expression.Condition(result.Expression, right.Expression, third.Expression);
                            result.IsClosedWrap = result.IsClosedWrap || right.IsClosedWrap || third.IsClosedWrap;
                        }
                        else
                        {
                            throw new ArgumentException(string.Format("{0} does not match {1}", OperatorWord.Question, OperatorWord.Colon));
                        }
                    }
                    else if (token.Is(OperatorWord.DoubleQuestion))
                    {
                        var test = Expression.Equal(result.Expression, Expression.Constant(null, result.Expression.Type));
                        result.Expression = Expression.Condition(test, right.Expression, result.Expression);
                    }
                    else
                    {
                        throw new ArgumentException(string.Format("Unsupported Operator {0}", token.Text));
                    }

                    result.IsClosedWrap = result.IsClosedWrap || right.IsClosedWrap;
                }
                break;

            default:
                throw new ArgumentException(string.Format("Unsupported TokenType {0}", token.Type));
            }

            return(result);
        }