BuildProvider:负责具有特定扩展名且保存在特定文件夹中的文件
using System.Web.Compilation;
using System.CodeDom;
public class DataBuildProvider : BuildProvider
public override void GenerateCode(AssemblyBuilder ab)
示例代码:
代码
using
System;
using
System.Collections.Generic;
using
System.Web.Compilation;
using
System.CodeDom;
using
System.Xml;
using
System.IO;
using
System.Web.Hosting;
namespace
AspNetUnleashed
{
public
class
DataBuildProvider : BuildProvider
{
string
_className;
public
override
void
GenerateCode(AssemblyBuilder ab)
{
//
Load the XML file
XmlDocument xmlData
=
new
XmlDocument();
xmlData.Load(HostingEnvironment.MapPath(
this
.VirtualPath));
//
Generate code from XML document
CodeCompileUnit dataCode
=
GetDataCode(xmlData);
//
Add the code
ab.AddCodeCompileUnit(
this
, dataCode);
}
private
CodeCompileUnit GetDataCode(XmlDocument xmlData)
{
//
Add class
_className
=
Path.GetFileNameWithoutExtension(
this
.VirtualPath);
CodeTypeDeclaration dataType
=
new
CodeTypeDeclaration(_className);
dataType.IsPartial
=
true
;
//
Add constructor
AddConstructor(dataType);
//
Add properties
AddProperties(dataType, xmlData);
//
Add Select method
AddSelect(dataType, xmlData);
//
Add Select with conString overload
AddSelectConString(dataType, xmlData);
//
Create namespace
CodeNamespace dataNS
=
new
CodeNamespace(
"
Data
"
);
//
Add class to namespace
dataNS.Types.Add(dataType);
//
Create code unit
CodeCompileUnit dataCode
=
new
CodeCompileUnit();
//
Add namespace to code unit
dataCode.Namespaces.Add(dataNS);
//
Add default namespaces
dataNS.Imports.Add(
new
CodeNamespaceImport(
"
System
"
));
return
dataCode;
}
private
void
AddConstructor(CodeTypeDeclaration dataType)
{
//
Add default constructor method
CodeConstructor classConstructor
=
new
CodeConstructor();
classConstructor.Attributes
=
MemberAttributes.Public;
dataType.Members.Add(classConstructor);
}
private
void
AddProperties(CodeTypeDeclaration dataType, XmlDocument xmlData)
{
foreach
(XmlElement el
in
xmlData.DocumentElement.ChildNodes)
{
string
propName
=
el.Attributes[
"
name
"
].Value;
string
propType
=
"
System.String
"
;
if
(el.HasAttribute(
"
type
"
))
propType
=
el.Attributes[
"
type
"
].Value;
//
Add backing field
string
propFieldName
=
"
_
"
+
propName;
CodeMemberField field
=
new
CodeMemberField(propType, propFieldName);
dataType.Members.Add(field);
//
Add property
CodeMemberProperty prop
=
new
CodeMemberProperty();
dataType.Members.Add(prop);
prop.Name
=
propName;
prop.Type
=
new
CodeTypeReference(propType);
prop.Attributes
=
MemberAttributes.Public;
//
Add Get
CodeMethodReturnStatement getMethod
=
new
CodeMethodReturnStatement();
CodeFieldReferenceExpression refField
=
new
CodeFieldReferenceExpression(
new
CodeThisReferenceExpression(), propFieldName);
getMethod.Expression
=
refField;
prop.GetStatements.Add(getMethod);
//
Add Set
CodeAssignStatement setMethod
=
new
CodeAssignStatement(
new
CodeFieldReferenceExpression(
new
CodeThisReferenceExpression(), propFieldName),
new
CodePropertySetValueReferenceExpression());
prop.SetStatements.Add(setMethod);
}
}
private
void
AddSelect(CodeTypeDeclaration dataType, XmlDocument xmlData)
{
//
Create Select method
CodeMemberMethod selectMethod
=
new
CodeMemberMethod();
selectMethod.Name
=
"
Select
"
;
selectMethod.Attributes
=
MemberAttributes.Static
|
MemberAttributes.Public;
selectMethod.Parameters.Add(
new
CodeParameterDeclarationExpression(
"
System.Data.SqlClient.SqlConnection
"
,
"
con
"
));
CodeVariableReferenceExpression refCon
=
new
CodeVariableReferenceExpression(
"
con
"
);
AddSummaryComment(selectMethod,
"
Returns List of
"
+
_className);
//
Specify return type
CodeTypeReference refList
=
new
CodeTypeReference(
"
System.Collections.Generic.List
"
,
new
CodeTypeReference[] {
new
CodeTypeReference(_className) });
selectMethod.ReturnType
=
refList;
//
Add List collection for results
CodeVariableDeclarationStatement initResults
=
new
CodeVariableDeclarationStatement(refList,
"
results
"
,
new
CodeObjectCreateExpression(refList));
selectMethod.Statements.Add(initResults);
CodeVariableReferenceExpression refResults
=
new
CodeVariableReferenceExpression(
"
results
"
);
//
Add Command object
CodeVariableDeclarationStatement initCmd
=
new
CodeVariableDeclarationStatement(
"
System.Data.SqlClient.SqlCommand
"
,
"
cmd
"
,
new
CodeObjectCreateExpression(
"
System.Data.SqlClient.SqlCommand
"
));
selectMethod.Statements.Add(initCmd);
CodeVariableReferenceExpression refCmd
=
new
CodeVariableReferenceExpression(
"
cmd
"
);
CodeAssignStatement addCmdCon
=
new
CodeAssignStatement(
new
CodePropertyReferenceExpression(refCmd,
"
Connection
"
), refCon);
selectMethod.Statements.Add(addCmdCon);
CodeVariableDeclarationStatement initCmdText
=
new
CodeVariableDeclarationStatement(
typeof
(
string
),
"
cmdText
"
,
new
CodePrimitiveExpression(GetCommandText(xmlData)));
selectMethod.Statements.Add(initCmdText);
CodeAssignStatement addCmdText
=
new
CodeAssignStatement(
new
CodePropertyReferenceExpression(refCmd,
"
CommandText
"
),
new
CodeVariableReferenceExpression(
"
cmdText
"
));
selectMethod.Statements.Add(addCmdText);
//
Init SqlDataReader
CodeMethodInvokeExpression cmdExec
=
new
CodeMethodInvokeExpression(refCmd,
"
ExecuteReader
"
);
CodeVariableDeclarationStatement initReader
=
new
CodeVariableDeclarationStatement(
"
System.Data.SqlClient.SqlDataReader
"
,
"
reader
"
, cmdExec);
selectMethod.Statements.Add(initReader);
CodeVariableReferenceExpression refReader
=
new
CodeVariableReferenceExpression(
"
reader
"
);
//
Create While Loop
CodeVariableDeclarationStatement initCounter
=
new
CodeVariableDeclarationStatement(
"
System.Int32
"
,
"
counter
"
);
selectMethod.Statements.Add(initCounter);
CodeVariableReferenceExpression refLoopCounter
=
new
CodeVariableReferenceExpression(
"
counter
"
);
CodeAssignStatement loopInit
=
new
CodeAssignStatement(refLoopCounter,
new
CodePrimitiveExpression(
0
));
CodeMethodInvokeExpression loopTest
=
new
CodeMethodInvokeExpression(refReader,
"
Read
"
);
CodeAssignStatement loopIncrement
=
new
CodeAssignStatement(refLoopCounter,
new
CodeBinaryOperatorExpression(refLoopCounter, CodeBinaryOperatorType.Add,
new
CodePrimitiveExpression(
1
)));
CodeIterationStatement loop
=
new
CodeIterationStatement(loopInit, loopTest, loopIncrement);
selectMethod.Statements.Add(loop);
//
Create object
CodeVariableDeclarationStatement initRecord
=
new
CodeVariableDeclarationStatement(_className,
"
record
"
,
new
CodeObjectCreateExpression(_className));
CodeVariableReferenceExpression refRecord
=
new
CodeVariableReferenceExpression(
"
record
"
);
loop.Statements.Add(initRecord);
//
Loop through properties
foreach
(XmlElement el
in
xmlData.DocumentElement.ChildNodes)
{
string
propName
=
el.Attributes[
"
name
"
].Value;
string
propType
=
"
System.String
"
;
if
(el.HasAttribute(
"
type
"
))
propType
=
el.Attributes[
"
type
"
].Value;
CodeIndexerExpression refIndexer
=
new
CodeIndexerExpression(refReader,
new
CodePrimitiveExpression(propName));
CodeCastExpression castIt
=
new
CodeCastExpression(propType, refIndexer);
CodePropertyReferenceExpression refProp
=
new
CodePropertyReferenceExpression(refRecord, propName);
CodeAssignStatement assignProp
=
new
CodeAssignStatement(refProp, castIt);
loop.Statements.Add(assignProp);
}
//
add record to collection
CodeMethodInvokeExpression invokeAdd
=
new
CodeMethodInvokeExpression(refResults,
"
Add
"
,
new
CodeExpression[] { refRecord });
loop.Statements.Add(invokeAdd);
//
Return results
CodeMethodReturnStatement ret
=
new
CodeMethodReturnStatement(refResults);
selectMethod.Statements.Add(ret);
//
Add the Select method to the class
dataType.Members.Add(selectMethod);
}
private
void
AddSelectConString(CodeTypeDeclaration dataType, XmlDocument xmlData)
{
//
Create Select method
CodeMemberMethod selectMethod
=
new
CodeMemberMethod();
selectMethod.Name
=
"
Select
"
;
selectMethod.Attributes
=
MemberAttributes.Static
|
MemberAttributes.Public;
selectMethod.Parameters.Add(
new
CodeParameterDeclarationExpression(
"
System.String
"
,
"
connectionStringName
"
));
AddSummaryComment(selectMethod,
"
Returns List of
"
+
_className);
CodeVariableReferenceExpression refConStringName
=
new
CodeVariableReferenceExpression(
"
connectionStringName
"
);
//
Specify return type
CodeTypeReference refList
=
new
CodeTypeReference(
"
System.Collections.Generic.List
"
,
new
CodeTypeReference[] {
new
CodeTypeReference(_className) });
selectMethod.ReturnType
=
refList;
//
Add List collection for results
CodeVariableDeclarationStatement initResults
=
new
CodeVariableDeclarationStatement(refList,
"
results
"
,
new
CodeObjectCreateExpression(refList));
selectMethod.Statements.Add(initResults);
CodeVariableReferenceExpression refResults
=
new
CodeVariableReferenceExpression(
"
results
"
);
//
Get connection string setting
CodeTypeReferenceExpression refConStrings
=
new
CodeTypeReferenceExpression(
"
System.Web.Configuration.WebConfigurationManager
"
);
CodePropertyReferenceExpression refPropConStrings
=
new
CodePropertyReferenceExpression(refConStrings,
"
ConnectionStrings
"
);
CodeIndexerExpression conString
=
new
CodeIndexerExpression(refPropConStrings, refConStringName);
CodeVariableDeclarationStatement initConStringSetting
=
new
CodeVariableDeclarationStatement(
"
System.Configuration.ConnectionStringSettings
"
,
"
conStringSettings
"
, conString);
selectMethod.Statements.Add(initConStringSetting);
CodeVariableReferenceExpression refConStringSettings
=
new
CodeVariableReferenceExpression(
"
conStringSettings
"
);
//
Get connection string
CodePropertyReferenceExpression refPropConString
=
new
CodePropertyReferenceExpression(refConStringSettings,
"
ConnectionString
"
);
CodeVariableDeclarationStatement initConString
=
new
CodeVariableDeclarationStatement(
"
System.String
"
,
"
conString
"
, refPropConString);
selectMethod.Statements.Add(initConString);
CodeVariableReferenceExpression refConString
=
new
CodeVariableReferenceExpression(
"
conString
"
);
//
Create connection object
CodeVariableDeclarationStatement initCon
=
new
CodeVariableDeclarationStatement(
"
System.Data.SqlClient.SqlConnection
"
,
"
con
"
,
new
CodeObjectCreateExpression(
"
System.Data.SqlClient.SqlConnection
"
));
selectMethod.Statements.Add(initCon);
CodeVariableReferenceExpression refCon
=
new
CodeVariableReferenceExpression(
"
con
"
);
//
Assign connection string
CodeAssignStatement addConString
=
new
CodeAssignStatement(
new
CodePropertyReferenceExpression(refCon,
"
ConnectionString
"
), refConString);
selectMethod.Statements.Add(addConString);
//
Add Try
CodeTryCatchFinallyStatement tryBlock
=
new
CodeTryCatchFinallyStatement();
selectMethod.Statements.Add(tryBlock);
//
Open Connection
CodeMethodInvokeExpression conOpen
=
new
CodeMethodInvokeExpression(refCon,
"
Open
"
);
tryBlock.TryStatements.Add(conOpen);
//
Call Select with connection
CodeTypeReferenceExpression refMe
=
new
CodeTypeReferenceExpression(_className);
CodeMethodReferenceExpression refSelect
=
new
CodeMethodReferenceExpression(refMe,
"
Select
"
);
CodeMethodInvokeExpression invokeSelect
=
new
CodeMethodInvokeExpression(refSelect,
new
CodeExpression[] { refCon });
//
Assign results to local variable
CodeAssignStatement assignResults
=
new
CodeAssignStatement(refResults, invokeSelect);
tryBlock.TryStatements.Add(assignResults);
//
Close Connection
CodeMethodInvokeExpression conClose
=
new
CodeMethodInvokeExpression(refCon,
"
Close
"
);
tryBlock.FinallyStatements.Add(conClose);
//
Return results
CodeMethodReturnStatement ret
=
new
CodeMethodReturnStatement(refResults);
selectMethod.Statements.Add(ret);
//
Add the Select method to the class
dataType.Members.Add(selectMethod);
}
private
string
GetCommandText(XmlDocument xmlData)
{
string
tableName
=
xmlData.DocumentElement.Name;
List
<
String
>
columns
=
new
List
<
String
>
();
foreach
(XmlElement el
in
xmlData.DocumentElement.ChildNodes)
{
columns.Add(el.Attributes[
"
name
"
].Value);
}
string
columnList
=
String.Join(
"
,
"
, columns.ToArray());
return
String.Format(
"
SELECT {0} FROM {1}
"
, columnList, tableName);
}
private
void
AddSummaryComment(CodeTypeMember member,
string
comment)
{
member.Comments.Add(
new
CodeCommentStatement(
"
<summary>
"
+
comment
+
"
</summary>
"
,
true
));
}
}
}
<system.web>
<compilation debug="true">
<codeSubDirectories>
<add directoryName="CustomBuildProviders"/>
</codeSubDirectories>
<buildProviders>
<add extension=".simple" type="AspNetUnleashed.SimpleBuildProvider"/>
<add extension=".data" type="AspNetUnleashed.DataBuildProvider"/>
</buildProviders>
<expressionBuilders>
<add expressionPrefix="lookup" type="AspNetUnleashed.LookupExpressionBuilder"/>
</expressionBuilders>
<assemblies>
<add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>
ExpressionBuilder:从一个表达式生成另外一个表达式
using System.Web.Compilation;
public class LookupExpressionBuilder : ExpressionBuilder
public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
public override object EvaluateExpression(object target, BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
public override bool SupportsEvaluate
<?xml version="1.0"?>
<lookup>
<add key="WelcomeMessage" value="Welcome to our Web site!" />
<add key="Copyright" value="All content copyrighted by the company." />
</lookup>
<%$ lookup:WelcomeMessage %>
示例代码:
代码
using
System;
using
System.CodeDom;
using
System.Web.UI;
using
System.ComponentModel;
using
System.Web.Compilation;
using
System.Xml;
using
System.Web.Hosting;
using
System.Web.Caching;
namespace
AspNetUnleashed
{
public
class
LookupExpressionBuilder : ExpressionBuilder
{
public
override
CodeExpression GetCodeExpression(BoundPropertyEntry entry,
object
parsedData, ExpressionBuilderContext context)
{
CodeTypeReferenceExpression refMe
=
new
CodeTypeReferenceExpression(
base
.GetType());
CodePrimitiveExpression expression
=
new
CodePrimitiveExpression(entry.Expression);
return
new
CodeMethodInvokeExpression(refMe,
"
GetEvalData
"
,
new
CodeExpression[] { expression });
}
public
override
object
EvaluateExpression(
object
target, BoundPropertyEntry entry,
object
parsedData, ExpressionBuilderContext context)
{
return
GetEvalData(entry.Expression);
}
public
override
bool
SupportsEvaluate
{
get
{
return
true
;
}
}
public
static
string
GetEvalData(
string
expression)
{
XmlDocument lookupDoc
=
(XmlDocument)HostingEnvironment.Cache[
"
Lookup
"
];
if
(lookupDoc
==
null
)
{
lookupDoc
=
new
XmlDocument();
string
lookupFileName
=
HostingEnvironment.MapPath(
"
~/Lookup.config
"
);
lookupDoc.Load(lookupFileName);
CacheDependency fileDepend
=
new
CacheDependency(lookupFileName);
HostingEnvironment.Cache.Insert(
"
Lookup
"
, lookupDoc, fileDepend);
}
string
search
=
String.Format(
"
//add[@key='{0}']
"
, expression);
XmlNode match
=
lookupDoc.SelectSingleNode(search);
if
(match
!=
null
)
return
match.Attributes[
"
value
"
].Value;
return
"
[no match]
"
;
}
}
}
HTTP处理程序:
public interface IHttpHandler
{
void ProcessRequest(HttpContext context);
}
<httpHandlers>
<add path="*.gif" verb="*" type="AspNetUnleashed.ImageHandler" validate="false"/>
<add path="*.jpeg" verb="*" type="AspNetUnleashed.ImageHandler" validate="false"/>
<add path="*.jpg" verb="*" type="AspNetUnleashed.ImageHandler" validate="false"/>
<add path="*.rss" verb="*" type="AspNetUnleashed.RSSHandler" validate="false"/>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add verb="GET,HEAD" path="ScriptResource.axd" validate="false" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</httpHandlers>
path:关联路径
verb:动作:get or post
type:处理程序
vaildate:处理程序是否在应用程序启动时载入
异步HTTP处理程序:
public interface IHttpAsyncHandler : IHttpHandler
{
IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData);
void EndProcessRequest(IAsyncResult result);
}
获取应用程序属性:
this.ApplicationInstance.NumberOfRequests
public int NumberOfRequests
{
get
{...
}
}
示例代码:
代码
<%
@ Application Language
=
"
C#
"
%>
<%
@ Import Namespace
=
"
System.Data
"
%>
<%
@ Import Namespace
=
"
System.Data.SqlClient
"
%>
<%
@ Import Namespace
=
"
System.Web.Configuration
"
%>
<
script runat
=
"
server
"
>
private
string
_conString;
private
SqlConnection _con;
private
SqlCommand _cmdSelect;
private
SqlCommand _cmdInsert;
public
override
void
Init()
{
//
initialize connection
_conString
=
WebConfigurationManager.ConnectionStrings[
"
Log
"
].ConnectionString;
_con
=
new
SqlConnection(_conString);
//
initialize select command
_cmdSelect
=
new
SqlCommand(
"
SELECT COUNT(*) FROM Log WHERE Path=@Path
"
, _con);
_cmdSelect.Parameters.Add(
"
@Path
"
, SqlDbType.NVarChar,
500
);
//
initialize insert command
_cmdInsert
=
new
SqlCommand(
"
INSERT Log (Path) VALUES (@Path)
"
, _con);
_cmdInsert.Parameters.Add(
"
@Path
"
, SqlDbType.NVarChar,
500
);
}
public
int
NumberOfRequests
{
get
{
int
result
=
0
;
_cmdSelect.Parameters[
"
@Path
"
].Value
=
Request.AppRelativeCurrentExecutionFilePath;
try
{
_con.Open();
result
=
(
int
)_cmdSelect.ExecuteScalar();
}
finally
{
_con.Close();
}
return
result;
}
}
void
Application_BeginRequest(
object
sender, EventArgs e)
{
//
Record new request
_cmdInsert.Parameters[
"
@Path
"
].Value
=
Request.AppRelativeCurrentExecutionFilePath;
try
{
_con.Open();
_cmdInsert.ExecuteNonQuery();
}
finally
{
_con.Close();
}
}
</
script
>
HttpModule:在每次请求页面时发生,可处理HttpApplication事件
public interface IHttpModule
{
void Init(HttpApplication context);
}
public void Init(HttpApplication app)
{
app.AuthorizeRequest += new EventHandler(AuthorizeRequest);
}
<httpModules>
<add name="QueryStringModule" type="AspNetUnleashed.QueryStringModule"/>
</httpModules>
示例代码:
代码
public
class
QueryStringAuthenticationModule : IHttpModule
{
public
void
Init(HttpApplication app)
{
app.AuthorizeRequest
+=
new
EventHandler(AuthorizeRequest);
}
private
void
AuthorizeRequest(Object sender, EventArgs e)
{
//
Get context
HttpApplication app
=
(HttpApplication)sender;
HttpContext context
=
app.Context;
//
If the request is for Login.aspx, exit
string
path
=
context.Request.AppRelativeCurrentExecutionFilePath;
if
(String.Compare(path,
"
~/login.aspx
"
,
true
)
==
0
)
return
;
//
Check for password
bool
authenticated
=
false
;
if
(context.Request.QueryString[
"
password
"
]
!=
null
)
{
if
(context.Request.QueryString[
"
password
"
]
==
"
secret
"
)
authenticated
=
true
;
}
//
If not authenticated, redirect to login.aspx
if
(
!
authenticated)
context.Response.Redirect(
"
~/Login.aspx
"
);
}
public
void
Dispose() { }
}