读取表结构
选择响应的表后,查询出对应的表结构,一般实体的所需要的信息有:列名、列备注、类型、长度、是否主键、是否自增长、是否可空
继续上代码:
/// <summary> /// 物理表的列信息 /// </summary> public class TableColumn { private readonly string _connStr; public TableColumn() { } public TableColumn(string connStr) { _connStr = connStr; } public string TableName { get; private set; } public string Name { get; private set; } public string Remark { get; private set; } public string Type { get; private set; } public int Length { get; private set; } public bool IsIdentity { get; private set; } public bool IsKey { get; private set; } public bool IsNullable { get; private set; } public string CSharpType { get { return SqlHelper.MapCsharpType(Type, IsNullable); } } /// <summary> /// 查询列信息 /// </summary> /// <param name="tablesName"></param> /// <returns></returns> public List<TableColumn> QueryColumn(List<string> tablesName) { #region 表结构 var paramKey = string.Join(",", tablesName.Select((a, index) => "@p" + index)); var paramVal = tablesName.Select((a, index) => new SqlParameter("@p" + index, a)).ToArray(); var sql = string.Format(@"SELECT obj.name AS tablename , col.name , ISNULL(ep.[value], '') remark , t.name AS type , col.length , COLUMNPROPERTY(col.id, col.name, 'IsIdentity') AS isidentity , CASE WHEN EXISTS ( SELECT 1 FROM dbo.sysindexes si INNER JOIN dbo.sysindexkeys sik ON si.id = sik.id AND si.indid = sik.indid INNER JOIN dbo.syscolumns sc ON sc.id = sik.id AND sc.colid = sik.colid INNER JOIN dbo.sysobjects so ON so.name = si.name AND so.xtype = 'PK' WHERE sc.id = col.id AND sc.colid = col.colid ) THEN 1 ELSE 0 END AS iskey , col.isnullable FROM dbo.syscolumns col LEFT JOIN dbo.systypes t ON col.xtype = t.xusertype INNER JOIN dbo.sysobjects obj ON col.id = obj.id AND obj.xtype IN ( 'U', 'v' ) AND obj.status >= 0 LEFT JOIN dbo.syscomments comm ON col.cdefault = comm.id LEFT JOIN sys.extended_properties ep ON col.id = ep.major_id AND col.colid = ep.minor_id AND ep.name = 'MS_Description' LEFT JOIN sys.extended_properties epTwo ON obj.id = epTwo.major_id AND epTwo.minor_id = 0 AND epTwo.name = 'MS_Description' WHERE obj.name IN ({0});", paramKey); #endregion var result = SqlHelper.Query(_connStr, sql, paramVal); return (from DataRow row in result.Rows select new TableColumn { IsIdentity = Convert.ToBoolean(row["isidentity"]), IsKey = Convert.ToBoolean(row["iskey"]), IsNullable = Convert.ToBoolean(row["isnullable"]), Length = Convert.ToInt32(row["length"]), Name = row["name"].ToString(), Remark = row["remark"].ToString(), TableName = row["tablename"].ToString(), Type = row["type"].ToString() }).ToList(); } }
根据模板生成代码
开始我是尝试用T4的,发现不方便,繁杂的声明。因此我选择了nVelocity,这里不做太多介绍,附上相关文章学习,传送门
// <summary> /// 初始化模板引擎 /// </summary> public static string ProcessTemplate(string template, Dictionary<string, object> param) { var templateEngine = new VelocityEngine(); templateEngine.SetProperty(RuntimeConstants.RESOURCE_LOADER, "file"); templateEngine.SetProperty(RuntimeConstants.INPUT_ENCODING, "utf-8"); templateEngine.SetProperty(RuntimeConstants.OUTPUT_ENCODING, "utf-8"); templateEngine.SetProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, AppDomain.CurrentDomain.BaseDirectory); var context = new VelocityContext(); foreach (var item in param) { context.Put(item.Key, item.Value); } templateEngine.Init(); var writer = new StringWriter(); templateEngine.Evaluate(context, writer, "mystring", template); return writer.GetStringBuilder().ToString(); }
之前已经拿到的文件模版,通过上面的方法输出类文本,保存到选中项目的根目录下。
public static class FilesHelper { public static string Write(string directory, string fileName, string content) { var path = Path.Combine(directory, fileName + ".cs"); using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write)) { byte[] byteFile = Encoding.UTF8.GetBytes(content); fs.Write(byteFile, 0, byteFile.Length); } return path; } }
操作项目
终于到了最后一步了,部分人以为保存了文件后就完事了,最后通过包含文件就完事了。我们还是有点追求的,既然做成了插件就要更加的方便化。
通过之前[读取选中项目信息]步骤拿到的EnvDTE.Project ProjectDte,使用以下扩展方法进行添加、删除项目项。
/// <summary> /// 添加项目项 /// </summary> /// <param name="projectDte"></param> /// <param name="files"></param> public static void AddFilesToProject(this Project projectDte, List<string> files) { foreach (string file in files) { projectDte.ProjectItems.AddFromFile(file); } if (files.Any()) projectDte.Save(); } /// <summary> /// 排除项目项 /// </summary> /// <param name="projectDte"></param> /// <param name="files"></param> public static void RemoveFilesFromProject(this Project projectDte, List<string> files) { foreach (string file in files) { projectDte.ProjectItems.Item(Path.GetFileName(file)).Remove(); } if (files.Any()) projectDte.Save(); }
附加
部分同学可能想调试的时候会出现:无法直接启动“类库输出类型”项目,可以在项目属性-调试配置:
1.启动配置外部程序:C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\devenv.exe
2.命令行参数:/rootsuffix Exp
估计有同学会制作自己的图标,另外附上两条icon制作的网站:
http://iconfont.cn/search/index
http://www.easyicon.net/covert/
结尾
整篇文章的技术难点并不多,但是因为插件开发的资料相对较少,80%的时间花去找接口文档、找资料。
此工具的原型是公司架构师的,公司所有开发都在用,但是他把源码丢了………………好奇心使我重新实现了一份,当然了,说不定哪天带团队的时候会用上。
最后双手奉上源码,并不是什么牛逼的东西,希望可以帮助需要的同学。https://github.com/SkyChenSky/AutoBuildEntity