这一个星期都在与代码生成器在奋战。
一开始,打算采用T4模板引挚。经过两天研究,发现困难很大。T4的设计,是与IDE绑在一起,而且每个visual studio版本,绑定越来越紧,越来越不兼容。
所以,还是打算采用CodeSmith.
一年多没用CodeSmith(原来也不会用),好不容易找到安装包还有一个重要的示例:
http://www.codeproject.com/Articles/17065/Code-Generator-using-CodeSmith-Api
这个示例,比较清楚地写出了如何调用CodeSmith API,通过模板,生成代码:
但是,这个作者比较小气,没有公开原码。我也不清楚为什么,可能也有自己的原因。
所以,我反编译过了,找到了代码:
CodeTemplateCompiler compiler; GenericProperty property = (GenericProperty) this.properties.GetProperty("Template Path", "Paths"); GenericProperty property2 = (GenericProperty) this.properties.GetProperty("Code Path", "Paths"); GenericProperty property1 = (GenericProperty) this.properties.GetProperty("SourceTable", "Database"); GenericProperty property3 = (GenericProperty) this.properties.GetProperty("IncludeDelete", "StoreProcedure Options"); GenericProperty property4 = (GenericProperty) this.properties.GetProperty("IncludeDrop", "StoreProcedure Options"); GenericProperty property5 = (GenericProperty) this.properties.GetProperty("IncludeInsert", "StoreProcedure Options"); GenericProperty property6 = (GenericProperty) this.properties.GetProperty("IncludeUpdate", "StoreProcedure Options"); GenericProperty property7 = (GenericProperty) this.properties.GetProperty("IncludeGet", "StoreProcedure Options"); GenericProperty property8 = (GenericProperty) this.properties.GetProperty("IncludeGetList", "StoreProcedure Options"); GenericProperty property9 = (GenericProperty) this.properties.GetProperty("DeletePrefix", "StoreProcedure Style"); GenericProperty property10 = (GenericProperty) this.properties.GetProperty("InsertPrefix", "StoreProcedure Style"); GenericProperty property11 = (GenericProperty) this.properties.GetProperty("SelectPrefix", "StoreProcedure Style"); GenericProperty property12 = (GenericProperty) this.properties.GetProperty("UpdatePrefix", "StoreProcedure Style"); GenericProperty property15 = (GenericProperty) this.properties.GetProperty("Entire DataBase", "Database"); GenericProperty property13 = (GenericProperty) this.properties.GetProperty("NameSpace", "NameSpace"); GenericProperty property14 = (GenericProperty) this.properties.GetProperty("DotNet Version", "Version"); if (!this.rbDatabase.Checked) { try { this.timePB.Interval = 100; this.timePB.Start(); compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\Entity.cst"); compiler.Compile(); if (compiler.Errors.Count == 0) { CodeTemplate template = compiler.CreateInstance(); DatabaseSchema schema = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text); TableSchema schema2 = schema.Tables[this.tbName.SelectedItem.ToString()]; template.SetProperty("NameSpace", property13.Value.ToString()); template.SetProperty("SourceTable", schema2); template.RenderToFile(property2.Value.ToString() + @"\Entity\" + schema2.Name + ".cs", true); } else if (compiler.Errors.Count > 0) { MessageBox.Show(compiler.Errors.ToString()); } compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\EntityBase.cst"); compiler.Compile(); if (compiler.Errors.Count == 0) { CodeTemplate template2 = compiler.CreateInstance(); DatabaseSchema schema3 = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text); TableSchema schema4 = schema3.Tables[this.tbName.SelectedItem.ToString()]; template2.SetProperty("NameSpace", property13.Value.ToString()); template2.SetProperty("SourceTable", schema4); template2.RenderToFile(property2.Value.ToString() + @"\Entity\Base\" + schema4.Name + "Base.cs", true); } else if (compiler.Errors.Count > 0) { MessageBox.Show(compiler.Errors.ToString()); } compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\DataProvider.cst"); compiler.Compile(); if (compiler.Errors.Count == 0) { CodeTemplate template3 = compiler.CreateInstance(); DatabaseSchema schema5 = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text); TableSchema schema6 = schema5.Tables[this.tbName.SelectedItem.ToString()]; template3.SetProperty("NameSpace", property13.Value.ToString()); template3.SetProperty("SourceTable", schema6); template3.RenderToFile(property2.Value.ToString() + @"\Entity\" + schema6.Name + "DataProvider.cs", true); } else if (compiler.Errors.Count > 0) { MessageBox.Show(compiler.Errors.ToString()); } if (property14.Value.Equals("2003")) { compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\DataProviderBase1.cst"); } else { compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\DataProviderBase.cst"); } compiler.Compile(); if (compiler.Errors.Count == 0) { CodeTemplate template4 = compiler.CreateInstance(); DatabaseSchema schema7 = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text); TableSchema schema8 = schema7.Tables[this.tbName.SelectedItem.ToString()]; template4.SetProperty("NameSpace", property13.Value.ToString()); template4.SetProperty("SourceTable", schema8); template4.RenderToFile(property2.Value.ToString() + @"\Entity\Base\" + schema8.Name + "DataProviderBase.cs", true); } else if (compiler.Errors.Count > 0) { MessageBox.Show(compiler.Errors.ToString()); } compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\EntityControl.cst"); compiler.Compile(); if (compiler.Errors.Count == 0) { CodeTemplate template5 = compiler.CreateInstance(); DatabaseSchema schema9 = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text); TableSchema schema10 = schema9.Tables[this.tbName.SelectedItem.ToString()]; template5.SetProperty("NameSpace", property13.Value.ToString()); template5.SetProperty("SourceTable", schema10); template5.RenderToFile(property2.Value.ToString() + @"\Entity\" + schema10.Name + "Control.cs", true); } else if (compiler.Errors.Count > 0) { MessageBox.Show(compiler.Errors.ToString()); } if (property14.Value.Equals("2003")) { compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\EntityControlBase1.cst"); } else { compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\EntityControlBase.cst"); } compiler.Compile(); if (compiler.Errors.Count == 0) { CodeTemplate template6 = compiler.CreateInstance(); DatabaseSchema schema11 = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text); TableSchema schema12 = schema11.Tables[this.tbName.SelectedItem.ToString()]; template6.SetProperty("NameSpace", property13.Value.ToString()); template6.SetProperty("SourceTable", schema12); template6.RenderToFile(property2.Value.ToString() + @"\Entity\Base\" + schema12.Name + "ControlBase.cs", true); } else if (compiler.Errors.Count > 0) { MessageBox.Show(compiler.Errors.ToString()); } compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\StoredProcedures.cst"); compiler.Compile(); if (compiler.Errors.Count == 0) { CodeTemplate template7 = compiler.CreateInstance(); DatabaseSchema schema13 = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text); TableSchema schema14 = schema13.Tables[this.tbName.SelectedItem.ToString()]; template7.SetProperty("SourceTable", schema14); template7.SetProperty("IncludeDelete", property3.Value.ToString()); template7.SetProperty("IncludeDrop", property4.Value.ToString()); template7.SetProperty("IncludeInsert", property5.Value.ToString()); template7.SetProperty("IncludeUpdate", property6.Value.ToString()); template7.SetProperty("IncludeGet", property7.Value.ToString()); template7.SetProperty("IncludeGetList", property8.Value.ToString()); template7.SetProperty("DeletePrefix", property9.Value.ToString()); template7.SetProperty("InsertPrefix", property10.Value.ToString()); template7.SetProperty("SelectPrefix", property11.Value.ToString()); template7.SetProperty("UpdatePrefix", property12.Value.ToString()); template7.RenderToFile(property2.Value.ToString() + @"\Entity\Sp\" + schema14.Name + "StoredProcedures.sql", true); } else if (compiler.Errors.Count > 0) { MessageBox.Show(compiler.Errors.ToString()); } compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\GenericList.cst"); compiler.Compile(); if (compiler.Errors.Count == 0) { CodeTemplate template8 = compiler.CreateInstance(); template8.SetProperty("NameSpace", property13.Value.ToString()); template8.RenderToFile(property2.Value.ToString() + @"\Entity\GenericList.cs", true); } else if (compiler.Errors.Count > 0) { MessageBox.Show(compiler.Errors.ToString()); } compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\CBO.cst"); compiler.Compile(); if (compiler.Errors.Count == 0) { CodeTemplate template9 = compiler.CreateInstance(); template9.SetProperty("NameSpace", property13.Value.ToString()); template9.RenderToFile(property2.Value.ToString() + @"\Entity\CBO.cs", true); } else if (compiler.Errors.Count > 0) { MessageBox.Show(compiler.Errors.ToString()); } this.timePB.Stop(); this.ProgressBar1.Value = 0; ConfirmMsg msg = new ConfirmMsg(); msg.linkLabel1.Text = property2.Value.ToString() + @"\Entity"; msg.linkLabel1.Links.Add(0, 100, property2.Value.ToString() + @"\Entity"); msg.Show(); } catch (Exception exception) { this.timePB.Stop(); this.ProgressBar1.Value = 0; MessageBox.Show(exception.Message.ToString()); } }
最关键就是这两句:
compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\Entity.cst"); compiler.Compile();
然而,意想不到的事情发生了。
没想到CodeSmith公司,更是小气,CodeSmith.Engine.dll 竞然,需要license才可以被调用,我了个去,有这么黑的吗?
原来用的是4.1.1,然后到网上,找了一天多,终于找到5.3有破解的CodeSmith.Engine.dll库。
http://download.csdn.net/detail/meanshe/3949350
真是救了我的工作啊。
感谢上帝。
否则,我可能就得自己亲自动手来破解了。可能又得几天。
另外,我的代码里,有两处注掉了,如果你已有数据库,想让界面每次弹出,都事先写好信息,就把那些代码反注掉:
第一处:
public CodeGenerator() { this.InitializeComponent(); this.GetServerName(); this.comboBox1.SelectedIndex = 1; //如果不想每次都输入用户密码,就打开这些注释 //tbUserid.Text = "sa"; //tbPwd.Text = "123456"; //haoyujie }
第二处:
private void CodeGenerator_Load(object sender, EventArgs e) { this.properties = new GenericPropertyCollection_CustomTypeDescriptor(); this.properties.AddProperty(new GenericProperty("NameSpace", "PIMail", "NameSpace", "This is the NameSpace of the project", new Attribute[0])); this.properties.AddProperty(new GenericProperty("Entire DataBase", "True", "DataBase", "Is Code generated for whole database or not", new Attribute[0])); this.properties.AddProperty(new GenericProperty("IncludeDelete", "True", "StoreProcedure Options", "Is Delete StoreProcedure Included or not", new Attribute[0])); this.properties.AddProperty(new GenericProperty("IncludeDrop", "True", "StoreProcedure Options", "Is Drop Script Included or not", new Attribute[0])); this.properties.AddProperty(new GenericProperty("IncludeInsert", "True", "StoreProcedure Options", "Is Insert Script Included or not", new Attribute[0])); this.properties.AddProperty(new GenericProperty("IncludeUpdate", "True", "StoreProcedure Options", "Is Update Script Included or not", new Attribute[0])); this.properties.AddProperty(new GenericProperty("IncludeGet", "True", "StoreProcedure Options", "Is Get Script Included or not", new Attribute[0])); this.properties.AddProperty(new GenericProperty("IncludeGetList", "True", "StoreProcedure Options", "Is GetList Script Included or not", new Attribute[0])); this.properties.AddProperty(new GenericProperty("DeletePrefix", "Delete", "StoreProcedure Style", "the prefix for delete store procedure", new Attribute[0])); this.properties.AddProperty(new GenericProperty("InsertPrefix", "Add", "StoreProcedure Style", "the prefix for Add store procedure", new Attribute[0])); this.properties.AddProperty(new GenericProperty("SelectPrefix", "Select", "StoreProcedure Style", "the prefix for Select store procedure", new Attribute[0])); this.properties.AddProperty(new GenericProperty("UpdatePrefix", "Update", "StoreProcedure Style", "the prefix for Update store procedure", new Attribute[0])); this.properties.AddProperty(new GenericProperty("DotNet Version", "2003", "Version", "The DotNet Version ", new Attribute[0])); this.propertyGrid1.SelectedObject = this.properties; this.propertyGrid1.Refresh(); //如果不想每次都输入用户密码,就打开这些注释 //haoyujie // this.GetConnection(); // string curDatabaseName = "AutoPack"; //this.dbName.SelectedText = curDatabaseName; // if (!this.Added) //标记属性框里,是否有 // { // AddDatabaseName(curDatabaseName); // } // else // { // ModifyDatabaseName(curDatabaseName); // } // this.dbName.SelectedIndex = 0; // this.dbtoolStripComboBox2.SelectedIndex = this.dbName.SelectedIndex; // this.rbDatabase.Checked = false; // this.rbTable.Checked = true; // tbName.SelectedItem = "TBL_TREE_HIERARCHY"; // ////////////////////////////////////////////////////////////////////////// // this.tbTemplate.Text = "E:\\tmp\\Final_Templates"; // this.properties.AddProperty(new GenericProperty("Template Path", this.tbTemplate.Text, "Paths", "The path where the templates are place", new Attribute[0])); // this.propertyGrid1.Refresh(); // this.tempathAdded = true; // ////////////////////////////////////////////////////////////////////////// // this.tbCode.Text = "E:\\tmp\\tmpcodeout"; // this.properties.AddProperty(new GenericProperty("Code Path", this.tbCode.Text, "Paths", "The path where the templates are place", new Attribute[0])); // this.propertyGrid1.Refresh(); // this.codepathAdded = true; // try // { // DirectoryInfo info = new DirectoryInfo(this.tbCode.Text); // info.CreateSubdirectory("Entity"); // info.CreateSubdirectory(@"Entity\Base"); // info.CreateSubdirectory(@"Entity\Sp"); // } // catch (Exception exception) // { // MessageBox.Show(exception.Message.ToString()); // } }
这是我反编译后的代码,边窗体都做好了。方便大家学习。
如果有人认为我冒犯了他的权益,就联系我。
等了半天,还没出天,哪天出来,我把链接放在这里。
代码下载:
CodeGenerator
http://download.csdn.net/detail/haoyujie/7215131
另外,请CSDN的编辑们放心,我所反编译的代码,原作者是提供原码的。
只是现在找不到原码了。所以,我这也不算什么过分。