首页 / 网页编程 / ASP.NET / 一个较完整的关键字过滤解决方案(下)
一个较完整的关键字过滤解决方案(下)2011-04-17 博客园 Jeffrey Zhao在这篇文章里,我们来针对一些问题进行讨论。如果您觉得有哪些您感兴趣但是没有涉及 到的问题则请在评论中补充,我会修改文章添加一下内容。陷阱何在?首先,我们来分析上一篇文章最后谈到的“陷阱”。很可惜啊,过了两个星期还是没有朋 友能够指出这个问题,其实很简单,运行一下就能发觉有异常抛出:public partial class Default : System.Web.UI.Page, IForbiddenWordFilter
{
...
FilterForbiddenWordType IForbiddenWordFilter.GetFilterType(string key)
{
if (key.EndsWith(this.txtPassword.ID)) return FilterForbiddenWordType.Ignored;
return FilterForbiddenWordType.Normal;
}
}在运行至this.txtPassword.ID时会抛出NullReferenceException。其原因就是,我们的 FilterForbiddenWordModule在OnPostMapRequestHandler过程中进行调用,而此时Handler对 象已经生成(意味着IForbiddenWordFilter.GetFilterType方法已经可以调用),但是直到 Handler被执行时this.txtPassword才被实例化(从现象得出的结论,是否确切有待考证), 自然会抛出NullReferenceException了。可是我实在想不出一个办法可以在得到 this.txtPassword.ID的值,甚至退一步讲,我无法在运行时得到this.txtPassword这个 field的名称——即一个字符串“txtPassword”。我不可能直接使用这个字符串常量,这样 就会使我们的改进效果付之东流。我们需要通过代码来访问,因为我们需要能够得到编译及 重构的支持,不是吗?起初我很绝望,但是10分钟后忽然灵光一闪,想到了这种方式来获得field的名称:FilterForbiddenWordType IForbiddenWordFilter.GetFilterType(string key)
{
Expression<Func<object>> action = () => this.txtPassword;
var name = (action.Body as MemberExpression).Member.Name;
if (key.EndsWith(name)) return FilterForbiddenWordType.Ignored;
return FilterForbiddenWordType.Normal;
}这是一个非常实用的技巧:通过Lambda表达式来构造一个表达式树,然后通过这个表达式 树的成员来获取field的名称。我们享受到了我们所需的便利,因为个中实现已经由编译器完 成(或许我会另写文章来阐述一下我在关于这个方面的思维过程)。适用场合有的时候我觉得谈适用场合比较虚,因为其实关键是在“思考”。“官方”提出的适用场 合并不一定完整和正确,了解了一个解决方案之后慢慢会有更好的体会,甚至更真实。如果 一个解决方案是通过一个适用场合引发的,那么这个解决方案的适用场合“似乎”不言而喻 。此外,如果一个解决方案是像我们现在的这样一样,从实际出发,再发散,慢慢将功能补 充完整,最后几经权衡之后反而有些违背初衷,那么谈适用场合其实就是在谈“理解”,当 你理解了这个解决方案的特性,适用场合和不适用场合都可以简单地判断出来。所以再虚还 是要谈,至少要摆个样子思考一下。例如:我们是在输入的时候进行过滤,那么服务器端得到的数据已经是替换后的内容,因 此如果你要用户原本输入的内容,肯定就不能采用这个方法。嗯?完了?当然没完,但是下面就要由您来进行思考了。:)