利用CodeSmith在自己的工程中动态生成代码

本文详细介绍了使用CodeSmith进行代码生成的过程,包括选择合适的模板引擎、解决License限制问题及反编译示例代码等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


这一个星期都在与代码生成器在奋战。

一开始,打算采用T4模板引挚。经过两天研究,发现困难很大。T4的设计,是与IDE绑在一起,而且每个visual studio版本,绑定越来越紧,越来越不兼容。

所以,还是打算采用CodeSmith.

一年多没用CodeSmith(原来也不会用),好不容易找到安装包还有一个重要的示例:


Code Generator using CodeSmith Api


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.youkuaiyun.com/detail/meanshe/3949350

Code Smith v5.3.3 破解补丁

真是救了我的工作啊。

感谢上帝。


否则,我可能就得自己亲自动手来破解了。可能又得几天。




另外,我的代码里,有两处注掉了,如果你已有数据库,想让界面每次弹出,都事先写好信息,就把那些代码反注掉:


第一处:

        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.youkuaiyun.com/detail/haoyujie/7215131

 

另外,请优快云的编辑们放心,我所反编译的代码,原作者是提供原码的。

只是现在找不到原码了。所以,我这也不算什么过分。

CodeSmith 是一种基于模板的代码生成工具,它使用类似于 ASP.NET 的语法来生成任意类型的代码或文本。与其他许多代码生成工具不同,CodeSmith 不要求您订阅特定的应用程序设计或体系结构。使用 CodeSmith,可以生成包括简单的强类型集合和完整应用程序在内的任何东西。 当您生成应用程序时,您经常需要重复完成某些特定的任务,例如编写数据访问代码或者生成自定义集合。CodeSmith 在这些时候特别有用,因为您可以编写模板自动完成这些任务,从而不仅提高您的工作效率,而且能够自动完成那些最为乏味的任务。CodeSmith 附带了许多模板,包括对应于所有 .NET 集合类型的模板以及用于生成存储过程的模板,但该工具的真正威力在于能够创建自定义模板。 基本说明: CodeSmith 是一种语法类似于asp.net的基于模板的代码生成器,程序可以自定义模板,从而减少重复编码的劳动量,提高效率。 安装CodeSmith并且注册后发现有两个可运行程序CodeSmith Studio.exe和CodeSmith Explorer.exe CodeSmith Studio.exe用来创建自定义模板 CodeSmith Explorer.exe用来导入模板并且生成代码 打开 CodeSmith Studio.exe,新建一个C#模板。发现有如下类似与asp.net的标识符号 软件特性: 1.他可以用于生成C#,VB.NET,TSQL以及其他任何语言代码 2.他本身是可以编程的(这是他的灵活性之源) 3.他提供了强大的SchemaExplorer对象,使数据库储过程的生成非常容易 4.有了他,你不会再向我一样埋怨从一个项目到另一个项目时,需要重新写许多代码.因为你只需要一套模板而已 5.他使用的语法是典型的ASP.NET语法,并且,可以像我们写ASP那样将代码和静态内容混和撰写(好像在写ASP的时代一样)
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值