博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Asp.Net之自定义表达式构造器(ExpressionBuilder)
阅读量:6251 次
发布时间:2019-06-22

本文共 6363 字,大约阅读时间需要 21 分钟。

在Asp.Net的Page页面中我们经常会使用到资源文件。读取资源文件的方式为:<%$Resources:Resource1,Test1%>,这样就可以显示Resource1这个资源文件中的Test1的键值,并且在页面设计过程中就可以正确的显示资源文件中的值了。这里就是使用到了.Net中的表达式构造器,那么它是如何实现的?我们能不能定义自己的表达式构造器呢?本文通过构建一个简单的Xml表达式构造器来说明这一过程。 

首先来看看Asp.Net中的表达式构造器是如何实现的

默认在C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config中我们可以找到如下配置节:

 

在这里定义了三个表达式构造器:Resources,ConnectionStrings,AppSettings。因此我们可以在页面中直接使用它们,比如可以使用<%$AppSettings:aa %>来读取AppSettings的配置。注意这里使用的是$符号,它是读取表达式构造器的专用标识。

接下来重点看看如何实现自己的表达式构造器

我们的目的是实现一个简单的Xml表达式构造器,可以读取指定xml文件中的配置信息,并且在页面设计阶段就可以看到效果。
一、修改配置
在自己的web.config中加入配置:

 

表示我们的表达式构造器的前缀为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值,为了测试,没有考虑性能和异常的问题        public static string GetXmlKey(string strKey)        {            string[] keys = strKey.Split(',');            string strFile = HttpContext.Current.Server.MapPath("/") + keys[0] + ".xml";                        XmlDocument xmlDoc = new XmlDocument();            xmlDoc.Load(strFile);            XmlNodeList nodeList = xmlDoc.SelectSingleNode("test").ChildNodes;            foreach (XmlNode xn in nodeList)            {                if (xn is XmlElement)                {                    if (xn.Name == keys[1])                    {                        return (xn as XmlElement).GetAttribute("value");                    }                }            }            return "";        }        public static object GetXmlKey(string key, Type targetType, string propertyName)        {            return GetXmlKey(key);        }

在这里定义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页面中调用:

运行此页面就可以正确的显示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继承

在我们的例子中只需要实现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方法如下:

//取得Xml中的key值,为了测试,没有考虑性能和异常的问题        public static string GetXmlKey(string strKey, string strFileName)        {            string[] keys = strKey.Split(',');            string strFile = "";            if (String.IsNullOrEmpty(strFileName))            {                strFile = HttpContext.Current.Server.MapPath("/") + keys[0] + ".xml";            }            else            {                strFile = strFileName;            }            XmlDocument xmlDoc = new XmlDocument();            xmlDoc.Load(strFile);            XmlNodeList nodeList = xmlDoc.SelectSingleNode("test").ChildNodes;            foreach (XmlNode xn in nodeList)            {                if (xn is XmlElement)                {                    if (xn.Name == keys[1])                    {                        return (xn as XmlElement).GetAttribute("value");                    }                }            }            return "";        }        public static object GetXmlKey(string key, Type targetType, string propertyName)        {            return GetXmlKey(key, "");        }        public static string GetXmlKey(string strKey)        {            return GetXmlKey(strKey, "");        }

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

转自:

转载地址:http://mrusa.baihongyu.com/

你可能感兴趣的文章
alias命令详情
查看>>
自定义异步加载资源插件
查看>>
easyui combobox两种不同的数据加载方式
查看>>
Smarty配置与实例化
查看>>
***Redis hash是一个string类型的field和value的映射表.它的添加、删除操作都是O(1)(平均)。hash特别适合用于存储对象...
查看>>
Siege——多线程编程最佳实例
查看>>
c# 生成 验证码
查看>>
SQL Server 触发器
查看>>
何为SLAM
查看>>
[工具]infolite-chrome插件css插件
查看>>
javascript 深拷贝
查看>>
【代码小记】无
查看>>
【知识点】Java机密
查看>>
BarTender 2016表单中的“秤显示”控件
查看>>
全面理解javascript的caller,callee,call,apply概念[转载]
查看>>
Jquery 下拉框取值
查看>>
IDEA中使用Maven创建Java Web项目
查看>>
2017.12.25
查看>>
react--1.创建项目
查看>>
11月20日学习内容整理:jquery插件
查看>>