ASP.NET AJAX(7)_Microsoft AJAX Library扩展客户端组件继承时需要注意的问题扩展类型如何修改已有类型

首先,延续上一讲的内容,谈一下客户端面向对象类型系统中事件的使用

在C#中定义的一种方式
public class WorkEventArgs:EventArgs
{
      ...
}

public class SomeClass
{
      public event EventHandler<WorkEventArgs> Work;
      protected void OnWork(WorkEventArgs  e)
      {
             if(Work!=null)Work(this,e);
      }
}
在Microsoft AJAX Library中释放事件
  1. 定义EventHandlerList对象 MyNamespace.MyClass=function(){this._events=new Sys.EventHandlerList();}
  2. 添加add和remove事件
MyNamespace.MyClass.prototype=
{
         add_myEvent:function(handler)
         {
               this._events.addHandler("myEvent",handler);
          },
          remove_myEvent:function(handler)
          {
               this._events.removeHandler("myEvent",handler);
          },
          raiseMyEvent:function(e)
          {
                 var handler=this._events.getHandler("myEvent");
                 if(handler)
                {
                       handler(this.e);
                }
          }
}
一个定义和使用事件的示例

创建一个aspx页面,添加ScriptManager,以下是主要代码

<asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        
        <script language="javascript" type="text/javascript">
            Type.registerNamespace("Demo");//注册一个命名空间
            Demo.Firer = function() {//定义一个构造函数
                //this._events = new Sys.EventHandlerList();
                this._events = null;//我们只是声明,需要的时候再创建它
            }
            Demo.Firer.prototype =//定义成员
            {
                _get_events: function() {//获得类的EventHandlerList
                    if (!this._events) {//如果是NULL,则创建EventHandlerList对象
                        this._events = new Sys.EventHandlerList();
                    }
                    return this._events;
                },
                add_fire: function(handler) {
                    this._get_events().addHandler("fire", handler);
                },
                remove_fire: function(handler) {
                    this._get_events().removeHandler("fire", handler);
                },
                raiseFire: function(e) {
                    var hander = this._get_events().getHandler("fire");
                    if (hander) {
                        hander(this, e);
                    }
                },
                fireAfter: function(seconds) {
                    setTimeout(Function.createDelegate(this, this._timeoutCallback), seconds * 1000);
                },
                _timeoutCallback: function() {
                    this.raiseFire(Sys.EventArgs.Empty);
                }
            }
            Demo.Firer.registerClass("Demo.Firer");//注册这个类
            
            function text()
            {
                var firer=new Demo.Firer();
                firer.add_fire(onFireHandler);
                firer.fireAfter(2);
            }
            
            function onFireHandler(sender,e)
            {
                alert("I'm fired!");
            }
        </script>
        
        <input type="button" value="Text" onclick="text()" />

示例很简单,点击按钮,等待两秒钟后,触发事件

继承时需要注意的问题

toString,toLocaleString,valueOf,hasOwnProperty无法被继承,如果我们定义一个类A继承至类B,而在类A中没有定义toString方法,而我们使用B b=new B();b.toString();方法则只是输出当前的类名,这就是Microsoft AJAX Library设计上的一个问题,也不能说是它的问题吧,可能微软有微软的想法,我没有跟上它的想法而已

一个解决toString无法被继承的问题的示例
<script language="javascript" type="text/javascript">
        Type.registerNamespace("Demo");
        Demo.Parent = function() { }
        Demo.Parent.prototype = {
            toString: function() {
                return Object.getTypeName(this);
            }
        }
        Demo.Parent.registerClass("Demo.Parent");

        Demo.Child = function() {
            Demo.Child.initializeBase(this);
        }
        Demo.Child.prototype = {}
        Demo.Child.registerClass("Demo.Child", Demo.Parent);

        function text() {
            alert(new Demo.Parent()+"\n"+new Demo.Child());
        }
    </script>
    
    <input type="button" value="Text" onclick="text()" />

这时,如果我们点击按钮,按理说应该弹出"Demo.Parent\nDemo.Child",但是,试试上它弹出的是"Demo.Parent\n[object Object]"

那么我们要解决这个问题,就需要做如下操作

1.找到MicrosoftAJAX.debug.js(通常路径为C:\Program Files\Microsoft ASP.NET\ASP.NET 2.0 AJAX Extensions\v1.0.61025\MicrosoftAjaxLibrary\System.Web.Extensions\1.0.61025.0)

2.找到其中的Type.prototype.resolveInheritance这个方法

3.然后把它复制到页面代码的新建的一个<script>标记中

<script language="javascript" type="text/javascript">
        Type.prototype.resolveInheritance = function Type$resolveInheritance() {
            if (arguments.length !== 0) throw Error.parameterCount();

            if (this.__basePrototypePending) {
                var baseType = this.__baseType;

                baseType.resolveInheritance();

                for (var memberName in baseType.prototype) {//遍历定义在父类的成员
                    var memberValue = baseType.prototype[memberName];
                    if (!this.prototype[memberName]) {//如果子类中没有同名的成员
                        this.prototype[memberName] = memberValue;//把父类的成员复制到子类中
                    }
                }

                //以下是我们自己添加的代码
                var dontEnumMembers = ["toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable"];//所有无法继承的方法名
                for (var i = 0; i < dontEnumMembers.length; i++) {//遍历
                    var memberName = dontEnumMembers[i];
                    if (this.prototype[memberName] != Object.prototype[memberName]) {//如果自己的类中已经定义了这个方法
                        continue;//不做以下操作,继续循环
                    }
                    var memberValue = baseType.prototype[memberName];//得到父类的这个名字的方法
                    if (memberValue != Object.prototype[memberName]) {//判断是否有自己的实现
                        this.prototype[memberName] = memberValue;//把父类的对这个方法的实现,复制到子类
                    }
                }
                //添加的代码到此为止
                delete this.__basePrototypePending;
            }
        }
    </script>

5,我们刷新页面,得到了我们预期的效果,这段代码应该是很实用的,修补了Micorsoft AJAX Library的一个问题(当然我不确定是不是真的算是设计上的问题)

扩展类型

  • Microsoft AJAX Library提供了面向对象机制,可以用来扩展已有类型,优点是有一个标准的模式可用,缺点是工作量很大,并且并非真正的修改了类型

如何修改已有类型

  • 修改某个类的prototype成员
  • 为已有类型添加成员的操作
  • 修改某成员的步骤(1.备份prototype成员,定义同名成员,并在合适的时候使用以前的成员)
  • 优点:简单,容易实现
  • 缺点:修改父类可能无法在子类上体现
一个扩展已有类型的示例

创建一个aspx页面

<asp:ScriptManager ID="s" runat="server"></asp:ScriptManager>
        <script  language="javascript" type="text/javascript">
            Type.registerNamespace("Demo");

            Demo.Employee = function(name, year) {
                this._name = name;
                this._year = year;
            }
            Demo.Employee.prototype =
                {
                    get_name: function() {
                        return this._name;
                    },

                    get_year: function() {
                        return this._year;
                    },

                    _calculateSalary: function() {
                        return 3000;
                    },

                    toString: function() {
                        return this._name + ", " + this._calculateSalary();
                    }
                }
            Demo.Employee.registerClass("Demo.Employee");

            function text() {
                alert(new Demo.Employee("Xiaoyaojian", 5));
            }
        </script>
        
        <script language="javascript" type="text/javascript">
            var p = Demo.Employee.prototype;//得到Employee的成员
            p._old_calculateSalary = p._calculateSalary;//把父类的方法备份
            p._calculateSalary = function() {//重新定义这个方法
                return this._old_calculateSalary() + (this.get_year() - 1) * 2000;
            }
        </script>
    
        <input type="button" value="Xiaoyaojian" onclick="text()" />

演示,很简单,关键呢就在下面一个<script>标记里,我已经添加了注释,看懂应该不会有任何问题

这是一个对单独类的修改,那么如果有继承关系呢?往下看  最后一个示例

<asp:ScriptManager ID="d" runat="server"></asp:ScriptManager>
    
        <script language="javascript" type="text/javascript">
            Type.registerNamespace("Demo");
            Demo.Parent = function() { }
            Demo.Parent.prototype =
            {
                someMethod: function() {
                    return alert("Original someMethod.");
                }
            }
            Demo.Parent.registerClass("Demo.Parent");
            Demo.Child = function() {
                Demo.Child.initializeBase(this);
            }
            Demo.Child.prototype = {}
            Demo.Child.registerClass("Demo.Child", Demo.Parent);


            //new Demo.Child();
            Demo.Parent.prototype.someMethod = function() {
                return alert("I've been modified.");
            }

            function text() {
                new Demo.Child().someMethod();
            }
        </script>
        
        <input type="button" value="Xiaoyaojian" onclick="text()" />

这时,我们点击按钮,就会看到我们修改的父类someMethod方法,也体现到了子类,而当我们把注释掉的new Demo.Child();打开,我们就会看到了我们非常不愿意看到的效果,也是我一开始提到的,对父类的修改可能不会体现在子类上,这就是一个“可能”,因为当我们创建一个Child对象的时候,它已经去解决继承的问题,把父类的成员复制到子类中,我们再去修改父类的方法,就无法体现在子类上啦

完活。貌似今天完成的比较早了,下午三点四十,前几篇都是在晚上十一点以后完成的,生日也过了,感冒也好了,我想着尽快把关于Microsoft AJAX Library的这期写完,然后。。。。。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏企鹅号快讯

Java文件上传管理器 控制台

上传文件下载管理器项目技术 JDBC + IO + Socket 实现功能 客户端注册:通过输入用户名,密码,确认密码并且校验完成以后将用户信息储存在数据库中。...

2556
来自专栏大内老A

ASP.NET MVC基于标注特性的Model验证:将ValidationAttribute应用到参数上

ASP.NET MVC默认采用基于标准特性的Model验证机制,但是只有应用在Model类型及其属性上的ValidationAttribute才有效。如果我们能...

1948
来自专栏菩提树下的杨过

C#执行Javascript代码的几种方法

一、开源项目 Javascript .NET 地址: http://javascriptdotnet.codeplex.com/ 它是Google Chrome...

1865
来自专栏Flutter&Dart

DartVM服务器开发(第六天)--利用注解处理请求

下面,如果你跟着仔细操作,你将学会如何使用注解,使用反射获取注解、通过反射调用方法。

662
来自专栏Android 研究

Android插件化基础1-----加载SD上APK

大致的意思是: ClassLoader 是一个负责加载classes的对象,ClassLoader类是一个抽象类,需要给出类的二进制名称,ClassLoader...

763
来自专栏kwcode

ASP.NET 实现Base64文件流下载PDF

因为业务需要调用接口获取的是 Base64文件流 需要提供给客户下载PDF文档 源码部分借鉴网上,具体地址忘记了。 //Base64文件流 ...

2725
来自专栏大内老A

ASP.NET Core管道深度剖析(3):管道是如何处理HTTP请求的?

我们知道ASP.NET Core请求处理管道由一个服务器和一组有序的中间件组成,所以从总体设计来讲是非常简单的,但是就具体的实现来说,由于其中涉及很多对象的交互...

2065
来自专栏xiaoheike

hibernate一级缓存

Hibernate 一级缓存默认是打开,不需要任何的配置。实际上,你无法强制禁止它的使用。 如果你理解了一级缓存实际上和会话是关联的,就很容易理解一级缓存。总...

711
来自专栏Golang语言社区

GO语言标准错误处理机制error用法实例

本文实例讲述了GO语言标准错误处理机制error用法。分享给大家供大家参考。具体分析如下: 在 Golang 中,错误处理机制一般是函数返回时使用的,是对外的接...

4078
来自专栏跟着阿笨一起玩NET

.net如何自定义config配置文件节点

本文转载:http://www.cnblogs.com/lori/archive/2013/04/03/2997617.html

191

扫描关注云+社区