Exemplo n.º 1
0
        public SourceText GetOutputTextForStoredProcedure(Definition.Schema schema, Definition.StoredProcedure storedProcedure)
        {
            var rootDir     = _output.GetOutputRootDir();
            var fileContent = File.ReadAllText(Path.Combine(rootDir.FullName, "DataContext", "Outputs", "Output.cs"));

            var tree = CSharpSyntaxTree.ParseText(fileContent);
            var root = tree.GetCompilationUnitRoot();

            // Replace Namespace
            if (_configFile.Config.Project.Role.Kind == ERoleKind.Lib)
            {
                root = root.ReplaceNamespace(ns => ns.Replace("Source.DataContext", _configFile.Config.Project.Output.Namespace).Replace("Schema", schema.Name));
            }
            else
            {
                root = root.ReplaceNamespace(ns => ns.Replace("Source", _configFile.Config.Project.Output.Namespace).Replace("Schema", schema.Name));
            }

            // Replace ClassName
            root = root.ReplaceClassName(ci => ci.Replace("Output", storedProcedure.GetOutputTypeName()));

            // Generate Properies
            // https://stackoverflow.com/questions/45160694/adding-new-field-declaration-to-class-with-roslyn
            var nsNode       = (NamespaceDeclarationSyntax)root.Members[0];
            var classNode    = (ClassDeclarationSyntax)nsNode.Members[0];
            var propertyNode = (PropertyDeclarationSyntax)classNode.Members[0];
            var outputs      = storedProcedure.Input?.Where(i => i.IsOutput).ToList() ?? new List <StoredProcedureInputModel>();

            foreach (var output in outputs)
            {
                nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
                classNode = (ClassDeclarationSyntax)nsNode.Members[0];

                var propertyIdentifier = TokenHelper.Parse(output.Name);
                propertyNode = propertyNode
                               .WithType(ParseTypeFromSqlDbTypeName(output.SqlTypeName, output.IsNullable ?? false));

                propertyNode = propertyNode
                               .WithIdentifier(propertyIdentifier);

                root = root.AddProperty(ref classNode, propertyNode);
            }

            // Remove template Property
            nsNode    = (NamespaceDeclarationSyntax)root.Members[0];
            classNode = (ClassDeclarationSyntax)nsNode.Members[0];
            root      = root.ReplaceNode(classNode, classNode.WithMembers(new SyntaxList <MemberDeclarationSyntax>(classNode.Members.Cast <PropertyDeclarationSyntax>().Skip(1))));

            return(root.NormalizeWhitespace().GetText());
        }
Exemplo n.º 2
0
        private MethodDeclarationSyntax GenerateStoredProcedureMethodText(MethodDeclarationSyntax methodNode, Definition.StoredProcedure storedProcedure, bool isOverload = false)
        {
            // Replace MethodName
            var methodName       = $"{storedProcedure.Name}Async";
            var methodIdentifier = SyntaxFactory.ParseToken(methodName);

            methodNode = methodNode.WithIdentifier(methodIdentifier);

            var parameters = new[] { SyntaxFactory.Parameter(SyntaxFactory.Identifier("input"))
                                     .WithType(SyntaxFactory.ParseTypeName($"{storedProcedure.Name}Input")) };

            var parameterList = methodNode.ParameterList;

            parameterList = parameterList.WithParameters(
                parameterList.Parameters.InsertRange(2, parameters).RemoveAt(1)
                );
            methodNode = methodNode.WithParameterList(parameterList);

            // Get Method Body as Statements
            var methodBody       = methodNode.Body;
            var statements       = methodBody.Statements.ToList();
            var returnExpression = (statements.Last() as ReturnStatementSyntax).Expression.GetText().ToString();

            if (isOverload)
            {
                returnExpression = returnExpression.Replace("CrudActionAsync", methodName);
            }
            else
            {
                // Generate Sql-Parameters
                var sqlParamSyntax      = (LocalDeclarationStatementSyntax)statements.Single(i => i is LocalDeclarationStatementSyntax);
                var sqlParamSyntaxIndex = statements.IndexOf(sqlParamSyntax);

                var arguments = new List <SyntaxNodeOrToken>();
                var inputs    = storedProcedure.Input.ToList();
                var lastInput = inputs.Last();
                inputs.ForEach(i =>
                {
                    var isLastItem = i == lastInput;

                    var args = new List <SyntaxNodeOrToken>();
                    args.Add(SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(i.Name.Remove(0, 1)))));
                    args.Add(SyntaxFactory.Token(SyntaxKind.CommaToken));
                    args.Add(SyntaxFactory.Argument(SyntaxFactory.IdentifierName($"input.{GetPropertyFromSqlInputTableType(i.Name)}")));

                    if (i.IsOutput)
                    {
                        args.Add(SyntaxFactory.Token(SyntaxKind.CommaToken));
                        args.Add(SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression)));
                    }

                    arguments.Add(SyntaxFactory.InvocationExpression(
                                      SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                           SyntaxFactory.IdentifierName("AppDbContext"),
                                                                           SyntaxFactory.IdentifierName((i.IsTableType ?? false) ? "GetCollectionParameter" : "GetParameter")))
                                  .WithArgumentList(SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList <ArgumentSyntax>(args))));

                    if (!isLastItem)
                    {
                        arguments.Add(SyntaxFactory.Token(SyntaxKind.CommaToken));
                    }
                });

                statements[sqlParamSyntaxIndex] = SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(SyntaxFactory.IdentifierName("var"))
                                                                                          .WithVariables(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier("parameters"))
                                                                                                                                              .WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                                                   SyntaxFactory.ObjectCreationExpression(
                                                                                                                                                                       SyntaxFactory.GenericName(
                                                                                                                                                                           SyntaxFactory.Identifier("List"))
                                                                                                                                                                       .WithTypeArgumentList(SyntaxFactory.TypeArgumentList(SyntaxFactory.SingletonSeparatedList <TypeSyntax>(SyntaxFactory.IdentifierName("SqlParameter")))))
                                                                                                                                                                   .WithInitializer(SyntaxFactory.InitializerExpression(SyntaxKind.CollectionInitializerExpression,
                                                                                                                                                                                                                        SyntaxFactory.SeparatedList <ExpressionSyntax>(arguments))))))));

                methodBody = methodBody.WithStatements(new SyntaxList <StatementSyntax>(statements.Skip(2)));

                returnExpression = returnExpression.Replace("schema.CrudAction", storedProcedure.SqlObjectName);
            }

            methodNode = methodNode.WithBody(methodBody);

            // Replace ReturnType and ReturnLine
            var returnType  = "Task<CrudResult>";
            var returnModel = "CrudResult";

            if (!storedProcedure.HasResult() && storedProcedure.HasOutputs())
            {
                var outputType = storedProcedure.GetOutputTypeName();

                returnType       = $"Task<{outputType}>";
                returnExpression = returnExpression.Replace("ExecuteSingleAsync<CrudResult>", $"ExecuteAsync<{outputType}>");
            }
            else if (storedProcedure.IsScalarResult())
            {
                var output = storedProcedure.Output.FirstOrDefault();
                returnModel = ParseTypeFromSqlDbTypeName(output.SqlTypeName, output.IsNullable ?? false).ToString();

                returnType       = $"Task<{returnModel}>";
                returnExpression = returnExpression.Replace("ExecuteSingleAsync<CrudResult>", $"ReadJsonAsync");
            }
            else
            {
                switch (storedProcedure.OperationKind)
                {
                case Definition.OperationKindEnum.Find:
                case Definition.OperationKindEnum.List:
                    returnModel = storedProcedure.Name;
                    break;
                }

                switch (storedProcedure.ResultKind)
                {
                case Definition.ResultKindEnum.Single:
                    returnType       = $"Task<{returnModel}>";
                    returnExpression = returnExpression.Replace("ExecuteSingleAsync<CrudResult>", $"ExecuteSingleAsync<{returnModel}>");
                    break;

                case Definition.ResultKindEnum.List:
                    returnType       = $"Task<List<{returnModel}>>";
                    returnExpression = returnExpression.Replace("ExecuteSingleAsync<CrudResult>", $"ExecuteListAsync<{returnModel}>");
                    break;
                }
            }

            methodNode = methodNode.WithReturnType(SyntaxFactory.ParseTypeName(returnType).WithTrailingTrivia(SyntaxFactory.Space));

            var returnStatementSyntax      = statements.Single(i => i is ReturnStatementSyntax);
            var returnStatementSyntaxIndex = statements.IndexOf(returnStatementSyntax);

            statements[returnStatementSyntaxIndex] = SyntaxFactory.ReturnStatement(SyntaxFactory.ParseExpression(returnExpression).WithLeadingTrivia(SyntaxFactory.Space))
                                                     .WithLeadingTrivia(SyntaxFactory.Tab, SyntaxFactory.Tab, SyntaxFactory.Tab)
                                                     .WithTrailingTrivia(SyntaxFactory.CarriageReturn);

            methodBody = methodBody.WithStatements(new SyntaxList <StatementSyntax>(statements));
            methodNode = methodNode.WithBody(methodBody);

            return(methodNode.NormalizeWhitespace());
        }