原文地址:http://dotnetslackers.com/articles/atlas/xml_script_tutorial_part1.aspx


asp.net ajax xml-script教程(一)


原文发布日期:2006.12.01
作者:Alessandro Gallo
翻译:webabcd


概述
asp.net ajaxt提供了一种通过使用声明程序模型来实例化客户端类型的方法。下面的代码给出了一个最简单的例子,用来在页面加载完毕后显示一段信息。
<%@ Page %>    
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0    
Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">    
<html xmlns="http://www.w3.org/1999/xhtml" >    
    <head runat="server">            
        <title>Hello XML-script</title>    
    </head>    
    <body>            
    <form id="form1"    

runat="server">            
    <asp:ScriptManager ID="TheScriptManager" runat="server">                    
     <Scripts>                            
        <asp:ScriptReference    
            Assembly="Microsoft.Web.Preview"
Name="Microsoft.Web.Resources.ScriptLibrary.PreviewScript.js" />                        
     </Scripts>            
    </asp:ScriptManager>            
    <script type="text/xml-script">                    
        <page xmlns="http://schemas.microsoft.com/xml-script/2005">
            <components>                            
                <application load="page_load" />                    
            </components>                    
        </page>            
    </script>            
    <script type="text/javascript">            
    <!--                    
    function page_load(sender, e)    
    {                            
        alert("Hello World!");                    
    }            
    //-->            
    </script>            
    </form>    
    </body>    
</html>
 
注意,如果要使用xml-script特性的话,你需要在微软的ajax站点下载Futures CTP package,然后引用PreviewScript.js这个文件,该文件包含在Microsoft.Web.Preview程序集中。

声明代码总是要内嵌到一个脚本标记下,这个脚本标记的type属性为text/xml-script。这段声明代码并不难理解。我们这里有一个封装了components元素的page根元素,它是一般xml-script的标准写法。

在components元素下有一个application节点,设置其load属性的值为一段javascript代码的函数名称。这个load属性被解析成一个事件名称,它的值指向一个客户端函数,该客户端函数将被增加到一个事件处理列表中。因为application元素被映射到了Sys.Application实例,所以当Sys.Application触发了它的load事件的时候,page_load()将被调用。

这是如何实现的呢?声明代码是以xml元素和方法之间的映射为基础的,属性和事件是通过asp.net ajax类来被使用的。这种映射在每一个有类型描述符的类中都存在,而每一个有类型描述符的类都可以在声明代码中被使用。


类型描述符
类型描述符是一个对象,它用来描述类的属性,方法和时间。每个想要提供类型描述符的类都必须实现ITypeDescriptorProvider接口,该接口定义了一个被称做getDescriptor()的方法。这个方法必须返回一个关联到类的类型描述符。ITypeDescriptorProvider接口的原型如下:
Sys.Preview.ITypeDescriptorProvider.prototype = {            
    getDescriptor: Sys$Preview$ITypeDescriptorProvider$getDescriptor    
}
 
另一个实现类型描述符的方法是给类增加描述符扩展。如果我们看一下PreviewScript.js文件(在Sys.Preview命名空间下),会发现一些通过这个方法扩展出来的类型描述符。例如,接下来的代码出示了Sys.Preview.Button类下的类型描述符。
Sys.Preview.UI.Button.descriptor = {            
    properties: [ { name: 'command', type: String },                                    
                                { name: 'argument', type: String } ],            
    events: [ { name: 'click' } ]    
}
 
一个类型描述符就是一个对象(用“,”来分隔开每个“属性-值”对比如{ name: "value" }就是一个“属性-值”对),类型描述符的包含属性如下:
    ·properties:一个属性描述符的数组
    ·events:一个事件描述符的数组
    ·methods:一个方法描述符的数组

每一个数组都包含着一组描述符,此时这些描述符的作用是用来描述一个详细的属性、事件或方法的。例如,让我们看一下事件数组中包含的描述符。
{ name : 'click' }
 
这个简单的描述符告诉了我们,Button类有一个名称为click的事件。属性数组中包含两个描述符。
{ name: 'command', type: String }    
{ name: 'argument', type: String }
 
第一个描述符描述了一个被称做command的属性,类型是string型。第二个描述符告诉我们Button类有一个string类型的属性,被称做argument。

类型描述符能够反映出客户端类型,它从xml-script中被独立出来。但是,xml-script解析器会在声明代码里把属性、方法和事件映射到xml元素中。

通过查看这个类型描述符,我们即使不了解xml-script是如何工作的,也可以写一段创建类型实体所需的声明代码。用Button类的类型描述符比较一下下面的这段xml
<button id="myButton" command="save" click="myButton_click" />

在上面这段xml里,类的名字(Sys.Preview.UI.Button)被映射到了元素的名字(button),属性都是一一对应的,而且事件也被映射成了属性,这个事件属性的值被设置成一个javascript函数名,由这个函数来负责处理click事件。

它的id属性是从哪来的呢?Button类继承自Sys.Component,它id属性也是继承自这个类。如果你在PreviewScript.js文件中搜索Sys.Component的类型描述符,你就会发现有一个id属性的类型描述符。
Sys.Component.descriptor = {            
    properties: [ {name: 'dataContext', type: Object},                                    
                                {name: 'id', type: String},
                                {name: 'isInitialized', type: Boolean, readOnly: true},
                                {name: 'isUpdating', type: Boolean, readOnly: true} ],            
    events: [ {name: 'propertyChanged'} ]    
}
描述一个方法也需要提供方法参数的类型描述符。下面的代码出示了从Sys.Preview.Net.ServiceMethodRequest类中提出来的方法属性。
methods: [ {name: 'invoke', params: [ {name: 'userContext', type: Object} ] } ]
在这个例子中,这个类暴露了一个被称做invoke的方法(通过方法描述符的name属性得知)。这个方法接收一个被称做userContext的参数,这个参数的类型是Object。参数在params属性中被描述,每一个参数都有相关的参数描述符。


结论
在这篇教程里,我们看到了在asp.net页中包含声明代码的基础示例。然后我们介绍了类型描述符,并且知道如何看懂它们。类型描述符为客户端类型提供了了反射,它们在声明程序模型中被使用,这种声明程序模型允许使用xml语法来实例化客户端类型。

在下一篇教程里我们继续学习类型描述符和xml元素之间的映射。