如何使用.NET生成C#源代码

转载 2005年03月02日 11:59:00
上周给大家说了说如何使用.NET实现直接计算一个表达式,其实该方法可以扩展为执行一个类里面的一个方法或者使用在其他更有用的地方,正如文章中所说,文章只是描述可以实现的一个方法,以及该方法的一个简单实现。

        今天我们要看看怎么使用.NET一个自动生成源代码,配合上一篇文章您就可以使用自己产生代码供自己消费了(上一篇文章请参考:http://www.csdn.net/Develop/read_article.asp?id=34659)。

        听起来是不是很爽?有些朋友可能会说这个有点难吧,其实不然。我们工程里面使用了微软提供的CodeDom命名空间,所以可以轻松实现。有关CodeDom的详细信息可以参考MSDN,上面说的非常清楚!我在这里也就不罗索了。连接参考:http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemCodeDom.asp?frame=true

         本文介绍一个简单的数据访问层的源代码自动生成的实现,所有的代码都是使用hard-code的方式写的,如果您有兴趣可以使用其他的方法,比如数据库(资源文件)中获得资源,生成源代码,还可以实现一些O-R Mapping的操作。

        该文章中的数据访问层中有一个属性一个字段以及一个方法。属性是一个获得连接对象的属性,字段是一个连接对象的私有成员,方法是一个Get方法,得到一个查询结果集。源代码生成以后就象下面这个样子:
using System;
using System.Data;
using System.Data.SqlClient;

namespace Power.Cuike519 {
   
   
    public class PowerDataAccess {
       
        private SqlConnection m_connection;
       
        public PowerDataAccess() {
        }
       
        public virtual SqlConnection Connection {
            get {
                return this.m_connection;
            }
            set {
                this.m_connection = value;
            }
        }
       
        public virtual DataSet GetAllAuthors(string s_State) {
            try {
                if (this.m_connection!=null) {
                    System.Data.SqlClient.SqlDataAdapter da = new SqlDataAdapter(string.Format("select * from authors where state like '{0}'",s_State),this.m_connection);
                    System.Data.DataSet ds = new DataSet();
                    da.Fill(ds);
                    return ds;
                }
                else {
                    return null;
                }
            }
            catch (System.ApplicationException ex) {
                throw ex;
            }
            finally {
                this.m_connection.Close();
            }
        }
    }
}
        下面看看我们用了什么方法生成这段代码的,为了可以生成该代码我们需要一个工程,我建立了一个Windows应用程序来做这件事情,你也可以使用控制台或者ASP.NET程序将你生成的源代码发布到网络上让更多的人看到。我们在工程里面写了一个方法CreatePowerDataAccessLayer,该方法创建了上面的源代码,下面我们就看看源代码的片断:

        首先我们需要一个保存源代码的流,我们使用下面的代码创建流:
Stream codeStream = File.Open("sample.cs", FileMode.Create);
StreamWriter codeWriter = new StreamWriter(codeStream);
       

        接着我们想要编写的是CSharp的代码那么我们就使用CSharpCodeProvider来创建一个代码生成器。
CSharpCodeProvider provider = new CSharpCodeProvider();
ICodeGenerator codeGenerator = provider.CreateGenerator(codeWriter);
CodeGeneratorOptions codeGeneratorOptions = new CodeGeneratorOptions();
       

        为了可以让我们的源代码可以正确运行我们使用下面方法为我们的源代码添加命名空间
CodeSnippetCompileUnit literal = new CodeSnippetCompileUnit("using System;/nusing System.Data;/nusing System.Data.SqlClient;/n");
codeGenerator.GenerateCodeFromCompileUnit(literal,codeWriter,codeGeneratorOptions);
       

        接着我们就要为我们的源代码设置一个命名空间以及在此命名空间下面创建一个类
CodeNamespace codeNamespace = new CodeNamespace("Power.Cuike519");//命名空间名称
CodeTypeDeclaration codeTypeDeclaration = new CodeTypeDeclaration();
codeTypeDeclaration.Name = "PowerDataAccess"; // 类名
codeTypeDeclaration.IsClass = true;
codeTypeDeclaration.TypeAttributes = TypeAttributes.Public;
codeNamespace.Types.Add(codeTypeDeclaration);
       

       接着我们为该类创建一个构造函数,这里只创建一个默认的构造函数
CodeConstructor codeConstrustor = new CodeConstructor();
codeConstrustor.Attributes = MemberAttributes.Public;
codeTypeDeclaration.Members.Add(codeConstrustor);
      

       接着为我们的类创建一个字段,该字段是私有的,它是SqlConnection类型的名字叫m_connection
CodeMemberField codeMember = new CodeMemberField();
codeMember.Name = "m_connection";
codeMember.Attributes = MemberAttributes.Private;
codeMember.Type = new CodeTypeReference("SqlConnection");
codeTypeDeclaration.Members.Add(codeMember);
        

        有了字段我们为该字断添加一个可以操作和读取的属性,我们为它指定set和get方法,同时它是public的,是SqlConnection类型的,如下所示:
CodeMemberProperty codeMemberProperty = new CodeMemberProperty();
codeMemberProperty.Name = "Connection";
codeMemberProperty.Attributes = MemberAttributes.Public;
codeMemberProperty.Type = new CodeTypeReference("SqlConnection");
codeMemberProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(),"m_connection")));
codeMemberProperty.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(),"m_connection"),new CodePropertySetValueReferenceExpression()));
codeTypeDeclaration.Members.Add(codeMemberProperty);
  

        为了让我们的类看起来更有用我们使用下面的方法创建一个函数以及函数里面的内容,这里可以一次将函数体写入其中,这里没有这样做的原因是可以提供一个机会,看到微软在该命名空间下提供了其他很多有关源代码中使用的语句的类。
  

        它是public的返回的是DataSet类型的方法的名字叫GetAllAuthors。虽然叫这个名字但是我们还是提供了一个参数,以提供更加灵活的使用空间,同时也为了说明函数中使用参数的方法。
CodeMemberMethod codeMemberMethod = new CodeMemberMethod();
codeMemberMethod.Name = "GetAllAuthors";
codeMemberMethod.Attributes = MemberAttributes.Public;
codeMemberMethod.ReturnType = new CodeTypeReference("DataSet");
codeMemberMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string),"s_State"));

        为了让我们的源代码更强壮我们使用了try-catch-finnaly语句,就像下面这样:
CodeTryCatchFinallyStatement try1 = new CodeTryCatchFinallyStatement();

        为了判断我们的m_connection是不是已经初始化了我们使用下面的判断语句来判断:
CodeConditionStatement conditionalStatement = new CodeConditionStatement();
conditionalStatement.Condition = new CodeVariableReferenceExpression("this.m_connection!=null");
 

        我们在条件为真的时候希望我们的源代码执行下面的代码:
CodeVariableDeclarationStatement variableDeclarationDA = new CodeVariableDeclarationStatement(typeof(System.Data.SqlClient.SqlDataAdapter),"da",new CodeVariableReferenceExpression("new SqlDataAdapter(string.Format(/"select * from authors where state like '{0}'/",s_State),this.m_connection)") );
conditionalStatement.TrueStatements.Add(variableDeclarationDA);
CodeVariableDeclarationStatement variableDeclarationDS = new CodeVariableDeclarationStatement(typeof(DataSet),"ds",new CodeVariableReferenceExpression("new DataSet()") );
conditionalStatement.TrueStatements.Add(variableDeclarationDS);
CodeExpression invokeExpression = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("da"),"Fill", new CodeVariableReferenceExpression("ds") );
CodeExpressionStatement expressionStatement = new CodeExpressionStatement( invokeExpression );
conditionalStatement.TrueStatements.Add(expressionStatement);
conditionalStatement.TrueStatements.Add(new CodeVariableReferenceExpression("return ds"));
      

       而在假的时候执行下面的语句:
conditionalStatement.FalseStatements.Add(new CodeVariableReferenceExpression("return null"));

       接着我们把if语句添加到try语句中间,就像下面这样:
try1.TryStatements.Add(conditionalStatement);

       同时我们使用下面的方法把try语句添加到我们的方法里面:
codeMemberMethod.Statements.Add(try1);

        接着就是我们遇到异常的时候希望抛出异常信息,代码如下:
CodeCatchClause catch1 = new CodeCatchClause("ex", new CodeTypeReference("System.ApplicationException"));
catch1.Statements.Add(new CodeVariableReferenceExpression("throw ex") );
try1.CatchClauses.Add( catch1 );

        接着就是需要回收资源的代码,我们在这里将连接关闭(其实应该先检查状态再关闭,虽然SqlDataAdapter不需要显式的关闭,但是如果加上判断写在这里也没有什么错)
try1.FinallyStatements.Add( new CodeVariableReferenceExpression("this.m_connection.Close()"));
codeTypeDeclaration.Members.Add(codeMemberMethod);

        下面就可以将代码生成了
codeGenerator.GenerateCodeFromNamespace(codeNamespace,codeWriter,codeGeneratorOptions);

        在最后不要忘了关闭资源
codeWriter.Close();
codeStream.Close(); 

        文章中大部分是代码,希望您没有看糊涂,最终生成的代码就是上面所展现的。文中有什么不妥请直接发表评论或者发邮件到wu_jian830@hotmail.com。谢谢!


作者Blog:http://blog.csdn.net/cuike519/

.net代码生成器大全

1:CodeSmith       一款人气很旺国外的基于模板的dotnet代码生成器 官方网站:http://www.codesmithtools.com 官方论坛:http://forum.c...
  • guozh
  • guozh
  • 2015年04月06日 11:06
  • 3716

ASP.NET单点登录 TOKEN的使用

原網址鏈接 asp.net 跨域单点登录实现原理: 当用户第一次访问web应用系统的时候,因为还没有登录,会被引导到认证中心进行登录; 根据用户提供的登录信息,认证系统进行身份效验,...
  • LeeJay5
  • LeeJay5
  • 2014年10月03日 15:31
  • 4070

.net 实体对象生成json对象

转载地址:http://www.cnblogs.com/qingyuan/archive/2010/01/22/JSON.html 1. 简单介绍一下JSON   JSON(JavaScr...
  • zhuyu19911016520
  • zhuyu19911016520
  • 2014年04月25日 13:51
  • 6335

C#-ASP.NET 自动生成验证码

string code = CreateRandomCode(5); TempData["SecurityCode"] = code; return F...
  • wpg_boke
  • wpg_boke
  • 2016年08月13日 22:50
  • 200

C# 利用QRCode生成二维码图片

网上生成二维码的组件是真多,可是真正好用的,并且生成速度很快的没几个,QRCode就是我在众多中找到的,它的生成速度快。但是网上关于它的使用说明,真的太少了,大都是千篇一律的复制粘贴。这是本要用它做了...
  • lybwwp
  • lybwwp
  • 2014年01月18日 10:04
  • 62885

ASP.NET C#根据HTML页面导出PDF

在启明星采购系统里,新增了导出PDF功能。整个功能使用了第三方软件 wkhtmltopdf(下载) 官网 https://wkhtmltopdf.org/ 提供有更多版本下载 他可以把HTML页...
  • hbqjzx
  • hbqjzx
  • 2017年12月18日 14:56
  • 84

C#生成Code128码

using System; using System.Collections.Generic; using System.Data; using System.Drawing; namespace ...
  • smartsmile2012
  • smartsmile2012
  • 2014年03月28日 12:08
  • 4094

如何使用protobuf-net生成.cs(c#)文件

第一天接触protobuf就被将军了
  • qq_17435831
  • qq_17435831
  • 2016年07月26日 16:49
  • 2673

C#导出Word总结

一、步骤: 1.在Word中建立书签; 2.编写C#代码:
  • u010678947
  • u010678947
  • 2015年07月31日 16:18
  • 4467

.NET使用OpenSSL生成的pem密钥文件

using System; using System.Security.Cryptography; /// /// 作者:http://thinhunan.cnblogs.com /// 名称:R...
  • liguo9860
  • liguo9860
  • 2014年11月08日 17:53
  • 3803
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何使用.NET生成C#源代码
举报原因:
原因补充:

(最多只允许输入30个字)