Ejemplo n.º 1
0
 internal void Push(QueryMethod method) => methodsStack.Push(method);
Ejemplo n.º 2
0
        public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node)
        {
            var methodSymbol = SemanticModel.GetSymbolInfo(node.Expression).Symbol as IMethodSymbol;
            //先判断有无拦截器
            var interceptor = GetInvocationInterceptor(methodSymbol);

            if (interceptor != null)
            {
                return(interceptor.VisitInvocation(node, methodSymbol, this));
            }

            //再判断是否在QueryMethod的Lambda内
            //if (queryMethodCtx.HasAny && queryMethodCtx.Current.InLambdaExpression)
            //    return base.VisitInvocationExpression(node);

            bool needPopQueryMethod = false;

            if (methodSymbol != null)
            {
                var ownerType = methodSymbol.ContainingType;
                if (TypeHelper.IsQuerialbeClass(ownerType, out bool isSystemQuery) &&
                    TypeHelper.IsQueryMethod(methodSymbol))    //注意:只处理相关QueryMethods
                {
                    //设置当前查询方法上下文
                    var queryMethod = new QueryMethod()
                    {
                        IsSystemQuery    = isSystemQuery, //是否系统存储的查询,否则是Sql查询
                        MethodName       = methodSymbol.Name,
                        ArgsCount        = node.ArgumentList.Arguments.Count,
                        Identifiers      = null,
                        LambdaParameters = null
                    };
                    queryMethodCtx.Push(queryMethod); //支持嵌套
                    needPopQueryMethod = true;

                    if (!queryMethod.IsIncludeMethod) //排除Include类方法
                    {
                        //注意:目前只支持所有的非Lambda参数为IdentifierNameSyntax
                        queryMethod.Identifiers      = new IdentifierNameSyntax[queryMethod.ArgsCount];
                        queryMethod.LambdaParameters = new string[queryMethod.ArgsCount];
                        queryMethod.Identifiers[0]   = GetIdentifier(node.Expression); //指向自己
                        if (queryMethod.ArgsCount > 1)
                        {
                            //注意:这里不移除无效的参数节点,由VisitArgumentList()处理
                            for (int i = 0; i < queryMethod.ArgsCount - 1; i++)
                            {
                                queryMethod.Identifiers[i + 1] = (IdentifierNameSyntax)node.ArgumentList.Arguments[i].Expression;
                            }
                        }
                    }
                }
                else if (methodSymbol.Name == "ToString" && ownerType.ToString() == "System.Enum") //处理虚拟枚举值的ToString
                {
                    if (node.Expression is MemberAccessExpressionSyntax memberAccess)
                    {
                        var ownerSymbol = SemanticModel.GetSymbolInfo(memberAccess.Expression).Symbol;
                        if (ownerSymbol is IFieldSymbol) //eg: sys.Enums.Gender.Male.ToString() => "Male"
                        {
                            if (TypeHelper.IsEnumModel(ownerSymbol.ContainingType))
                            {
                                return(SyntaxFactory.ParseExpression($"\"{ownerSymbol.Name}\"").WithTriviaFrom(node));
                            }
                        }
                    }
                }
                //TODO:处理Enum.Parse等方法
            }

            var res = (InvocationExpressionSyntax)base.VisitInvocationExpression(node);

            if (needPopQueryMethod)
            {
                //注意:将ToScalar转换为ToScalar<T>
                if (queryMethodCtx.Current.MethodName == TypeHelper.SqlQueryToScalarMethod)
                {
                    var memberAccess   = (MemberAccessExpressionSyntax)node.Expression;
                    var newGenericName = (SimpleNameSyntax)SyntaxFactory.ParseName($"ToScalar<{methodSymbol.TypeArguments[0]}>");
                    memberAccess = memberAccess.WithName(newGenericName);
                    res          = res.WithExpression(memberAccess);
                }
                queryMethodCtx.Pop();
            }

            return(res);
        }