上周給大家說了說如何使用.NET實現直接計算一個表達式,其實該方法可以擴展為執行一個類裡面的一個方法或者使用在其他更有用的地方,正如文章中所說,文章只是描述可以實現的一個方法,以及該方法的一個簡單實現。
今天我們要看看怎麼使用.NET一個自動生成源代碼,配合上一篇文章您就可以使用自己產生代碼供自己消費了
聽起來是不是很爽?有些朋友可能會說這個有點難吧,其實不然。我們工程裡面使用了微軟提供的CodeDom命名空間,所以可以輕松實現。有關CodeDom的詳細信息可以參考MSDN,上面說的非常清楚!我在這裡也就不羅索了。
本文介紹一個簡單的數據訪問層的源代碼自動生成的實現,所有的代碼都是使用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("MyDataAccess.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()));