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。
posted @ 2007-03-17 15:55  张志敏  阅读(3508)  评论(4编辑  收藏  举报