ASP.NET AJAX Futures January CTP中的一个Bug
还是比较喜欢ASP.NET AJAX早期版本中出现的xml绑定技术,这部分功能在正式版中虽然被移除了,但是在微软放出的CTP版本中依然存在,而且内部结构发生了很大的变化,唯一庆幸的是xml绑定的语法基本上没有变化,所以一直在研究这个版本。
首先说一下这个版本的优点,给我感觉最好的就是兼容主流浏览器,我用IE7、FireFox1.5.10和Opera9.10测试过,xml绑定都能够正常工作,看来微软还是下了一番功夫的。
但是,在这个版本中,实现xml绑定的核心Sys.Preview.Binding类中有个致命的Bug,会导致在某些情况下绑定出错。先看一下Sys.Preview.Binding.initialize的源代码:
function Sys$Preview$Binding$initialize() { Sys.Preview.Binding.callBaseMethod(this, 'initialize'); if (this.get_automatic()) { if (this._direction !== Sys.Preview.BindingDirection.In) { var target = this.get_target(); if (Sys.INotifyPropertyChange.isImplementedBy(target)) { this._targetNotificationHandler = Function.createDelegate(this, this._onTargetPropertyChanged); target.add_propertyChanged(this._targetNotificationHandler); } // 问题出现在这里,当direction不等于In,也就是Out或者InOut时, // 当target死掉时通知绑定target已经死掉, // 但是,如果Source死掉呢?怎么办?不知道。 if (Sys.INotifyDisposing.isImplementedBy(target)) { this._targetDisposingHandler = Function.createDelegate(this, this._onDisposing); target.add_disposing(this._targetDisposingHandler); } } if (this._direction !== Sys.Preview.BindingDirection.Out) { var source = this._getSource(); if (Sys.INotifyPropertyChange.isImplementedBy(source)) { this._sourceNotificationHandler = Function.createDelegate(this, this._onSourcePropertyChanged); source.add_propertyChanged(this._sourceNotificationHandler); } // 这里犯有同样的错误,当direction不等于Out,也就是In或者InOut时, // source死掉时会通知绑定source已死, // 但是却没有考虑让target死掉时也通知binding if (Sys.INotifyDisposing.isImplementedBy(source)) { this._sourceDisposingHandler = Function.createDelegate(this, this._onDisposing); source.add_disposing(this._sourceDisposingHandler); } this.evaluate(Sys.Preview.BindingDirection.In); } } }
既然是绑定,那个就应该不管是source还是target任意一方死掉时,都应该通知绑定,自己将死,让绑定做好善后工作,以上代码只要稍微修改一下,就可以正常工作了。
要改写这个方法,我们需要重写这个方法,修改好的代码如下:
Sys.Preview.Binding.prototype.initialize = function() { Sys.Preview.Binding.callBaseMethod(this, 'initialize'); if (this.get_automatic()) { var target = this.get_target(); var source = this._getSource(); if (this._direction !== Sys.Preview.BindingDirection.In) { if (Sys.INotifyPropertyChange.isImplementedBy(target)) { this._targetNotificationHandler = Function.createDelegate(this, this._onTargetPropertyChanged); target.add_propertyChanged(this._targetNotificationHandler); } } if (this._direction !== Sys.Preview.BindingDirection.Out) { if (Sys.INotifyPropertyChange.isImplementedBy(source)) { this._sourceNotificationHandler = Function.createDelegate(this, this._onSourcePropertyChanged); source.add_propertyChanged(this._sourceNotificationHandler); } this.evaluate(Sys.Preview.BindingDirection.In); } // 不管绑定的方向,不管target和source那个死掉,都要通知绑定,做好善后工作。 if (Sys.INotifyDisposing.isImplementedBy(target)) { this._targetDisposingHandler = Function.createDelegate(this, this._onDisposing); target.add_disposing(this._targetDisposingHandler); } if (Sys.INotifyDisposing.isImplementedBy(source)) { this._sourceDisposingHandler = Function.createDelegate(this, this._onDisposing); source.add_disposing(this._sourceDisposingHandler); } } }
不知道我的理解是否正确,随后,我会附上一个Demo的项目,来演示这个Bug。
张志敏所有文章遵循创作共用版权协议,要求署名、非商业 、保持一致。在满足创作共用版权协议的基础上可以转载,但请以超链接形式注明出处。
本博客已经迁移到 GitHub , 围观地址: https://beginor.github.io/