动态数据生成解决方案
实现原理:
网页:使用StreamReader读取模板,替换里面的关键词,用 StreamWriter生成新页。
程序:使用类Codedom生成程序文件。
实现:具体如下

输入数据库名,用户名和密码进入系统。程序使用Form验证,所有未经过验证转到此画面。
Web.config配置如下:
<authentication mode="Forms">
<forms loginUrl="conn.aspx"
protection="All"
timeout="30"
name=".ASPXAUTH"
path="/"
requireSSL="false"
slidingExpiration="true"
defaultUrl="Pages_Creator.aspx"
cookieless="UseDeviceProfile"
enableCrossAppRedirects="false" />
</authentication>
<authorization>
<deny users="?" />
</authorization>

以下是数据库服务名,可以为IP地址。WUSF\DAT为我的数据库所在的服务器名称。
<appSettings>
<add key="Connecting" value="WUSF\DAT" />
</appSettings>
数据验证成功后转入程序生成画面,显示所有用户具有权限的数据库和对应的表,此部分功能涉及到相关SQL语句及程序如下。

SQL:
--Sql Server 关于获取数据库名,表名及字段名的几个语句。
所有的库名
select [name] from master.dbo.sysdatabases where dbid>6

--当前库下的所有表名
use hischeck
select[name]from sysobjects where xtype='U'

--当前表下的所有字段名
select column_name from information_schema.columns where table_name='hcempno'
select column_name from information_schema.columns where table_name='hcempno'
select [name] from syscolumns where id = object_id('hcempno')

C#:
CreatePage tmp = new CreatePage();//数据库操作类
this.lbdbname.DataSource = tmp.dbDataName(ConnectionString);
this.lbdbname.DataTextField = "name";
this.lbdbname.DataValueField = "name";
this.lbdbname.DataBind();

//得到第一个数据库名,用于初始化右边下拉列表。
this.ddlTable.DataSource = tmp.ddlDataTable(ConnectionString, lbdbname.Items[0].Value);
this.ddlTable.DataTextField = "name";
this.ddlTable.DataValueField = "name";
this.ddlTable.DataBind();

//选择事件,选择左边数据库名,右边得到对应的表名。
protected void lbdbname_SelectedIndexChanged(object sender, EventArgs e)

{
CreatePage tmp = new CreatePage();
this.ddlTable.DataSource = tmp.ddlDataTable(ConnectionString, this.lbdbname.SelectedItem.Value);
this.ddlTable.DataTextField = "name";
this.ddlTable.DataValueField = "name";
this.ddlTable.DataBind();
}

生成网页及对应程序代码如下:
范本页:
AddTemplet.config



<%
@ Page Language="C#" AutoEventWireup="true" CodeFile="FileStr.aspx.cs" Inherits="CodeAccrue.Web.FileStr" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>strTitle</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<form id="form1" runat="server">
<div>
<table width="100%" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td height="25" colspan="2" align="center">strTitle(Add) </td>
</tr>
strShowtd
<tr>
<td height="25" align="right"> </td>
<td> <asp:Button ID="btnAdd" OnClick="btnAdd_Click" runat="server" Text="Add" />
<input id="Button1" type="reset" value="Reset" /></td>
</tr>
</table>
</div>
</form>
</body>
</html>

生成檔C#代码:


1
2
protected void btnCreate_Click(object sender, EventArgs e)
3
{
4
string strlbname = lbdbname.SelectedValue;
5
string strddltable = ddlTable.SelectedValue;
6
string ConnectionString = "Data Source=" + Session["DbSour"] + ";uid=" + Session["Ud"] + ";pwd=" + Session["PW"] + ";database=" + Session["DbNM"] + ";";
7
8
CreatePage tmp = new CreatePage();
9
DataTable dt = tmp.GetAllFiles(ConnectionString, strddltable);
10
//生成詳細
11
string strtd = null;
12
for (int i = 0; i < dt.Rows.Count; i++)
13
{
14
strtd = strtd + "<tr>\r\n\t<td width=\"26%\" height=\"25\" align=\"right\">" + dt.Rows[i]["column_name"].ToString() + " </td>\r\n\t<td width=\"74%\"> <asp:TextBox ID=\"txt" + dt.Rows[i]["column_name"].ToString() + "\" runat=\"server\"></asp:TextBox></td>\r\n</tr>\r\n";
15
}
16
17
string path = HttpContext.Current.Server.MapPath("Templet/");
18
Encoding code = Encoding.GetEncoding("utf-8");
19
20
// 读取模板文件
21
string temp = HttpContext.Current.Server.MapPath("Templet/AddTemplet.config");
22
StreamReader sr = null;
23
StreamWriter sw = null;
24
string str = "";
25
try
26
{
27
sr = new StreamReader(temp, code);
28
str = sr.ReadToEnd(); // 读取文件
29
}
30
catch (Exception exp)
31
{
32
HttpContext.Current.Response.Write(exp.Message);
33
HttpContext.Current.Response.End();
34
sr.Close();
35
}
36
37
string htmlfilename = "Page_" + strddltable + "_Add" + ".aspx";
38
// 替换内容
39
// 这时,模板文件已经读入到名称为str的变量中了
40
41
str = str.Replace("strTitle", "Page_" + strddltable + "_Add"); //模板页中的strTitle
42
str = str.Replace("FileStr", "Page_" + strddltable + "_Add");
43
str = str.Replace("strShowtd", strtd);
44
45
if (!Directory.Exists(Server.MapPath(strddltable)))//判斷是否有目錄﹐如果沒有就創建
46
Directory.CreateDirectory(Server.MapPath(strddltable));
47
48
// 写文件
49
try
50
{
51
CreateCode(Server.MapPath(strddltable) + "\\" + "Page_" + strddltable + "_Add.aspx.cs", "Page_" + strddltable + "_Add", dt, ConnectionString, strddltable);
52
sw = new StreamWriter(Server.MapPath(strddltable) + "\\" + htmlfilename, false, code);
53
sw.Write(str);
54
sw.Flush();
55
}
56
catch (Exception ex)
57
{
58
HttpContext.Current.Response.Write(ex.Message);
59
HttpContext.Current.Response.End();
60
}
61
finally
62
{
63
sw.Close();
64
}
65
66
}
67
68
public void CreateCode(string strpath, string strclassNM, DataTable dt, string ConnectionString, string strddltable)
69
{
70
Stream codeStream = File.Open(strpath, FileMode.Create);
71
StreamWriter codeWriter = new StreamWriter(codeStream);
72
//创建一个代码生成器实例
73
CSharpCodeProvider provider = new CSharpCodeProvider();
74
ICodeGenerator codeGenerator = provider.CreateGenerator(codeWriter);
75
CodeGeneratorOptions codeGeneratorOptions = new CodeGeneratorOptions();
76
77
//添加命名空间
78
CodeSnippetCompileUnit literal = new CodeSnippetCompileUnit
79
("using System;\r\nusing System.Data;\r\nusing System.Data.SqlClient;\r\nusing System.Configuration;\r\nusing System.Collections;\r\nusing System.Web;\r\nusing System.Web.Security;\r\nusing System.Web.UI;\r\nusing System.Web.UI.WebControls;\r\nusing System.Web.UI.WebControls.WebParts;\r\nusing System.Web.UI.HtmlControls;\r\n");
80
codeGenerator.GenerateCodeFromCompileUnit(literal, codeWriter, codeGeneratorOptions);
81
82
//命名空间以及在此命名空间下面创建一个类
83
CodeNamespace codeNamespace = new CodeNamespace("CodeAccrue.Web");
84
CodeTypeDeclaration codeTypeDeclaration = new CodeTypeDeclaration();
85
codeTypeDeclaration.Name = strclassNM;//類名
86
codeTypeDeclaration.IsClass = true;
87
codeTypeDeclaration.TypeAttributes = TypeAttributes.Public;
88
codeTypeDeclaration.BaseTypes.Add("System.Web.UI.Page");
89
codeTypeDeclaration.IsPartial = true;
90
codeNamespace.Types.Add(codeTypeDeclaration);
91
92
//生成默認Page_Load事件
93
CodeMemberMethod CMethod = new CodeMemberMethod();
94
CMethod.Name = "Page_Load";
95
CMethod.Attributes = MemberAttributes.Private;
96
CMethod.ReturnType = new CodeTypeReference(typeof(void));
97
CMethod.Parameters.Add(new CodeParameterDeclarationExpression("object sender,", "EventArgs e"));
98
codeTypeDeclaration.Members.Add(CMethod);
99
100
//创建一个私有的字段
101
CodeMemberField codeMember = new CodeMemberField();
102
codeMember.Name = "strconn=@\"" + ConnectionString + "\"";
103
codeMember.Attributes = MemberAttributes.Private;
104
codeMember.Type = new CodeTypeReference(typeof(string));
105
codeTypeDeclaration.Members.Add(codeMember);
106
107
//生成btnCreate_Click事件
108
CodeMemberMethod CMethod2 = new CodeMemberMethod();
109
CMethod2.Name = "btnAdd_Click";
110
CMethod2.Attributes = MemberAttributes.Public;
111
CMethod2.ReturnType = new CodeTypeReference(typeof(void));
112
CMethod2.Parameters.Add(new CodeParameterDeclarationExpression("object sender,", "EventArgs e"));
113
114
string strsql = null;
115
string strFileNM=null;
116
for (int i = 0; i < dt.Rows.Count; i++)
117
{
118
strsql = strsql +"'\"+"+ dt.Rows[i]["column_name"].ToString()+"+\"'" + ",";
119
strFileNM = strFileNM +dt.Rows[i]["column_name"].ToString()+",";
120
CMethod2.Statements.Add(new CodeSnippetStatement("\t\t\t\tstring " + dt.Rows[i]["column_name"].ToString() + " = this.txt" + dt.Rows[i]["column_name"].ToString() + ".Text.Trim().ToString();"));
121
}
122
123
CMethod2.Statements.Add(new CodeSnippetStatement("\r\n\t\t\t\tstring strsql=\"" + strsql.Substring(0, strsql.Length - 1) + "\";"));
124
CMethod2.Statements.Add(new CodeSnippetStatement("\t\t\t\tstring strFileNM=\"" + strFileNM.Substring(0, strFileNM.Length - 1) + "\";"));
125
126
CMethod2.Statements.Add(new CodeSnippetStatement("\r\n\t\t\t\tCodeAccrue.WebClass.CreatePage tmp = new CodeAccrue.WebClass.CreatePage();"));
127
CMethod2.Statements.Add(new CodeSnippetStatement("\t\t\t\ttmp.ExecAdd(strconn,\"" + strddltable + "\",strFileNM,strsql);"));
128
129
codeTypeDeclaration.Members.Add(CMethod2);
130
131
//生成代码
132
codeGenerator.GenerateCodeFromNamespace(codeNamespace, codeWriter, codeGeneratorOptions);
133
codeWriter.Close();
134
codeStream.Close();
135
}
生成后档及代码:
Aspx:



<%
@ Page Language="C#" AutoEventWireup="true" CodeFile="Page_hcempno_Add.aspx.cs" Inherits="CodeAccrue.Web.Page_hcempno_Add" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Page_hcempno_Add</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<form id="form1" runat="server">
<div>
<table width="100%" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td height="25" colspan="2" align="center">Page_hcempno_Add(Add) </td>
</tr>
<tr>
<td width="26%" height="25" align="right">id </td>
<td width="74%"> <asp:TextBox ID="txtid" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td width="26%" height="25" align="right">strucode </td>
<td width="74%"> <asp:TextBox ID="txtstrucode" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td width="26%" height="25" align="right">linecode </td>
<td width="74%"> <asp:TextBox ID="txtlinecode" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td width="26%" height="25" align="right">empno </td>
<td width="74%"> <asp:TextBox ID="txtempno" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td width="26%" height="25" align="right">cname </td>
<td width="74%"> <asp:TextBox ID="txtcname" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td width="26%" height="25" align="right">sftype </td>
<td width="74%"> <asp:TextBox ID="txtsftype" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td width="26%" height="25" align="right">sex </td>
<td width="74%"> <asp:TextBox ID="txtsex" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td width="26%" height="25" align="right">age </td>
<td width="74%"> <asp:TextBox ID="txtage" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td width="26%" height="25" align="right">hold_date </td>
<td width="74%"> <asp:TextBox ID="txthold_date" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td width="26%" height="25" align="right">t_time </td>
<td width="74%"> <asp:TextBox ID="txtt_time" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td width="26%" height="25" align="right">g_time </td>
<td width="74%"> <asp:TextBox ID="txtg_time" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td width="26%" height="25" align="right">add_time </td>
<td width="74%"> <asp:TextBox ID="txtadd_time" runat="server"></asp:TextBox></td>
</tr>

<tr>
<td height="25" align="right"> </td>
<td> <asp:Button ID="btnAdd" OnClick="btnAdd_Click" runat="server" Text="Add" />
<input id="Button1" type="reset" value="Reset" /></td>
</tr>
</table>
</div>
</form>
</body>
</html>

CS:


using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;


namespace CodeAccrue.Web
{

public partial class Page_hcempno_Add : System.Web.UI.Page
{
private string strconn=@"Data Source=WUSF\DAT;uid=sa;pwd=055122;database=hischeck;";

private void Page_Load(object sender, EventArgs e)
{
}

public virtual void btnAdd_Click(object sender, EventArgs e)
{
string id = this.txtid.Text.Trim().ToString();
string strucode = this.txtstrucode.Text.Trim().ToString();
string linecode = this.txtlinecode.Text.Trim().ToString();
string empno = this.txtempno.Text.Trim().ToString();
string cname = this.txtcname.Text.Trim().ToString();
string sftype = this.txtsftype.Text.Trim().ToString();
string sex = this.txtsex.Text.Trim().ToString();
string age = this.txtage.Text.Trim().ToString();
string hold_date = this.txthold_date.Text.Trim().ToString();
string t_time = this.txtt_time.Text.Trim().ToString();
string g_time = this.txtg_time.Text.Trim().ToString();
string add_time = this.txtadd_time.Text.Trim().ToString();

string strsql="'"+id+"','"+strucode+"','"+linecode+"','"+empno+"','"+cname+"','"+sftype+"','"+sex+"','"+age+"','"+hold_date+"','"+t_time+"','"+g_time+"','"+add_time+"'";
string strFileNM="id,strucode,linecode,empno,cname,sftype,sex,age,hold_date,t_time,g_time,add_time";

CodeAccrue.WebClass.CreatePage tmp = new CodeAccrue.WebClass.CreatePage();
tmp.ExecAdd(strconn,"hcempno",strFileNM,strsql);
}
}
}

图片如下:


技术要点:生成网页文件很简单,关键是生成程序代码,Codedom的使用。
项目总结:实际上开发这样的程序并无实际上的意思(除非简单的数据操作),在实际的项目中,有很复杂的商务逻辑及页面布局。在代码生成方面比较有实际的意义,Codedom不仅可以生成代码,还可以动态编译成exe,dll/。网络上已经有很多代码生成工具,像CodeSmithStu就很不错。