背景
自從第一次接觸代碼生成器,就愛上她了。用過ComeSmith和T4,這些代碼生成器確實很優秀,為何我還要DIY自己的呢?有如下幾點理由:
-
- T4的元數據定義太麻煩,還要定義強類型的元數據類型。
- 一直希望用一款動態語言作為工具。
今天就介紹一下,如何用 nodejs + edge + ejs + c#,打造屬於自己的代碼生成器。核心外部庫介紹:
-
- edge:允許在nodejs中調用c#代碼。
- ejs:基於nodejs的模板引擎。
思路
常見的代碼生成器都支持從數據庫生成代碼,因此思路可以分為兩大步驟:一、讀取數據庫元數據;二、基於模板生成代碼。
讀取數據庫元數據可以用 edge + c#的一個開源類庫。
基於模板生成代碼可以用 ejs。
實現(代碼下載)
項目結構
核心代碼
SchemaReader.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 using DatabaseSchemaReader; 8 using DatabaseSchemaReader.DataSchema; 9 10 using Happy.Edge.DatabaseSchemaReader.Extentions; 11 12 namespace Happy.Edge.DatabaseSchemaReader 13 { 14 public sealed class SchemaReader 15 { 16 public async Task<object> AllTables(object options) 17 { 18 dynamic dynamicOptions = options; 19 20 var dbReader = new DatabaseReader( 21 dynamicOptions["connectionString"], 22 dynamicOptions["providerName"]); 23 24 return dbReader 25 .AllTables() 26 .Select(table => table.ToDynamic()) 27 .ToList(); 28 } 29 } 30 }
SchemaReader.js
1 var edge = require('edge'); 2 var path = require('path'); 3 var ejs = require('ejs'); 4 var fs = require('fs'); 5 6 exports.allTables = edge.func({ 7 assemblyFile: path.resolve(__dirname, './lib/bin/Happy.Edge.DatabaseSchemaReader.dll'), 8 typeName: 'Happy.Edge.DatabaseSchemaReader.SchemaReader', 9 methodName: 'AllTables' 10 }); 11 12 exports.allTables({ 13 providerName: 'System.Data.SqlClient', 14 connectionString: 'Data Source=(LocalDB)\\v11.0;AttachDbFilename=E:\\Happy.Edge\\database_schem_reader\\test_database\\Test.mdf;Integrated Security=True;Connect Timeout=30' 15 }, renderTables); 16 17 function renderTables(error, tables) { 18 tables.forEach(function (table) { 19 renderTable(table); 20 }); 21 } 22 23 function renderTable(table) { 24 var str = fs.readFileSync(__dirname + '/Templates/Entity.ejs', 'utf8'); 25 26 console.log(ejs.render(str, table)); 27 }
備注
這個示例只是驗證了這種可能性,這種理念可以延伸到其它工具開發。感謝edge。