65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 ASP.NET Core 的自定义代码生成器

starIconstarIconstarIconstarIconstarIcon

5.00/5 (16投票s)

2018 年 5 月 2 日

CPOL

3分钟阅读

viewsIcon

37986

downloadIcon

933

在本文中,我们将概述并使用我们的数据库表列生成基本级别的代码,这将有助于开发。

引言

这个示例背后的主要想法是轻松生成常见类型的代码。

单页应用程序使用 ASP.NET Core 和 AngularJS 构建。 这是执行环境,API 服务在 .NET Core 中生成代码。 在前端,我使用了 AngularJS。

内容聚焦

  • 连接到数据库服务器
  • 获取所有数据库列表,然后
  • 通过选择特定表来获取所有表列
  • 选择列,然后
  • 生成代码,就是这样

让我们深入研究代码,首先让我们从后端工作开始。 我们使用连接字符串连接我们的数据库服务器。

让我们处理后端,连接到数据库

让我们创建一个 API 控制器来完成所有操作。 在我们的控制器类中,让我们放置一个连接字符串以连接我们的数据库。

private string conString = "server=DESKTOP-80DEJMQ; uid=sa; pwd=sa@12345;";

获取所有数据库

让我们创建一个方法来从数据库服务器获取所有数据库列表。 以下是获取所有数据库的 SQL 查询。

SELECT name from sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb') _
ORDER BY create_date

这是 Get 方法,用于列出服务器中的所有数据库。

// api/Codegen/GetDatabaseList
[HttpGet, Route("GetDatabaseList"), Produces("application/json")]
public List<vmDatabase> GetDatabaseList()
{
    List<vmDatabase> data = new List<vmDatabase>();
    using (SqlConnection con = new SqlConnection(conString))
    {
        int count = 0; con.Open();
        using (SqlCommand cmd = new SqlCommand("SELECT name from sys.databases _
         WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb') ORDER BY create_date", con))
        {
            using (IDataReader dr = cmd.ExecuteReader())
            {
                while (dr.Read())
                {
                    count++;
                    data.Add(new vmDatabase()
                    {
                        DatabaseId = count,
                        DatabaseName = dr[0].ToString()
                    });
                }
            }
        }
    }
    return data.ToList();
}

获取所有表列

在这里,我们从选定的数据库中获取所有表。

// api/Codegen/GetDatabaseTableList
[HttpPost, Route("GetDatabaseTableList"), Produces("application/json")]
public List<vmTable> GetDatabaseTableList([FromBody]vmParam model)
{
    List<vmTable> data = new List<vmTable>();
    string conString_ = conString + " Database=" + model.DatabaseName + ";";
    using (SqlConnection con = new SqlConnection(conString_))
    {
        int count = 0; con.Open();
        DataTable schema = con.GetSchema("Tables");
        foreach (DataRow row in schema.Rows)
        {
            count++;
            data.Add(new vmTable()
            {
                TableId = count,
                TableName = row[2].ToString()
            });
        }
    }

    return data.ToList();
}

选择列

以下是获取所有表列的 SQL 查询。

SELECT COLUMN_NAME, DATA_TYPE, ISNULL(CHARACTER_MAXIMUM_LENGTH,0), _
IS_NULLABLE, TABLE_SCHEMA FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '" + _
model.TableName + "' ORDER BY ORDINAL_POSITION

这是 Get 方法,用于列出服务器中所有选定的表列。

// api/Codegen/GetDatabaseTableColumnList
[HttpPost, Route("GetDatabaseTableColumnList"), Produces("application/json")]
public List<vmColumn> GetDatabaseTableColumnList([FromBody]vmParam model)
{
    List<vmColumn> data = new List<vmColumn>();
    string conString_ = conString + " Database=" + model.DatabaseName + ";";
    using (SqlConnection con = new SqlConnection(conString_))
    {
        int count = 0; con.Open();
        using (SqlCommand cmd = new SqlCommand("SELECT COLUMN_NAME, DATA_TYPE, _
               ISNULL(CHARACTER_MAXIMUM_LENGTH,0), IS_NULLABLE, _
               TABLE_SCHEMA FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '" + _
               model.TableName + "' ORDER BY ORDINAL_POSITION", con))
        {
            using (IDataReader dr = cmd.ExecuteReader())
            {
                while (dr.Read())
                {
                    count++;
                    data.Add(new vmColumn()
                    {
                        ColumnId = count,
                        ColumnName = dr[0].ToString(),
                        DataType = dr[1].ToString(),
                        MaxLength = dr[2].ToString(),
                        IsNullable = dr[3].ToString(),
                        Tablename = model.TableName.ToString(),
                        TableSchema = dr[4].ToString()
                    });
                }
            }
        }
    }
    return data.ToList();
}

现在让我们概述一下服务器代码,该代码基于我们的数据库列生成生成的代码。

[EnableCors("AllowCors"), Produces("application/json"), Route("api/Codegen")]
public class CodegenController : Controller
{
    private readonly IHostingEnvironment _hostingEnvironment;
    private string conString = "server=DESKTOP-80DEJMQ; uid=sa; pwd=sa@12345;";

    public CodegenController(IHostingEnvironment hostingEnvironment)
    {
        _hostingEnvironment = hostingEnvironment;
    }

    #region ++++++ Database +++++++
    // api/Codegen/GetDatabaseList
    [HttpGet, Route("GetDatabaseList"), Produces("application/json")]
    public List<vmDatabase> GetDatabaseList()
    {
        List<vmDatabase> data = new List<vmDatabase>();
        using (SqlConnection con = new SqlConnection(conString))
        {
            int count = 0; con.Open();
            using (SqlCommand cmd = new SqlCommand("SELECT name from sys.databases _
            WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb') ORDER BY create_date", con))
            {
                using (IDataReader dr = cmd.ExecuteReader())
                {
                    while (dr.Read())
                    {
                        count++;
                        data.Add(new vmDatabase()
                        {
                            DatabaseId = count,
                            DatabaseName = dr[0].ToString()
                        });
                    }
                }
            }
        }
        return data.ToList();
    }

    // api/Codegen/v
    [HttpPost, Route("GetDatabaseTableList"), Produces("application/json")]
    public List<vmTable> GetDatabaseTableList([FromBody]vmParam model)
    {
        List<vmTable> data = new List<vmTable>();
        string conString_ = conString + " Database=" + model.DatabaseName + ";";
        using (SqlConnection con = new SqlConnection(conString_))
        {
            int count = 0; con.Open();
            DataTable schema = con.GetSchema("Tables");
            foreach (DataRow row in schema.Rows)
            {
                count++;
                data.Add(new vmTable()
                {
                    TableId = count,
                    TableName = row[2].ToString()
                });
            }
        }

        return data.ToList();
    }

    // api/Codegen/GetDatabaseTableColumnList
    [HttpPost, Route("GetDatabaseTableColumnList"), Produces("application/json")]
    public List<vmColumn> GetDatabaseTableColumnList([FromBody]vmParam model)
    {
        List<vmColumn> data = new List<vmColumn>();
        string conString_ = conString + " Database=" + model.DatabaseName + ";";
        using (SqlConnection con = new SqlConnection(conString_))
        {
            int count = 0; con.Open();
            using (SqlCommand cmd = new SqlCommand("SELECT COLUMN_NAME, DATA_TYPE, _
                   ISNULL(CHARACTER_MAXIMUM_LENGTH,0), IS_NULLABLE, _
                   TABLE_SCHEMA FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '" + _
                   model.TableName + "' ORDER BY ORDINAL_POSITION", con))
            {
                using (IDataReader dr = cmd.ExecuteReader())
                {
                    while (dr.Read())
                    {
                        count++;
                        data.Add(new vmColumn()
                        {
                            ColumnId = count,
                            ColumnName = dr[0].ToString(),
                            DataType = dr[1].ToString(),
                            MaxLength = dr[2].ToString(),
                            IsNullable = dr[3].ToString(),
                            Tablename = model.TableName.ToString(),
                            TableSchema = dr[4].ToString()
                        });
                    }
                }
            }
        }
        return data.ToList();
    }
    #endregion

    #region +++++ CodeGeneration +++++
    // api/Codegen/GenerateCode
    [HttpPost, Route("GenerateCode"), Produces("application/json")]
    public IActionResult GenerateCode([FromBody]object[] data)
    {
        List<string> spCollection = new List<string>();
        try
        {
            string webRootPath = _hostingEnvironment.WebRootPath; //From wwwroot
            string contentRootPath = _hostingEnvironment.ContentRootPath; //From Others
            var tblColumns = JsonConvert.DeserializeObject<List<vmColumn>>(data[0].ToString());
            
            string fileContentSet = string.Empty; string fileContentGet = string.Empty;
            string fileContentPut = string.Empty; string fileContentDelete = string.Empty;
            string fileContentVm = string.Empty; string fileContentView = string.Empty;
            string fileContentNg = string.Empty; string fileContentAPIGet = string.Empty;
            string fileContentAPIGetById = string.Empty;

            //SP
            fileContentSet = SpGenerator.GenerateSetSP(tblColumns, webRootPath);
            fileContentGet = SpGenerator.GenerateGetSP(tblColumns, webRootPath);
            fileContentPut = SpGenerator.GeneratePutSP(tblColumns, webRootPath);
            fileContentDelete = SpGenerator.GenerateDeleteSP(tblColumns, webRootPath);
            spCollection.Add(fileContentSet);
            spCollection.Add(fileContentGet);
            spCollection.Add(fileContentPut);
            spCollection.Add(fileContentDelete);

            //VM
            fileContentVm = VmGenerator.GenerateVm(tblColumns, webRootPath);
            spCollection.Add(fileContentVm);

            //VU
            fileContentView = ViewGenerator.GenerateForm(tblColumns, webRootPath);
            spCollection.Add(fileContentView);

            //NG
            fileContentNg = NgGenerator.GenerateNgController(tblColumns, webRootPath);
            spCollection.Add(fileContentNg);

            //API
            fileContentAPIGet = APIGenerator.GenerateAPIGet(tblColumns, webRootPath);
            spCollection.Add(fileContentAPIGet);
        }
        catch (Exception ex)
        {
            ex.ToString();
        }

        return Json(new
        {
            spCollection
        });
    }

    #endregion
}

在我们的代码生成机制中,.txt 模板用于表示真实的结构。 在下面的文件夹中,我们拥有所有格式化的模板,以在生成的代码中呈现真实的结构。

 

让我们展开生成器。 这是我们通过此应用程序生成的列表。

  1. API 控制器
  2. ViewModel
  3. 存储过程
  4. AngularJS 控制器
  5. HTML-Form

API-Generator

下面的代码方法将使用格式化的文本文件生成 API 控制器。

public static dynamic GenerateAPIGet(List<vmColumn> tblColumns, string contentRootPath)
{
    TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
    StringBuilder builderPrm = new StringBuilder();
    StringBuilder builderSub = new StringBuilder();
    builderPrm.Clear(); builderSub.Clear();
    string fileContent = string.Empty; string queryPrm = string.Empty; string submitPrm = string.Empty;

    string tableName = tblColumns[0].Tablename; string tableSchema = tblColumns[0].TableSchema;
    string path = @"" + contentRootPath + "\\template\\WebAPI\\APIController.txt";

    // API Controller
    string routePrefix = "api/" + textInfo.ToTitleCase
                          (Conversion.RemoveSpecialCharacters(tableName.ToString()));
    string apiController = textInfo.ToTitleCase
                           (Conversion.RemoveSpecialCharacters(tableName.ToString())) + "Controller";
    string collectionName = "List<" + tableName.ToString() + ">";
    string listObj = tableName.ToString() + "s";
    string getDbMethod = "_ctx." + tableName.ToString() + ".ToListAsync()";
    string entity = tableName.ToString();
    string urlApiGet = "api/" + textInfo.ToTitleCase
                       (Conversion.RemoveSpecialCharacters(tableName.ToString())) + "/GetAll";
    string urlApiGetByID = "api/" + textInfo.ToTitleCase
                       (Conversion.RemoveSpecialCharacters(tableName.ToString())) + "/GetByID/5";
    string urlApiPost = "api/" + textInfo.ToTitleCase
                       (Conversion.RemoveSpecialCharacters(tableName.ToString())) + "/Save";
    string urlApiPut = "api/" + textInfo.ToTitleCase
                       (Conversion.RemoveSpecialCharacters(tableName.ToString())) + "/UpdateByID/5";
    string urlApiDeleteByID = "api/" + textInfo.ToTitleCase
                       (Conversion.RemoveSpecialCharacters(tableName.ToString())) + "/DeleteByID/5";

    //Enity Fields
    foreach (var item in tblColumns)
    {
        //parameter
        builderPrm.AppendLine();
        builderPrm.Append("entityUpdate." + item.ColumnName + " = model." + item.ColumnName + ";");
    }
    submitPrm = builderPrm.AppendLine().ToString();

    using (StreamReader sr = new StreamReader(path, Encoding.UTF8))
    {
        fileContent = sr.ReadToEnd()
            .Replace("#RoutePrefix", routePrefix.ToString())
            .Replace("#APiController", apiController.ToString())
            .Replace("#Collection", collectionName.ToString())
            .Replace("#ListObj", listObj.ToString())
            .Replace("#DbMethod", getDbMethod.ToString())
            .Replace("#Entity", entity.ToString())
            .Replace("#UrlApiGet", urlApiGet.ToString())
            .Replace("#UrlGetByID", urlApiGetByID.ToString())
            .Replace("#UrlPostByID", urlApiPost.ToString())
            .Replace("#UrlApiPut", urlApiPut.ToString())
            .Replace("#ColUpdate", submitPrm.ToString())
            .Replace("#UrlDeleteByID", urlApiDeleteByID.ToString());
    }

    return fileContent.ToString();
}

API 控制器格式

在本部分中,我们像这样读取文本直到末行,然后使用 C# 动态替换这些 #tag 属性。 这是用于其他代码生成的主要技巧。

[Route("#RoutePrefix"), Produces("application/json")]
public class #APiController : Controller
{
    private dbContext _ctx = null;
    public #APiController(dbContext context)
    {
        _ctx = context;
    }

    // GET: #UrlApiGet
    [HttpGet, Route("GetAll")]
    public async Task<object> GetAll()
    {
        #Collection #ListObj = null;
        try
        {
            using (_ctx)
            {
                #ListObj = await #DbMethod;
            }
        }
        catch (Exception ex)
        {
            ex.ToString();
        }
        return #ListObj;
    }

    // GET #UrlGetByID
    [HttpGet, Route("GetByID/{id}")]
    public async Task<#Entity> GetByID(int id)
    {
        #Entity obj = null;
        try
        {
            using (_ctx)
            {
                obj = await _ctx.#Entity.FirstOrDefaultAsync(x => x.Id == id);
            }
        }
        catch (Exception ex)
        {
            ex.ToString();
        }
        return obj;
    }


    // POST #UrlPostByID 
    [HttpPost, Route("Save")]
    public async Task<object> Save([FromBody]#Entity model)
    {
        object result = null; string message = "";
        if (model == null)
        {
            return BadRequest();
        }
        using (_ctx)
        {
            using (var _ctxTransaction = _ctx.Database.BeginTransaction())
            {
                try
                {
                    _ctx.#Entity.Add(model);
                    await _ctx.SaveChangesAsync();
                    _ctxTransaction.Commit();
                    message = "Ok";
                }
                catch (Exception e)
                {
                    _ctxTransaction.Rollback();
                    e.ToString();
                    message = "Error";
                }

                result = new
                {
                    message
                };
            }
        }
        return result;
    }

    // PUT #UrlApiPut 
    [HttpPut, Route("UpdateByID/{id}")]
    public async Task<object> UpdateByID(int id, [FromBody]#Entity model)
    {
        object result = null; string message = string.Empty;
        if (model == null)
        {
            return BadRequest();
        }
        using (_ctx)
        {
            using (var _ctxTransaction = _ctx.Database.BeginTransaction())
            {
                try
                {
                    var entityUpdate = _ctx.#Entity.FirstOrDefault(x => x.Id == id);
                    if (entityUpdate != null)
                    {
                        #ColUpdate

                        await _ctx.SaveChangesAsync();
                    }
                    _ctxTransaction.Commit();
                    message = "Ok";
                }
                catch (Exception e)
                {
                    _ctxTransaction.Rollback(); e.ToString();
                    message = "Error";
                }

                result = new
                {
                    message
                };
            }
        }
        return result;
    }

    // DELETE #UrlDeleteByID
    [HttpDelete, Route("DeleteByID/{id}")]
    public async Task<object> DeleteByID(int id)
    {
        object result = null; string message = "";
        using (_ctx)
        {
            using (var _ctxTransaction = _ctx.Database.BeginTransaction())
            {
                try
                {
                    var idToRemove = _ctx.#Entity.SingleOrDefault(x => x.Id == id);
                    if (idToRemove != null)
                    {
                        _ctx.#Entity.Remove(idToRemove);
                        await _ctx.SaveChangesAsync();
                    }
                    _ctxTransaction.Commit();
                    message = "Ok";
                }
                catch (Exception e)
                {
                    _ctxTransaction.Rollback(); 
					e.ToString();
                    message = "Error";
                }

                result = new
                {
                    message
                };
            }
        }
        return result;
    }
}

ViewModel-Generator

对于特定的数据模型,我们需要生成一些视图模型。 下面的方法将生成这些数据模型。

public static dynamic GenerateVm(List<vmColumn> tblColumns, string contentRootPath)
{
    StringBuilder builderPrm = new StringBuilder();
    StringBuilder builderBody = new StringBuilder();
    builderPrm.Clear(); builderBody.Clear();
    string fileContent = string.Empty; string queryPrm = string.Empty;

    string tableName = tblColumns[0].Tablename; string tableSchema = tblColumns[0].TableSchema;
    string path = @"" + contentRootPath + "\\template\\ViewModel\\vmModel.txt";
    string className = "vm" + tableName.ToString();
    foreach (var item in tblColumns)
    {
        //parameter
        builderPrm.AppendLine();
        builderPrm.Append("  public " + TypeMap.GetClrType(item.DataType) + " " + 
                           item.ColumnName + " { get; set; }");
    }

    queryPrm = builderPrm.AppendLine().ToString();

    using (StreamReader sr = new StreamReader(path, Encoding.UTF8))
    {
        fileContent = sr.ReadToEnd().Replace("#ClassName", 
                      className.ToString()).Replace("#Properties", queryPrm.ToString());
    }

    return fileContent.ToString();
}

Stored Procedure-Generator

Insert-SP

这是插入操作的最小标签 sp 生成查询模板,在应用程序中,我们需要使用我们自己的附加逻辑来修改这些模板。

//CREATE
public static dynamic GenerateSetSP(List<vmColumn> tblColumns, string contentRootPath)
{
    StringBuilder builderPrm = new StringBuilder();
    StringBuilder builderBody = new StringBuilder();
    builderPrm.Clear(); builderBody.Clear();

    string path = @"" + contentRootPath + "\\template\\StoredProcedure\\InsertSP.txt";
    string fileContent = string.Empty; string fileld = string.Empty; 
                         string fileldPrm = string.Empty; string queryPrm = string.Empty;
    string tableName = tblColumns[0].Tablename; string tableSchema = tblColumns[0].TableSchema;

    string spName = ("[" + tableSchema + "].[Set_" + tableName + "]").ToString();
    foreach (var item in tblColumns)
    {
        fileld = fileld + item.ColumnName + ",";
        fileldPrm = fileldPrm + "@" + item.ColumnName + ",";

        //parameter
        builderPrm.AppendLine();
        if ((item.DataType.ToString() == "nvarchar") || (item.DataType.ToString() == "varchar"))
            builderPrm.Append("  @" + item.ColumnName + " " + 
                              item.DataType + "(" + item.MaxLength + "),");
        else
            builderPrm.Append("  @" + item.ColumnName + " " + item.DataType + ",");
    }

    queryPrm = builderPrm.Remove((builderPrm.Length - 1), 1).AppendLine().ToString();
    //queryPrm = builderPrm.ToString().TrimEnd(',');

    //Body
    builderBody.Append("INSERT INTO [" + tableSchema + "].[" + tableName + "](");
    builderBody.Append(fileld.TrimEnd(',') + ") ");
    //builderBody.AppendLine();
    builderBody.Append("VALUES (" + fileldPrm.TrimEnd(',') + ")");

    using (StreamReader sr = new StreamReader(path, Encoding.UTF8))
    {
        fileContent = sr.ReadToEnd().Replace("#Name", spName.ToString()).Replace
                      ("#Param", queryPrm.ToString()).Replace("#Body", builderBody.ToString());
    }

    return fileContent.ToString();
}

Get-SP

这是获取操作的最小标签 sp 生成查询模板,在应用程序中,我们需要使用我们自己的附加逻辑来修改这些模板。

//READ
public static dynamic GenerateGetSP(List<vmColumn> tblColumns, string contentRootPath)
{
    StringBuilder builderPrm = new StringBuilder();
    StringBuilder builderBody = new StringBuilder();
    builderPrm.Clear(); builderBody.Clear();

    string path = @"" + contentRootPath + "\\template\\StoredProcedure\\ReadSP.txt";
    string fileContent = string.Empty; string fileld = string.Empty; 
                         string fileldPrm = string.Empty; string queryPrm = string.Empty;
    string tableName = tblColumns[0].Tablename; string tableSchema = tblColumns[0].TableSchema;

    string spName = ("[" + tableSchema + "].[Get_" + tableName + "]").ToString();
    foreach (var item in tblColumns)
    {
        fileld = fileld + item.ColumnName + ",";
        fileldPrm = fileldPrm + "@" + item.ColumnName + ",";
    }

    //Body
    builderBody.Append("SELECT " + fileldPrm.TrimEnd(',') + 
                       " FROM [" + tableSchema + "].[" + tableName + "]");

    using (StreamReader sr = new StreamReader(path, Encoding.UTF8))
    {
        fileContent = sr.ReadToEnd().Replace("#Name", spName.ToString()).Replace
           ("#Body", builderBody.ToString()).Replace("#OrdPrm", fileldPrm.TrimEnd(',').ToString());
    }

    return fileContent.ToString();
}

Update-SP

这是更新操作的最小标签 sp 生成查询模板,在应用程序中,我们需要使用我们自己的附加逻辑来修改这些模板。

//UPDATE
public static dynamic GeneratePutSP(List<vmColumn> tblColumns, string contentRootPath)
{
    StringBuilder builderPrm = new StringBuilder();
    StringBuilder builderBody = new StringBuilder();
    builderPrm.Clear(); builderBody.Clear();

    string path = @"" + contentRootPath + "\\template\\StoredProcedure\\UpdateSP.txt";
    string fileContent = string.Empty; string fileld = string.Empty; 
                         string fileldPrm = string.Empty; string queryPrm = string.Empty;
    string tableName = tblColumns[0].Tablename; string tableSchema = tblColumns[0].TableSchema;

    string spName = ("[" + tableSchema + "].[Get_" + tableName + "]").ToString();
    foreach (var item in tblColumns)
    {
        fileld = fileld + item.ColumnName + ",";
        fileldPrm = fileldPrm + item.ColumnName + " = @" + item.ColumnName + ",";

        //parameter
        builderPrm.AppendLine();
        if ((item.DataType.ToString() == "nvarchar") || (item.DataType.ToString() == "varchar"))
            builderPrm.Append("  @" + item.ColumnName + " " + 
                              item.DataType + "(" + item.MaxLength + "),");
        else
            builderPrm.Append("  @" + item.ColumnName + " " + item.DataType + ",");
    }

    queryPrm = builderPrm.Remove((builderPrm.Length - 1), 1).AppendLine().ToString();

    //Body
    builderBody.Append("UPDATE [" + tableSchema + "].[" + tableName + "] 
                        SET " + fileldPrm.TrimEnd(',') + " WHERE [CONDITIONS]");

    using (StreamReader sr = new StreamReader(path, Encoding.UTF8))
    {
        fileContent = sr.ReadToEnd().Replace("#Name", spName.ToString()).Replace
                      ("#Param", queryPrm.ToString()).Replace
                      ("#Body", builderBody.ToString()).Replace("#OrdPrm", fileldPrm.ToString());
    }

    return fileContent.ToString();
}

Delete-SP

这是删除操作的最小标签 sp 生成查询模板,在应用程序中,我们需要使用我们自己的附加逻辑来修改这些模板。

//DELETE
public static dynamic GenerateDeleteSP(List<vmColumn> tblColumns, string contentRootPath)
{
    StringBuilder builderPrm = new StringBuilder();
    StringBuilder builderBody = new StringBuilder();
    builderPrm.Clear(); builderBody.Clear();

    string path = @"" + contentRootPath + "\\template\\StoredProcedure\\DeleteSP.txt";
    string fileContent = string.Empty; string fileld = string.Empty; 
                         string fileldPrm = string.Empty; string queryPrm = string.Empty;
    string tableName = tblColumns[0].Tablename; string tableSchema = tblColumns[0].TableSchema;

    string spName = ("[" + tableSchema + "].[Delete_" + tableName + "]").ToString();
    foreach (var item in tblColumns)
    {
        fileld = fileld + item.ColumnName + ",";
        fileldPrm = fileldPrm + "@" + item.ColumnName + ",";

        //parameter
        builderPrm.AppendLine();
        if ((item.DataType.ToString() == "nvarchar") || (item.DataType.ToString() == "varchar"))
            builderPrm.Append("  @" + item.ColumnName + " " + 
                              item.DataType + "(" + item.MaxLength + "),");
        else
            builderPrm.Append("  @" + item.ColumnName + " " + item.DataType + ",");
    }

    queryPrm = builderPrm.Remove((builderPrm.Length - 1), 1).AppendLine().ToString();

    //Body
    builderBody.Append("DELETE FROM [" + tableSchema + "].[" + tableName + "] WHERE [CONDITIONS]");

    using (StreamReader sr = new StreamReader(path, Encoding.UTF8))
    {
        fileContent = sr.ReadToEnd().Replace("#Name", spName.ToString()).Replace
                      ("#Param", queryPrm.ToString()).Replace("#Body", 
                      builderBody.ToString()).Replace("#OrdPrm", fileldPrm.ToString());
    }

    return fileContent.ToString();
}

让我们处理前端, AngularJ Controller-Generator

在我们的前端,我们还使用了与生成 API 控制器相同的机制。

public static dynamic GenerateNgController(List<vmColumn> tblColumns, string contentRootPath)
{
    TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
    StringBuilder builderPrm = new StringBuilder();
    StringBuilder builderSub = new StringBuilder();
    builderPrm.Clear(); builderSub.Clear();
    string fileContent = string.Empty; string queryPrm = string.Empty; string submitPrm = string.Empty;

    string tableName = tblColumns[0].Tablename; string tableSchema = tblColumns[0].TableSchema;
    string path = @"" + contentRootPath + "\\template\\AngularJS\\Controller.txt";

    //Controller Name
    string ctrlName = textInfo.ToTitleCase(Conversion.RemoveSpecialCharacters
                      (tableName.ToString())) + "Controller";
    string serviceInjected = "'$scope', '$http'"; string srvParam = "$scope, $http";
    string urlApiGet = "'/api/" + textInfo.ToTitleCase
                       (Conversion.RemoveSpecialCharacters(tableName.ToString())) + "/GetAll'";
    string url_GetByID = "'/api/" + textInfo.ToTitleCase
                       (Conversion.RemoveSpecialCharacters(tableName.ToString())) + 
                       "/GetByID/'+ parseInt(model.id)";
    string url_Post = "'/api/" + textInfo.ToTitleCase
                       (Conversion.RemoveSpecialCharacters(tableName.ToString())) + "/Save'";
    string url_Put = "'/api/" + textInfo.ToTitleCase
                       (Conversion.RemoveSpecialCharacters(tableName.ToString())) + 
                        "/UpdateByID/'+ parseInt(model.id)";
    string url_Delete = "'/api/" + textInfo.ToTitleCase
                       (Conversion.RemoveSpecialCharacters(tableName.ToString())) + 
                        "/DeleteByID/'+ parseInt(model.id)";

    using (StreamReader sr = new StreamReader(path, Encoding.UTF8))
    {
        fileContent = sr.ReadToEnd()
            .Replace("#ControllerName", ctrlName.ToString())
            .Replace("#ServiceInjected", serviceInjected.ToString())
            .Replace("#SrvParam", srvParam.ToString())
            .Replace("#UrlGet", urlApiGet.ToString())
            .Replace("#Url_GetByID", url_GetByID.ToString())
            .Replace("#Url_Post", url_Post.ToString())
            .Replace("#Url_Put", url_Put.ToString())
            .Replace("#Url_Delete", url_Delete.ToString());
    }

    return fileContent.ToString();
}

HTML-Generator (Form)

使用以下方法,我们生成了嵌入了 angular 标签的 HTML 表单。

public static dynamic GenerateForm(List<vmColumn> tblColumns, string contentRootPath)
{
    TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
    StringBuilder builderPrm = new StringBuilder();
    StringBuilder builderSub = new StringBuilder();
    builderPrm.Clear(); builderSub.Clear();
    string fileContent = string.Empty; string queryPrm = string.Empty; string submitPrm = string.Empty;

    string tableName = tblColumns[0].Tablename; string tableSchema = tblColumns[0].TableSchema;
    string path = @"" + contentRootPath + "\\template\\HtmlForm\\Form.txt";

    //Form Name
    string frmName = "name='frm" + tableName.ToString() + "' novalidate";

    //Form Fields
    foreach (var item in tblColumns)
    {
        //parameter
        builderPrm.AppendLine();
        builderPrm.Append(" <div class='form-group'>");
        builderPrm.AppendLine();
        if (item.ColumnName.Contains("email") || item.ColumnName.Contains("Email"))
        {
            builderPrm.Append("  <label for='" + item.ColumnName + "' class='control-label'>" + 
                              textInfo.ToTitleCase(Conversion.RemoveSpecialCharacters(item.ColumnName))
                              + "</label>");
            builderPrm.AppendLine();
            builderPrm.Append("  <input type='email' class='form-control' ng-model='vmfrm." + 
                              item.ColumnName + "' name='" + item.ColumnName + "' required />");
        }
        else if (item.ColumnName.Contains("password") || item.ColumnName.Contains("Password"))
        {
            builderPrm.Append("  <label for='" + item.ColumnName + "' class='control-label'>" + 
                              textInfo.ToTitleCase(Conversion.RemoveSpecialCharacters
                              (item.ColumnName)) + "</label>");
            builderPrm.AppendLine();
            builderPrm.Append("  <input type='password' class='form-control' ng-model='vmfrm." + 
                              item.ColumnName + "' name='" + item.ColumnName + "' required />");
        }
        else
        {
            builderPrm.Append("  <label for='" + item.ColumnName + "' class='control-label'>" + 
                              textInfo.ToTitleCase(Conversion.RemoveSpecialCharacters
                              (item.ColumnName)) + "</label>");
            builderPrm.AppendLine();
            builderPrm.Append("  <input type='text' class='form-control' ng-model='vmfrm." + 
                              item.ColumnName + "' name='" + item.ColumnName + "' required />");
        }
        builderPrm.AppendLine();
        builderPrm.Append(" </div>");
    }
    queryPrm = builderPrm.AppendLine().ToString();

    //Form Submit
    builderSub.Append(" <div class='form-group'>");
    builderSub.AppendLine();
    builderSub.Append("  <input type='submit' name='reset' value='Reset' ng-click='Reset()' />");
    builderSub.AppendLine();
    builderSub.Append("  <input type='submit' name='update' value='Update' ng-click='Update()' />");
    builderSub.AppendLine();
    builderSub.Append("  <input type='submit' name='submit' value='Save' ng-click='Save()' />");
    builderSub.AppendLine();
    builderSub.Append(" </div>");

    submitPrm = builderSub.AppendLine().ToString();

    using (StreamReader sr = new StreamReader(path, Encoding.UTF8))
    {
        fileContent = sr.ReadToEnd().Replace("#frmName", frmName.ToString()).Replace
                      ("#frmGroup", queryPrm.ToString()).Replace("#frmSubmit", submitPrm.ToString());
    }

    return fileContent.ToString();
}

生成的代码

我们使用了多个选项卡来表示所有生成的代码。 以下是我们的 HTML 部分,它展示了我们如何呈现生成的代码。

<div class="tab-struct custom-tab-2 mt-0">
    <ul role="tablist" class="nav nav-tabs" id="myTabs_15">
        <li class="active" role="presentation">
            <a data-toggle="tab" id="views_tab_1" role="tab" href="#views" aria-expanded="false">
                  HTML Views</a>
        </li>
        <li role="presentation" class="">
            <a data-toggle="tab" id="angular_tab_1" role="tab" href="#angular" aria-expanded="false">
                  AngularJS</a>
        </li>
        <li role="presentation" class="">
            <a data-toggle="tab" id="csharp_tab_1" role="tab" href="#csharp" aria-expanded="false">
                  WebAPI</a>
        </li>
        <li role="presentation" class="">
            <a data-toggle="tab" id="model_tab_1" role="tab" href="#model" aria-expanded="false">
                  Model</a>
        </li>
        <li class="" role="presentation">
            <a aria-expanded="true" data-toggle="tab" role="tab" id="sql_tab_1" href="#sql">SQL</a>
        </li>
    </ul>
    <div class="tab-content" id="myTabContent_15">
        <div id="views" class="tab-pane fade  active in" role="tabpanel" 
         style="max-height:450px; overflow-y: auto;">
            <pre class="pa-10" lang="html"><xmp id="genCodeVu"></xmp></pre>
        </div>
        <div id="angular" class="tab-pane fade" role="tabpanel" 
         style="max-height:450px; overflow-y: auto;">
            <pre class="pa-10" lang="sql"><xmp id="genCodeAngular"></xmp></pre>
        </div>
        <div id="csharp" class="tab-pane fade" role="tabpanel" 
         style="max-height:450px; overflow-y: auto;">
            <pre class="pa-10" lang="sql"><xmp id="genCodeAPI"></xmp></pre>
        </div>
        <div id="model" class="tab-pane fade" role="tabpanel" 
         style="max-height:450px; overflow-y: auto;">
            <pre class="pa-10" lang="cs"><xmp id="genCodeVm"></xmp></pre>
        </div>
        <div id="sql" class="tab-pane fade" role="tabpanel" 
         style="max-height:450px; overflow-y: auto;">
            <pre class="pa-10" lang="sql"><xmp id="genCodeSql"></xmp></pre>
        </div>
    </div>
</div>

我们使用了预格式化和 HTML 示例 Element 标签在 HTML 中呈现生成的代码。

<pre lang="sql"><xmp id="genCodeAPI"></xmp></pre>

这是代码生成前端函数,它与 API 交互,然后获取生成的content,该content通过在 HTML 页面中编写 DOM 来表示。

$scope.generate = function () {
    $('.nav-tabs a[href="#views"]').tab('show');

    var rowGen = [];
    var elementIDSql = 'genCodeSql';
    var elementIDVm = 'genCodeVm';
    var elementIDVu = 'genCodeVu';
    var elementIDNg = 'genCodeAngular';
    var elementIDApi = 'genCodeAPI';

    if ($scope.collist.length > 0) {
        var models = "[" + JSON.stringify($scope.collist) + "]";

        $http({
            method: 'POST',
            url: '/api/Codegen/GenerateCode',
            data: models,
            dataType: "json",
            contentType: 'application/json; charset=utf-8'
        }).then(function (response) {

            $('#genCodeSql').text(''); $('#genCodeVm').text(''); 
            $('#genCodeVu').text(''); $('#genCodeAngular').text(''); $('#genCodeAPI').text('');
            rowGen = response.data.spCollection;

            if (rowGen.length > 0) {
                for (var i = 0; i < rowGen.length; i++) {
                    //SP
                    if (i == 0)
                        document.getElementById(elementIDSql).innerHTML += 
                        "--+++++++++ SET SP +++++++ \r\n" + rowGen[i] + "\r\n";
                    else if (i == 1)
                        document.getElementById(elementIDSql).innerHTML += 
                        "--+++++++++ GET SP +++++++++ \r\n" + rowGen[i] + "\r\n";
                    else if (i == 2)
                        document.getElementById(elementIDSql).innerHTML += 
                        "--+++++++++ PUT SP +++++++++ \r\n" + rowGen[i] + "\r\n";
                    else if (i == 3)
                        document.getElementById(elementIDSql).innerHTML += 
                        "--+++++++++ DELETE SP +++++++++ \r\n" + rowGen[i] + "\r\n";
                    //VM
                    else if (i == 4)
                        document.getElementById(elementIDVm).innerHTML += 
                        "// +++++++++ MODEL PROPERTIES +++++++++ \r\n" + rowGen[i] + "\r\n";
                    //VIEW
                    else if (i == 5)
                        document.getElementById(elementIDVu).innerHTML += 
                        "<!-- +++++++++ HTML FORM +++++++++ --> \r\n" + rowGen[i] + "\r\n";
                    //ANGULAR
                    else if (i == 6)
                        document.getElementById(elementIDNg).innerHTML += 
                        "// +++++++++ AngularJS Controller +++++++++ \r\n" + rowGen[i] + "\r\n";
                    //API
                    else if (i == 7)
                        document.getElementById(elementIDApi).innerHTML += 
                        "// +++++++++ API Controller +++++++++ \r\n" + rowGen[i] + "\r\n";
                    else
                        document.getElementById(elementIDSql).innerHTML += " Error !!";
                };
            };
        }, function (error) {
            console.log(error);
        });
    }
    else {
        rowGen = []; $('#genCodeSql').text(''); $('#genCodeVm').text('');
        console.log("Please Choose a Column!!");
    };
};

输出

您可以在下面的屏幕中看到最终输出

源代码

我将完整的源代码上传到下载/克隆 @github,希望这会有所帮助。 🙂

© . All rights reserved.