原文地址:http://dotnetslackers.com/articles/atlas/xml_script_tutorial_part1.aspx
作者:Alessandro Gallo
原文发布日期:2006.12.01
概述
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"
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
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元素之间的映射。![](https://www.cnblogs.com/webabcd/aggbug/627812.html)
文章来源:http://www.cnblogs.com/webabcd/archive/2007/01/23/627812.html
asp.net ajax xml-script教程(一)
作者:Alessandro Gallo
原文发布日期:2006.12.01
概述
asp.net ajaxt提供了一种通过使用声明程序模型来实例化客户端类型的方法。下面的代码给出了一个最简单的例子,用来在页面加载完毕后显示一段信息。
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
注意,如果要使用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接口的原型如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
另一个实现类型描述符的方法是给类增加描述符扩展。如果我们看一下PreviewScript.js文件(在Sys.Preview命名空间下),会发现一些通过这个方法扩展出来的类型描述符。例如,接下来的代码出示了Sys.Preview.Button类下的类型描述符。
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
一个类型描述符就是一个对象(用“,”来分隔开每个“属性-值”对比如{ name: "value" }就是一个“属性-值”对),类型描述符的包含属性如下:
·properties:一个属性描述符的数组
·events:一个事件描述符的数组
·methods:一个方法描述符的数组
每一个数组都包含着一组描述符,此时这些描述符的作用是用来描述一个详细的属性、事件或方法的。例如,让我们看一下事件数组中包含的描述符。
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
这个简单的描述符告诉了我们,Button类有一个名称为click的事件。属性数组中包含两个描述符。
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
第一个描述符描述了一个被称做command的属性,类型是string型。第二个描述符告诉我们Button类有一个string类型的属性,被称做argument。
类型描述符能够反映出客户端类型,它从xml-script中被独立出来。但是,xml-script解析器会在声明代码里把属性、方法和事件映射到xml元素中。
通过查看这个类型描述符,我们即使不了解xml-script是如何工作的,也可以写一段创建类型实体所需的声明代码。用Button类的类型描述符比较一下下面的这段xml
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
在上面这段xml里,类的名字(Sys.Preview.UI.Button)被映射到了元素的名字(button),属性都是一一对应的,而且事件也被映射成了属性,这个事件属性的值被设置成一个javascript函数名,由这个函数来负责处理click事件。
它的id属性是从哪来的呢?Button类继承自Sys.Component,它id属性也是继承自这个类。如果你在PreviewScript.js文件中搜索Sys.Component的类型描述符,你就会发现有一个id属性的类型描述符。
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
描述一个方法也需要提供方法参数的类型描述符。下面的代码出示了从Sys.Preview.Net.ServiceMethodRequest类中提出来的方法属性。
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
在这个例子中,这个类暴露了一个被称做invoke的方法(通过方法描述符的name属性得知)。这个方法接收一个被称做userContext的参数,这个参数的类型是Object。参数在params属性中被描述,每一个参数都有相关的参数描述符。
结论
在这篇教程里,我们看到了在asp.net页中包含声明代码的基础示例。然后我们介绍了类型描述符,并且知道如何看懂它们。类型描述符为客户端类型提供了了反射,它们在声明程序模型中被使用,这种声明程序模型允许使用xml语法来实例化客户端类型。
在下一篇教程里我们继续学习类型描述符和xml元素之间的映射。
文章来源:http://www.cnblogs.com/webabcd/archive/2007/01/23/627812.html