学习自:https://blog.csdn.net/csdn1987/article/details/89677563
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace PXPublic
{
/// <summary>
/// 动态生成类文件
/// </summary>
public class GeneratorClass
{
static string fieldName = "";
static string commentText = "";//生成字段、属性、方法时的注释文本
static string methodCode = "";//生成方法时方法内部的代码片段
/// <summary>
/// 动态生成表结构类文件
/// </summary>
/// <param name="tableInfo">要生成类文件的表信息</param>
public static void GeneratorTableClass(MyDataSet tableInfo)
{
for (int i = 0; i < tableInfo.Tables[0].Rows.Count; i++)
{
//准备一个代码编译器单元
CodeCompileUnit unit = new CodeCompileUnit();
//设置命名空间(这个是指要生成的类的空间)
CodeNamespace myNamespace = new CodeNamespace("TableManager");
//导入必要的命名空间引用
myNamespace.Imports.Add(new CodeNamespaceImport("System"));
myNamespace.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
myNamespace.Imports.Add(new CodeNamespaceImport("System.Linq"));
myNamespace.Imports.Add(new CodeNamespaceImport("System.Text"));
myNamespace.Imports.Add(new CodeNamespaceImport("System.Threading.Tasks"));
myNamespace.Imports.Add(new CodeNamespaceImport("System.Data"));
//声明一个名为className的CodeTypeDeclaration
CodeTypeDeclaration myClass = new CodeTypeDeclaration(tableInfo.Tables[0].Rows[i]["tableName"].ToString());
myClass.IsClass = true; //指定该CodeTypeDeclaration为一个类
myClass.TypeAttributes = TypeAttributes.Public; //该类为公开的
//把这个类放在这个命名空间下
myNamespace.Types.Add(myClass);
//把该命名空间加入到编译器单元的命名空间集合中
unit.Namespaces.Add(myNamespace);
// 根据表名查询表的字段信息
string sql = " SELECT DISTINCT A.COLUMN_NAME" +
" ,B.COMMENTS " +
" ,A.DATA_TYPE " +
" ,A.DATA_LENGTH" +
" ,A.DATA_SCALE " +
" ,A.NULLABLE " +
" ,D.col# " +
" FROM USER_TAB_COLUMNS A,USER_COL_COMMENTS B,sys.col$ D" +
" WHERE A.TABLE_NAME = B.TABLE_NAME" +
" AND A.COLUMN_NAME = B.COLUMN_NAME" +
" AND D.NAME= A.COLUMN_NAME" +
" AND D.obj# IN (SELECT object_id FROM all_objects WHERE object_name = @TABLE_NAME )" +
" AND A.TABLE_NAME =@TABLE_NAME " +
" ORDER BY D.col# ";
DBManager.ParameterAdd("TABLE_NAME", tableInfo.Tables[0].Rows[i]["tableName"].ToString());
MyDataSet outDs = new MyDataSet();
int resultFlag = PXPublic.DBManager.ExcuteSelect(sql, outDs);
// 抽时间添加log4Net日志模块
//公用字段声明
CodeMemberField member = new CodeMemberField(typeof(System.String), "tableName");
member.Attributes = MemberAttributes.Private | MemberAttributes.Static; //设置访问类型
commentText = "\n/ <summary>\n" +
"/ 数据表名称\n" +
"/ </summary>";
member.Comments.Add(new CodeCommentStatement(commentText));
myClass.Members.Add(member); //把该字段添加到类中
member = new CodeMemberField(typeof(System.String), "tableCname");
member.Attributes = MemberAttributes.Private | MemberAttributes.Static; //设置访问类型
commentText = "\n/ <summary>\n" +
"/ 数据表描述\n" +
"/ </summary>";
member.Comments.Add(new CodeCommentStatement(commentText));
myClass.Members.Add(member); //把该字段添加到类中
//添加属性
CodeMemberProperty property = new CodeMemberProperty();
// 声明数据表结构字段
foreach (DataRow dr in outDs.Tables[0].Rows)
{
// 字段相关属性设置
fieldName = dr["COLUMN_NAME"].ToString().ToLower()+"_";
if (dr["DATA_TYPE"].ToString() == "VARCHAR2")
member = new CodeMemberField(typeof(System.String), fieldName);
else if (dr["DATA_TYPE"].ToString() == "NUMBER")
member = new CodeMemberField(typeof(System.Decimal), fieldName);
member.Attributes = MemberAttributes.Private | MemberAttributes.Static; //设置访问类型
commentText = "\n/ <summary>\n" +
"/ " + dr["COMMENTS"].ToString() +"\n"+
"/ </summary>";
member.Comments.Add(new CodeCommentStatement(commentText));
myClass.Members.Add(member); //把该字段添加到类中
// 属性相关信息设置
property = new CodeMemberProperty();
//设置访问类型
property.Attributes = MemberAttributes.Public | MemberAttributes.Static;
//对象名称
property.Name = dr["COLUMN_NAME"].ToString();
//有get
property.HasGet = true;
//有set
property.HasSet = true;
//设置property的类型
if (dr["DATA_TYPE"].ToString() == "VARCHAR2")
property.Type = new CodeTypeReference(typeof(System.String));
else if (dr["DATA_TYPE"].ToString() == "NUMBER")
property.Type = new CodeTypeReference(typeof(System.Decimal));
//添加注释
property.Comments.Add(new CodeCommentStatement(commentText));
//设置get里面的代码:get { return REC_CREATOR_;};由于属性使用静态属性,因此在设置get代码时变量不能使用this
property.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(null, fieldName)));
//property.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), dr["COLUMN_NAME"].ToString().ToLower())));
//设置set里面的代码:set { REC_CREATOR_ = value; };由于属性使用静态属性,因此在设置set代码时变量不能使用this
property.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(null, fieldName), new CodePropertySetValueReferenceExpression()));
///添加到Customerclass类中
myClass.Members.Add(property);
}
//添加MergeFrom方法
CodeMemberMethod method = new CodeMemberMethod();
//方法名
method.Name = "MergeFrom";
//访问类型
method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
//添加一个参数
method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(DataRow), "dataRow"));
commentText = "\n/ <summary>\n" +
"/ 从数据表中将对应字段名的值复制到当前类的同名属性中\n" +
"/ <param name=\"dataRow\">要复制数据数据行</param>\n" +
"/ </summary>";
method.Comments.Add(new CodeCommentStatement(commentText));
//设置返回值类型:int/不设置则为void
//method.ReturnType = new CodeTypeReference(typeof(int));
method.ReturnType = new CodeTypeReference();
//设置返回值(使用指定的代码片段初始化方法)
method.Statements.Add(new CodeSnippetStatement(" "));
///将方法添加到myClass类中
myClass.Members.Add(method);
//添加Query方法
method = new CodeMemberMethod();
//方法名
method.Name = "Query";
commentText = "\n/ <summary>\n" +
"/ 使用指定字段查询数据,查询结果必须唯一\n" +
"/ <param name=\"conditionColumn\">查询条件列</param>\n" +
"/ </summary>";
method.Comments.Add(new CodeCommentStatement(commentText));
//访问类型
method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
//添加一个参数
method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "conditionColumn"));
//设置返回值类型:int/不设置则为void
//method.ReturnType = new CodeTypeReference(typeof(int));
method.ReturnType = new CodeTypeReference();
//设置返回值
methodCode =" if (ConditionColumn.Trim() == \"\")\n"+
" return;\n"+
" PXPublic.MyDataSet outDs = new PXPublic.MyDataSet();\n"+
" string sql = \" SELECT * FROM \"+tableName+\" WHERE 1=1 \";\n"+
" if (ConditionColumn.Trim().Contains(\",\"))\n"+
" {\n"+
" string[] ConditionColumn_temp = ConditionColumn.Split(',');\n"+
" foreach (string column in ConditionColumn_temp)\n"+
" {\n"+
" // 获取当前类中的所有属性\n"+
" Type t = this.GetType();\n"+
" PropertyInfo[] info = t.GetProperties();\n"+
" // 判断当前传入的条件列是否属于当前类的属性(相当于判断当前传入列是否属于数据表字段)\n"+
" // 属于则获取到当前属性的值\n"+
" foreach (PropertyInfo preperty in info)\n"+
" {\n"+
" if (column == preperty.Name)\n"+
" {\n"+
" sql += string.Format(\" AND \"+column+\" = @\"+column);\n"+
" object temp = preperty.GetValue(this, null);\n"+
" PXPublic.DBManager.ParameterAdd(column, preperty.GetValue(this,null));\n"+
" }\n"+
" }\n"+
" }\n"+
" }\n"+
" PXPublic.DBManager.ExcuteSelect((sql), outDs);\n"+
" if(outDs.Tables[0].Rows.Count==1)\n"+
" {\n"+
" }\n"+
" else\n"+
" {\n"+
" PXPublic.SysMesgInfo.returnMsg = \"当前查询结果不唯一\";\n"+
" } ";
method.Statements.Add(new CodeSnippetStatement(methodCode));
///将方法添加到myClass类中
myClass.Members.Add(method);
//添加QueryCount方法
method = new CodeMemberMethod();
//方法名
method.Name = "QueryCount";
commentText = "\n/ <summary>\n" +
"/ 使用指定字段查询数据记录条数\n" +
"/ <param name=\"conditionColumn\">查询条件列</param>\n" +
"/ </summary>";
method.Comments.Add(new CodeCommentStatement(commentText));
//访问类型
method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
//添加一个参数
method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "conditionColumn"));
//设置返回值类型:int/不设置则为void
method.ReturnType = new CodeTypeReference(typeof(int));
//method.ReturnType = new CodeTypeReference();
//设置返回值
methodCode = " if (ConditionColumn.Trim() == \"\")\n" +
" return 0;\n" +
" PXPublic.MyDataSet outDs = new PXPublic.MyDataSet();\n" +
" string sql = \" SELECT COUNT(*) FROM \" + tableName + \" WHERE 1=1 \";\n" +
" if (ConditionColumn.Trim().Contains(\",\"))\n" +
" {\n" +
" string[] ConditionColumn_temp = ConditionColumn.Split(',');\n" +
" foreach (string column in ConditionColumn_temp)\n" +
" {\n" +
" // 获取当前类中的所有属性\n" +
" Type t = this.GetType();\n" +
" PropertyInfo[] info = t.GetProperties();\n" +
" // 判断当前传入的条件列是否属于当前类的属性(相当于判断当前传入列是否属于数据表字段)\n" +
" // 属于则获取到当前属性的值\n" +
" foreach (PropertyInfo preperty in info)\n" +
" {\n" +
" if (column == preperty.Name)\n" +
" {\n" +
" sql += string.Format(\" AND \" + column + \" = @\" + column);\n" +
" object temp = preperty.GetValue(this, null);\n" +
" PXPublic.DBManager.ParameterAdd(column, preperty.GetValue(this, null));\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
" PXPublic.DBManager.ExcuteSelect((sql), outDs);\n" +
" return outDs.Tables[0].Rows.Count; ";
method.Statements.Add(new CodeSnippetStatement(methodCode));
///将方法添加到myClass类中
myClass.Members.Add(method);
//添加Insert方法
method = new CodeMemberMethod();
//方法名
method.Name = "Insert";
commentText = "\n/ <summary>\n" +
"/ 新增一条数据到数据库对应数据表中\n" +
"/ </summary>";
method.Comments.Add(new CodeCommentStatement(commentText));
//访问类型
method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
//添加一个参数
//method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "conditionColumn"));
//设置返回值类型:int/不设置则为void
//method.ReturnType = new CodeTypeReference(typeof(int));
method.ReturnType = new CodeTypeReference();
//设置返回值
methodCode = " PXPublic.MyDataSet outDs = new PXPublic.MyDataSet();\n"+
" string InsertCol = \" \";\n"+
" string InsertSelect = \" \";\n"+
" int prepertyIndex = 0;\n"+
" // 获取当前类中的所有属性\n"+
" Type t = this.GetType();\n"+
" PropertyInfo[] info = t.GetProperties();\n"+
" // 判断当前传入的条件列是否属于当前类的属性(相当于判断当前传入列是否属于数据表字段)\n"+
" // 属于则获取到当前属性的值\n"+
" foreach (PropertyInfo preperty in info)\n"+
" {\n"+
" InsertCol += preperty.Name;\n"+
" if (preperty.GetValue(this, null).GetType() == typeof(String))\n"+
" InsertSelect += \"'\" + preperty.GetValue(this, null) + \"'\";\n"+
" else if (preperty.GetValue(this, null).GetType() == typeof(Decimal))\n"+
" InsertSelect += preperty.GetValue(this, null);\n"+
" if(prepertyIndex!=info.GetLength(0))\n"+
" {\n"+
" InsertSelect += \",\";\n"+
" InsertCol += \",\";\n"+
" }\n"+
" }\n"+
" string sql = \" INSERT INTO \" + tableName + \" ( \" + InsertCol + \") VALUES ( \" + InsertSelect + \" )\";\n"+
" PXPublic.DBManager.ExcuteSelect(sql, outDs);\n"+
" if (outDs.Tables[0].Rows.Count == 1)\n"+
" {\n"+
" }\n"+
" else\n"+
" {\n"+
" PXPublic.SysMesgInfo.returnMsg = \"当前查询结果不唯一\";\n"+
" } ";
method.Statements.Add(new CodeSnippetStatement(methodCode));
///将方法添加到myClass类中
myClass.Members.Add(method);
//添加Update方法
method = new CodeMemberMethod();
//方法名
method.Name = "Update";
commentText = "\n/ <summary>\n" +
"/ 根据指定字段修改数据\n" +
"/ <param name=\"updateColumn\">要修改数据的列</param>\n" +
"/ <param name=\"conditionColumn\">修改条件列</param>\n" +
"/ </summary>";
method.Comments.Add(new CodeCommentStatement(commentText));
//访问类型
method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
//添加一个参数
method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "updateColumn"));
method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "conditionColumn"));
//设置返回值类型:int/不设置则为void
//method.ReturnType = new CodeTypeReference(typeof(int));
method.ReturnType = new CodeTypeReference();
//设置返回值
methodCode =" if (ConditionColumn.Trim() == \"\")\n"+
" return;\n"+
" if (updateColumn.Trim() == \"\")\n"+
" return;\n"+
" PXPublic.MyDataSet outDs = new PXPublic.MyDataSet();\n"+
" string sql_set = \" SET \";\n"+
" string sql_where = \" WHERE 1=1 \";\n"+
" \n"+
" if (updateColumn.Trim().Contains(\",\"))\n"+
" {\n"+
" string[] updateColumn_temp = ConditionColumn.Split(',');\n"+
" foreach (string column in updateColumn_temp)\n"+
" {\n"+
" // 获取当前类中的所有属性\n"+
" Type t = this.GetType();\n"+
" PropertyInfo[] info = t.GetProperties();\n"+
" // 判断当前传入的条件列是否属于当前类的属性(相当于判断当前传入列是否属于数据表字段)\n"+
" // 属于则获取到当前属性的值\n"+
" foreach (PropertyInfo preperty in info)\n"+
" {\n"+
" if (column == preperty.Name)\n"+
" {\n"+
" sql_set += string.Format(column + \" = @\" + column);\n"+
" object temp = preperty.GetValue(this, null);\n"+
" PXPublic.DBManager.ParameterAdd(column, preperty.GetValue(this, null));\n"+
" }\n"+
" }\n"+
" }\n"+
" }\n"+
" else\n"+
" {\n"+
" }\n"+
" if (ConditionColumn.Trim().Contains(\",\"))\n"+
" {\n"+
" string[] ConditionColumn_temp = ConditionColumn.Split(',');\n"+
" foreach (string column in ConditionColumn_temp)\n"+
" {\n"+
" // 获取当前类中的所有属性\n"+
" Type t = this.GetType();\n"+
" PropertyInfo[] info = t.GetProperties();\n"+
" // 判断当前传入的条件列是否属于当前类的属性(相当于判断当前传入列是否属于数据表字段)\n"+
" // 属于则获取到当前属性的值\n"+
" foreach (PropertyInfo preperty in info)\n"+
" {\n"+
" if (column == preperty.Name)\n"+
" {\n"+
" sql_where += string.Format(\" AND \" + column + \" = @\" + column);\n"+
" object temp = preperty.GetValue(this, null);\n"+
" PXPublic.DBManager.ParameterAdd(column, preperty.GetValue(this, null));\n"+
" }\n"+
" }\n"+
" }\n"+
" }\n"+
" else\n"+
" {\n"+
" }\n"+
" string sql = \" UPDATE \" + tableName + sql_set + sql_where;\n"+
" PXPublic.DBManager.ExcuteSelect((sql), outDs);\n"+
" if (outDs.Tables[0].Rows.Count == 1)\n"+
" {\n"+
" }\n"+
" else\n"+
" {\n"+
" PXPublic.SysMesgInfo.returnMsg = \"当前查询结果不唯一\";\n"+
" }\n";
method.Statements.Add(new CodeSnippetStatement(methodCode));
///将方法添加到myClass类中
myClass.Members.Add(method);
//添加Delete方法
method = new CodeMemberMethod();
//方法名
method.Name = "Delete";
commentText = "\n/ <summary>\n" +
"/ 根据指定字段删除数据\n" +
"/ <param name=\"conditionColumn\">删除条件列</param>\n" +
"/ </summary>";
method.Comments.Add(new CodeCommentStatement(commentText));
//访问类型
method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
//添加一个参数
method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "conditionColumn"));
//设置返回值类型:int/不设置则为void
//method.ReturnType = new CodeTypeReference(typeof(int));
method.ReturnType = new CodeTypeReference();
//设置返回值
methodCode = " if (ConditionColumn.Trim() == \"\")\n"+
" return;\n"+
" PXPublic.MyDataSet outDs = new PXPublic.MyDataSet();\n"+
" string sql = \" DELETE FROM \" + tableName + \" WHERE 1=1 \";\n"+
" if (ConditionColumn.Trim().Contains(\",\"))\n"+
" {\n"+
" string[] ConditionColumn_temp = ConditionColumn.Split(',');\n"+
" foreach (string column in ConditionColumn_temp)\n"+
" {\n"+
" // 获取当前类中的所有属性\n"+
" Type t = this.GetType();\n"+
" PropertyInfo[] info = t.GetProperties();\n"+
" // 判断当前传入的条件列是否属于当前类的属性(相当于判断当前传入列是否属于数据表字段)\n"+
" // 属于则获取到当前属性的值\n"+
" foreach (PropertyInfo preperty in info)\n"+
" {\n"+
" if (column == preperty.Name)\n"+
" {\n"+
" sql += string.Format(\" AND \" + column + \" = @\" + column);\n"+
" object temp = preperty.GetValue(this, null);\n"+
" PXPublic.DBManager.ParameterAdd(column, preperty.GetValue(this, null));\n"+
" }\n"+
" }\n"+
" }\n"+
" }\n"+
" else\n"+
" {\n"+
" }\n"+
" PXPublic.DBManager.ExcuteSelect((sql), outDs);\n"+
" if (outDs.Tables[0].Rows.Count == 1)\n"+
" {\n"+
" }\n"+
" else\n"+
" {\n"+
" PXPublic.SysMesgInfo.returnMsg = \"当前查询结果不唯一\";\n"+
" }\n";
method.Statements.Add(new CodeSnippetStatement(methodCode));
///将方法添加到myClass类中
myClass.Members.Add(method);
//添加构造方法
//CodeConstructor constructor = new CodeConstructor();
//constructor.Attributes = MemberAttributes.Public;
/将构造方法添加到myClass类中
//myClass.Members.Add(constructor);
//添加特特性
//myClass.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(SerializeField))));
//创建一个代码生成器并指定语言为C sharp
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
//代码生成的方法
CodeGeneratorOptions options = new CodeGeneratorOptions();
options.BracingStyle = "C"; //C风格
//是否在字段、属性、方法之间添加空白行
options.BlankLinesBetweenMembers = true;
//获取程序的基目录
string path4 = System.AppDomain.CurrentDomain.BaseDirectory;
string outputPath = path4 + tableInfo.Tables[0].Rows[i]["tableName"].ToString() + ".cs"; //该文件的输出路径
using (StreamWriter sw = new StreamWriter(outputPath))
{
//为指定的代码文档对象模型(CodeDOM) 编译单元生成代码并将其发送到指定的文本编写器,使用指定的选项。(官方解释)
//将自定义代码编译器(代码内容)、和代码格式写入到sw中
provider.GenerateCodeFromCompileUnit(unit, sw, options); //生成类
}
}
}
}
}