Asp.Net之自定义表达式构造器(ExpressionBuilder)

简介:
在Asp.Net的Page页面中我们经常会使用到资源文件。读取资源文件的方式为 :<%$Resources:Resource1,Test1%> ,这样就可以显示Resource1这个资源文件中的Test1的键值,并且在页面设计过程中就可以正确的显示资源文件中的值了。这里就是使用到了.Net中的表达式构造器,那么它是如何实现的?我们能不能定义自己的表达式构造器呢?本文通过构建一个简单的Xml表达式构造器来说明这一过程。 
首先来看看Asp.Net中的表达式构造器是如何实现的
默认在C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config中我们可以找到如下配置节:
复制代码
       < expressionBuilders >
        
< add  expressionPrefix ="Resources"  type ="System.Web.Compilation.ResourceExpressionBuilder" />
        
< add  expressionPrefix ="ConnectionStrings"  type ="System.Web.Compilation.ConnectionStringsExpressionBuilder" />
        
< add  expressionPrefix ="AppSettings"  type ="System.Web.Compilation.AppSettingsExpressionBuilder" />
      
</ expressionBuilders >
复制代码
在这里定义了三个表达式构造器:Resources,ConnectionStrings,AppSettings。因此我们可以在页面中直接使用它们,比如可以使用<%$AppSettings:aa %>来读取AppSettings的配置。注意这里使用的是 $ 符号,它是读取表达式构造器的专用标识。

接下来重点看看如何实现自己的表达式构造器
我们的目的是实现一个简单的Xml表达式构造器,可以读取指定xml文件中的配置信息,并且在页面设计阶段就可以看到效果。
一、修改配置
在自己的web.config中加入配置:
           < expressionBuilders >
            
< add  expressionPrefix ="Xml"  type ="MyResource.XmlExpressionBuilder, MyResource, Version=1.0.0.0, Culture=neutral, PublicKeyToken=94a835118357b2d3" />
          
</ expressionBuilders >
表示我们的表达式构造器的前缀为Xml,也就是在页面中使用<%$Xml:.... %>的方式来读取
我们自定义的表达式构造器类的类名为XmlExpressionBuilder, 特别注意这个类所在的程序集需要使用强签名

二、实现表达式构造器类(ExpressionBuilder)
首先我们的类需要从ExpressionBuilder继承

public   class  XmlExpressionBuilder : ExpressionBuilder

实现GetCodeExpression方法
,这个方法是在页面实际运行时计算表达式的值使用的。它是用来为页面初始化生成代码(在允许页面编译时才会调用到此方法,Asp.Net在默认情况下是允许页面编译的):
复制代码
         public   override  CodeExpression GetCodeExpression(BoundPropertyEntry entry,  object  parsedData, ExpressionBuilderContext context)
        {
            
if  ((entry.DeclaringType  ==   null ||  (entry.PropertyInfo  ==   null ))
            {
                
return   new  CodeMethodInvokeExpression( new  CodeTypeReferenceExpression( base .GetType()),  " GetXmlKey " new  CodeExpression[] {  new  CodePrimitiveExpression(entry.Expression.Trim()) });
            }
            
return   new  CodeMethodInvokeExpression( new  CodeTypeReferenceExpression( base .GetType()),  " GetXmlKey " new  CodeExpression[] {  new  CodePrimitiveExpression(entry.Expression.Trim()),  new  CodeTypeOfExpression(entry.DeclaringType),  new  CodePrimitiveExpression(entry.PropertyInfo.Name) });
        }
复制代码
这个方法主要就是动态的调用GetXmlKey这个自定义的方法:
读取Xml值
在这里定义key值的格式为逗号分割的方式,比如在页面中调用<%$Xml:test,test1 %>,那么传递过来的参数strKey=test,test1

实现EvaluateExpression和SupportsEvaluate方法 ,这两个方法是在禁用页面编译时才会调用的,比如在页面中设置如下:
<% @ Page Language = " C# "   CodeBehind = " Default.aspx.cs "  Inherits = " MyResource._Default "  CompilationMode="Never"  %>
这种情况下就会调用这两个方法来取得表达式的值:
复制代码
         // 返回一个值,该值指示是否可在不编译的页中计算表达式
         public   override   bool  SupportsEvaluate
        {
            
get
            {
                
return   true ;
            }
        }
        
// 返回当前表达式的计算结果(禁用页面编译时 ---CompilationMode="Never" )
         public   override   object  EvaluateExpression( object  target, BoundPropertyEntry entry,  object  parsedData, ExpressionBuilderContext context)
        {
            
return  GetXmlKey(entry.Expression, target.GetType(), entry.PropertyInfo.Name);
        }
复制代码
附测试的test.xml文件

最后在自己的Aspx页面中调用:
         < asp:Label ID = " Label1 "  runat = " server "  Text = " <%$Xml:test,test1 %> " ></ asp:Label >
        
< br  />
        
< asp:Label ID = " Label3 "  runat = " server "  Text = " <%$Xml:test,test2 %> " ></ asp:Label >
        
< br  />
运行此页面就可以正确的显示test.xml中对应的值了。不过现在还有一个问题就是在页面的设计界面不能正确的显示test.xml中的值,因此我们还要接下来实现表达式编辑器类。

三、实现表达式编辑器类(ExpressionEditor)
首先在XmlExpressionBuilder上加入类属性 ,指定使用哪个表达式编辑器类
    [ExpressionEditor( " MyResource.XmlExpressionEditor, MyResource, Version=1.0.0.0, Culture=neutral, PublicKeyToken=94a835118357b2d3 " ), ExpressionPrefix( " Xml " )]
    
public   class  XmlExpressionBuilder : ExpressionBuilder

接下来实现自己的表达式编辑器类:XmlExpressionEditor ,它必须从ExpressionEditor继承
public   class  XmlExpressionEditor : ExpressionEditor
在我们的例子中只需要实现EvaluateExpression这个方法就可以了 ,它就是用来在页面的设计阶段来取得表达式的值的
复制代码
         public   override   object  EvaluateExpression( string  expression,  object  parseTimeData, Type propertyType, IServiceProvider serviceProvider)
        {
            
if  (serviceProvider  !=   null )
            {
                IWebApplication service 
=  (IWebApplication)serviceProvider.GetService( typeof (IWebApplication));
                
if  (service  !=   null )
                {
                    System.Configuration.Configuration configuration 
=  service.OpenWebConfiguration( true );
                    
if  (configuration  !=   null )
                    {
                        
string  strFile  =  configuration.FilePath.Substring( 0 , configuration.FilePath.LastIndexOf( " \\ " ));
                        
string [] keys  =  expression.Split( ' , ' );
                        strFile 
=  strFile  +   " \\ "   +  keys[ 0 +   " .xml " ;
                        
return  XmlExpressionBuilder.GetXmlKey(expression, strFile);
                    }
                }
            } 
            
            
return   "" ;
        }
复制代码
在这里也是通过调用XmlExpressionBuilder类中的GetXmlKey方法的,但是由于在设计状态下是取不到HttpContext.Current的值的,因此在这个方法中我通过IServiceProvider接口来取得当前路径,将得到xml文件名作为参数传递给GetXmlKey方法。修改后的GetXmlKey方法如下:
修改后的GetXmlKey方法

这样就可以在页面的设计视图取得正确的值了(当修改了XmlExpressionEditor文件后,重新编译后可能在设计视图还是不能正确显示,需要把VS2005重新启动一下就可以了)



    本文转自永春博客园博客,原文链接:http://www.cnblogs.com/firstyi/archive/2008/08/05/1260844.html,如需转载请自行联系原作者

相关文章
|
开发框架 前端开发 JavaScript
盘点72个ASP.NET Core源码Net爱好者不容错过
盘点72个ASP.NET Core源码Net爱好者不容错过
432 0
|
开发框架 .NET
ASP.NET Core NET7 增加session的方法
ASP.NET Core NET7 增加session的方法
165 0
|
开发框架 JSON .NET
ASP.NET Core 自定义配置警告信息
自定义配置警告信息需要在 startup 类中的 ConfigureService 方法中进行配置示例: // 注册 控制器服务 services.AddControllers(configure: setup => { setup.ReturnHttpNotAcceptable = true; ...
222 0
|
存储 开发框架 前端开发
asp.net与asp.net优缺点及示例
asp.net与asp.net优缺点及示例
268 0
|
XML 存储 JSON
使用自定义XML配置文件在.NET桌面程序中保存设置
本文将详细介绍如何在.NET桌面程序中使用自定义的XML配置文件来保存和读取设置。除了XML之外,我们还将探讨其他常见的配置文件格式,如JSON、INI和YAML,以及它们的优缺点和相关的NuGet类库。最后,我们将重点介绍我们为何选择XML作为配置文件格式,并展示一个实用的示例。
255 0
|
12月前
|
JSON 安全 API
.net 自定义日志类
在.NET中,创建自定义日志类有助于更好地管理日志信息。示例展示了如何创建、配置和使用日志记录功能,包括写入日志文件、设置日志级别、格式化消息等。注意事项涵盖时间戳、日志级别、JSON序列化、线程安全、日志格式、文件处理及示例使用。请根据需求调整代码。
185 13
|
Windows
.NET 隐藏/自定义windows系统光标
【10月更文挑战第20天】在.NET中,可以使用`Cursor`类来控制光标。要隐藏光标,可将光标设置为`Cursors.None`。此外,还可以通过从文件或资源加载自定义光标来更改光标的样式。例如,在表单加载时设置`this.Cursor = Cursors.None`隐藏光标,或使用`Cursor.FromFile`方法加载自定义光标文件,也可以将光标文件添加到项目资源中并通过资源管理器加载。这些方法适用于整个表单或特定控件。
225 0
|
开发框架 .NET Docker
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
201 1
|
开发框架 JSON .NET
ASP.NET Core 标识(Identity)框架系列(三):在 ASP.NET Core Web API 项目中使用标识(Identity)框架进行身份验证
ASP.NET Core 标识(Identity)框架系列(三):在 ASP.NET Core Web API 项目中使用标识(Identity)框架进行身份验证
234 1
|
开发框架 .NET 数据库连接
ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?
ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?
275 0

热门文章

最新文章