注册 | 登录 忘记密码? 51cto首页 | 博客 | 论坛 | 招聘
热点文章 IB客座主编(四)美国西蒙公..
 帮助

深入Atlas系列:Web Sevices Access in Atlas示例(1) - 特别的访问方式


2006-10-12 14:32:11
版权声明:原创作品,如需转载,请与作者联系。否则将追究法律责任。
  注意:部分内容已经过期,请结合《深入Atlas系列:Web Sevices Access in Atlas(7) - RTM中的客户端支持》阅读此文。

  在《深入Atlas系列:Web Sevices Access in Atlas(1) - 客户端支持》 里我们分析了Atlas客户端以AJAX方式访问Web Services方法所使用的基础代码,那就是Sys.Net.ServiceMethod,它提供了对于Web Service方法访问的封装。有了它,我们可以很方便地访问Web Services方法。但是在Atlas中,我们有更加方便的访问方式,在这篇文章里,我们就来讨论一下这些方法。


一、使用Sys.Net.ServiceMethod.invoke静态方法访问Web Services

   如果阅读了Atlas代码之后,可以发现在客户端一些需要访问Web Services方法的类,例如AutoCompleteBehavior,它们在访问Web Services方法的时候并没有直接使用Sys.Net.ServiceMethod,而是调用了Sys.Net.ServiceMethod类的静态 方法invoke。在以后的文章中我会分析Atlas客户端对Web Service方法提供代理的实现,届时也能发现,事实上在代理内部,使用的也是该静态方法。这个静态方法相当简单,不过我们还是来分析一下吧。代码如 下:
Sys.Net.ServiceMethod.invoke静态方法分析

  代码如想象中的简单,只是在静态方法内部构造一个Sys.Net.ServiceMethod类的对象,并调用它的invoke方法。由于Sys.Net.ServiceMethod的invoke方法提供了“神奇”的“函数重载”(详细信息请见《深入Atlas系列:Web Sevices Access in Atlas(1) - 客户端支持》的分析),因此Sys.Net.ServiceMethod.invoke静态方法也能通过两种方式调用,如下:

  第一种是:
Sys.Net.ServiceMethod.invoke静态方法分析

  第二种是:
Sys.Net.ServiceMethod.invoke静态方法分析

  于是,以后就能使用这种比较简洁的方式访问Web Services方法了。


二、使用Declarative Syntax访问Web Services方法

  深入代码可以发现各种有效的使用方式,尤其在现在这样文档极其匮乏的时期。事实上,对于使用Declarative Syntax访问Web Services的描述才是这篇文章的重点。仔细Atlas代码之后,可以发现在这样一个类:
1 Sys.Net.ServiceMethodRequest = function() {
2     ……
3 }
4 Sys.Net.ServiceMethodRequest.registerClass('Sys.Net.ServiceMethodRequest', Sys.Component);
5 Sys.TypeDescriptor.addType('script', 'serviceMethod', Sys.Net.ServiceMethodRequest);

  在我之前的文章《使用Atlas创建自己的Client Control》 里简单分析了一点:使用Sys.TypeDescriptor.addType方法能够为一个类提供Declarative Syntax的支持。关于这一点的具体实现方式已经超出了现在这篇文章的讨论范围,但是我会在“深入Atlas系列”的后续文章里从实现角度具体分析 Atlas对于Xml Scripts的解析方式,敬请留意。:)

  对于支持Declarative Syntax的类,其最重要的方法应该就是this.getDescriptor了(确切的说,这个是 Sys.ITypeDescriptorProvider接口的方法。对于没有实现该接口的类,Atlas在识别其成员时使用的是别的方式。不过由于 Sys.Component实现了Sys.ITypeDescriptorProvider接口,因此我们如果继承了Sys.Component,只要重 载getDescriptor方法就可以了)。它提供了对于类成员的描述,Atlas在进行操作时会频繁使用这些信息,因此该方法非常重要。我们来看一下 它在Sys.Net.ServiceMethodRequest中的实现:
getDescriptor方法实现

  以上就是Sys.Net.ServiceMethodRequest类的成员描述,应该说还是相当直观的。

  接着开始分析Sys.Net.ServiceMethodRequest类的主要成员,一些属性的get/set方法就忽略了。其实整个类唯一作用较大的方法就是this.invoke。代码如下:
this.invoke方法分析

  整个Sys.Net.ServiceMethodRequest类的代码就分析完了!看得出来它只是对 Sys.Net.ServiceMethod类进行了一个封装,但是就是这种简单的封装就能提供Declarative Syntax支持!原因就在于Atlas的代码已经对于解析Xml Scripts和识别一个类做了非常多的工作,我们当然就省事了。

   不过在这个类中,有一个非常有意思的成员,那就是parameters属性。它是个只读属性,返回一个对象作为参数字典,我们能够对其以key - value的方式进行设置。事实上我们不是第一次遇到这个东西了。在最常用的Action之一:Sys.InvokeMethodAction就有该参 数,该参数允许这样使用:
<parameters param1="value1" param2="value2" ... />

  很自然,我们的parameters属性也能如此使用。Atlas在解析Xml时对于这样的情况,会将Xml属性名和值以key - value的形式存放在该parameters对象中。

   但是,这远远不够!我们为什么要在getDescripter方法中给出该属性的定义?目的不是为了给我们的代码调用(只要存在我们代码就能访问,根本 无须通过这个方法获得类成员),而是为了让Declarative Syntax识别!有了类成员的描述,我们就能使用各种Action,还有Atlas的特色之一:Binding。

  对了,大家应该也 已经想到了,我们可以将parameters属性和“别的什么”绑定起来啊。但是先别高兴太早,因为parameters是只读属性,按照普通的方法无法 将一个值赋于该属性。但是Atlas想到了这一点,它的Binding能够处理这种情况。在后面的例子中可以看到,我们可以如此使用Binding。
<bindings>
    
<binding dataContext="txtName" dataPath="text" property="parameters" propertyKey="name" />
    
<binding dataContext="txtAge" dataPath="text" property="parameters" propertyKey="age" />
</bindings>

  这里使用到了目前文档中不曾记载的Binding使用方式,它用到了propertyKey。Atlas在处理Binding时,如果发现用 户提供了propertyKey,则首先使用property的get方法获得这个对象的属性的值,然后再把propertyKey的值作为key,以 key - value的方式设置该属性。这个做法简直就是为了parameters这样的属性量身定制的!

  Sys.Net.ServiceMethodRequest类的分析到这里应该就足够了。接下来,我们通过一个例子来具体看一下该如何使用Declarative Syntax调用Web Services方法。


三、使用Declarative Syntax访问Web Services方法范例

  首先,我们定义所需要使用的Web Services方法和类:
EmployeeService.asmx文件代码

  每次调用AddEmployee方法会在List中增加一个Employee对象,并输出整个Employee对象。

  接下来是HTML:
HTML代码

  这个范例的目的是在两个文本框(txtName和txtAge)里填写一个Employee的姓名和年龄,然后点击按钮btnInvoke之 后会调用Web Services方法增加一个Employee并得到一个Employee列表,然后显示在页面上。在这里,我会使用Atlas中的 Sys.UI.Data.ListView控件来显示Employee列表。关于该控件的使用方式,可以参考Dflying兄的文章《使用ASP.NET Atlas ListView控件显示列表数据》。

  然后就是最重要的Atlas Xml Scripts了:
Atlas Xml Scripts

  我们关注一下最重要的<serviceMethod />使用吧,正如之前所提到的,我将txtName的值与name参数绑定起来,并且将txtAge的值与age参数绑定起来,就是这么简单。

   嗯,先不急着运行,是不是看出什么问题来了?对,我们为什么没有将employeeService的result属性和listView的data属性 绑定起来的呢?否则我们如何获得数据呢?其实我也想,这可以说是Sys.Net.ServiceMethodRequest的一个Bug:它在 result更新是不会调用this.raisePropertyChanged方法!这样Binding怎么可能收到result更新的信息呢?对于这 点我也相当无语。没有办法我们只能响应completed事件,让它调用onComplete这个javascript方法了。onComplete方法 代码如下:
onComplete方法

  代码非常简单,就这样起效果了。我们来看一下使用吧:

  首先打开页面,会看到显示为No Data:


  在文本框内输入信息并点击按钮,则可以添加一个Employee,反复多次则添加多个:




四、开发自己的Componet,完全使用Declarative Syntax访问Web Services方法

   必须借助于Javascript才能完成任务,是不是总是觉得心理有点别扭?至少我是这样的。而且除此之外, Sys.Net.ServiceMethodRequest还有一个不合理的地方:它的Priority属性类型是Number,在写Xml的时候就必须 把数字赋予该属性。因此,我们来修改一下它的代码,开发一下一个更好的ServiceMethodRequest吧。

  本想继承 Sys.Net.ServiceMethodRequest并重载invoke函数可是令人惊讶的是,我们无法这样做,因为 Sys.Net.ServiceMethodRequest没有调用registerBaseMethod来注册invoke函数。虽然我们依旧可以写一 个this.invoke = function() { ... }也可以正确运行,但是这个不是OO的Good Practise,因此我还是完整的写了一遍代码。

  由于大部分代码和Sys.Net.ServiceMethodRequest相同,那么我就给出一小部分不同的代码吧。
Jeffz.Net.ServiceMethodRequest部分代码