扩展 ASP.NET 2.0 第一部分:创建自定义生成提供程序






4.37/5 (16投票s)
2005年11月7日
2分钟阅读

53746

404
通过为自定义项目资源创建自定义生成提供程序来扩展 ASP.NET 运行时。
引言
ASP.NET 是一个出色的托管环境,支持对其注册资源的动态编译。本文的目的是展示如何通过使用自定义生成提供程序来利用动态编译。
BuildProvider 类
System.Web.Compilation.BuildProvider
抽象类提供了一组方法和属性,允许 ASP.NET 生成源代码。要使用此类,必须实现它,并在 web.config(或 Web 服务器的 machine.config)下的 system.web/compilation/buildProviders
部分下添加一个元素。
此列表概述了 ASP.NET 构建环境如何使用您的 BuildProvider
实例
- 构建环境会查找 web.config 中注册的生成提供程序。
- 当环境遇到
App_Code
特殊文件夹中与配置条目的extension
属性匹配的文件扩展名时,将创建您的提供程序的实例。 - 一个
AssemblyBuilder
对象被传递到构建器的GenerateCode
方法中。 - 您的提供程序使用
AssemblyBuilder
和其他System.Web.Compilation
类,将文件的源代码添加到整个程序集中。
要了解有关 BuildProvider
类的更多信息,请参见参考部分。
一个 ZipCode BuildProvider
本文使用一个简单的生成提供程序,该提供程序解析包含邮政编码信息的文件。 该提供程序为文件中的每一行创建一个状态类,并将邮政编码公开为属性。 自定义文件和生成的类如下所示
All.zipcode 文件的内容
Iowa|IA|50311;51442;50111;50021;50023
Nebraska|NE|12345;67890
Texas|TX|99999;12345
生成的 state 类
如前所述,必须在 web.config 中注册提供程序,运行时才能连接您的提供程序。ZipCodeBuildProvider
的条目如下所示
<buildProviders>
<add appliesTo="Code"
extension=".zipCode"
type="Lozanotek.Examples.ZipCodeBuildProvider, BuildProvider"/>
</buildProviders>
为了生成将被编译到程序集中的源代码,您必须使用 System.Web.Compilation
命名空间下的类来创建一个抽象语法树 (AST),并通过 AssemblyBuilder
类将其提供给运行时。 CreateClass
、CreateField
和 CreateProperty
方法用于通过解析文件中的一行并创建其相应的编译单元来创建自定义状态类。
/// <summary>
/// Creates a class by parsing the given line
/// </summary>
/// <param name="line">Line to parse</param>
/// <returns>A class declaration for a custom state class</returns>
private CodeTypeDeclaration CreateClass(string line)
{
// Parse out the tokens
string[] values = line.Split(new string[1] { "|" },
StringSplitOptions.RemoveEmptyEntries);
// Set the name of the class
string className = values[0];
CodeTypeDeclaration cls = new CodeTypeDeclaration(className);
// Set an internal field and its value
string fieldName = values[1];
CodeMemberField abbrField = CreateField(fieldName);
cls.Members.Add(abbrField);
// Get the zip codes listed for the states
string[] zipCodes = values[2].Split(new string[1] { ";" },
StringSplitOptions.RemoveEmptyEntries);
// Create a property for each of the zip codes found
foreach (string zipCode in zipCodes)
{
string tempZip = zipCode.Trim();
CodeMemberField zipField = CreateField(tempZip);
CodeMemberProperty zipProperty = CreateProperty(tempZip);
cls.Members.Add(zipField);
cls.Members.Add(zipProperty);
}
return cls;
}
/// <summary>
/// Creates a private string field to store the value for the zip code
/// </summary>
/// <param name="fieldName">Name of the fild to create</param>
/// <returns>A unit representing an private string field</returns>
private CodeMemberField CreateField(string fieldName)
{
// Specify that you want to create a string field with the given name
CodeMemberField field = new CodeMemberField(typeof(String),
string.Format("_{0}", fieldName));
// Make the field private and static
field.Attributes = MemberAttributes.Private | MemberAttributes.Static;
// Assign the value of the field to the zip code
field.InitExpression =
new CodeSnippetExpression(string.Format("\"{0}\"", fieldName));
return field;
}
/// <summary>
/// Creates a property that returns the value of a string field
/// </summary>
/// <param name="propertyName">Name of the property to create</param>
/// <returns>A unit representing a public static property</returns>
private CodeMemberProperty CreateProperty(string propertyName)
{
CodeMemberProperty prop = new CodeMemberProperty();
prop.Name = string.Format("zip{0}", propertyName);
prop.Type = new CodeTypeReference(typeof(String));
prop.Attributes = MemberAttributes.Public | MemberAttributes.Static;
// Build the body of the property by assigning it a get statement
prop.GetStatements.Add(new CodeMethodReturnStatement(
new CodeFieldReferenceExpression(null,
string.Format("_{0}", propertyName))));
return prop;
}
结论
我希望本文向您展示了开发人员如何利用 ASP.NET 运行时的可扩展性。 在我的下一篇扩展 ASP.NET 2.0 的文章中,我将演示如何通过创建自定义表达式生成器来进一步扩展 ASP.NET。
请随时使用下面的论坛对本文提出任何意见或建议。
参考文献
在撰写本文期间,我使用了以下资源