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/
浙公網安備 33010602011771號