使用ASP.NET AJAX异步调用Web Service和页面中的类方法(7):服务器端和客户端数据类型的自动转换:泛型集合类型
本文来自《ASP.NET AJAX程序设计 第II卷:客户端Microsoft AJAX Library相关》的第三章《异步调用Web Service和页面中的类方法》,请同时参考本章的其他文章。
3.7.4 泛型集合类型
.NET Framework 2.0中新引入的泛型集合类型不但能够大大提高程序的执行效率,也能让IDE在编译前就能了解更多的类型信息,进而在我们的开发过程中提供更完善的辅助信息。因此,作为“传统”集合的替代品,泛型集合类型正被越来越广泛地使用于各种.NET应用程序中。
ASP.NET AJAX异步通讯层也能够为常用的泛型集合类型自动生成相应的客户端JavaScript类型,让我们可以方便地在客户端和服务器端传递集合类型的数据。
对于泛型集合类型中的类型T,若为简单类型,那么ASP.NET AJAX异步通讯层将自动为我们生成客户端JavaScript类型。例如对于如下返回List<int>类型的Web Service方法:
[WebMethod]
public List<int> GetGenericIntList()
{
List<int> intList = new List<int>();
for (int i = 0; i < 10; ++i)
{
intList.Add(i * 10);
}
return intList;
}
若是为该Web Service添加了[ScriptService]属性,且用ScriptManager控件将其引入到了页面中的话,那么在客户端即可直接调用该Web Service方法。ASP.NET AJAX异步通讯层将自动把返回的List<int>类型转换为JavaScript中的数组,图3-22显示了返回值在Visual Studio调试器中显示出的结构。
图3-22 服务器端List<int>类型在客户端的结构
考虑如下接收一个List<int>参数的Web Service方法:
[WebMethod]
public void SendGenericIntList(List<int> intList)
{
// ......
}
我们即可用如下客户端代码将某个JavaScript数组传递到该SendGenericIntList()方法中,注意SendGenericIntList()方法所在的Web Service类为PeopleManagementService:
var intList = new Array();
for (var i = 0 ; i < 10; ++i) {
intList.push(i);
}
PeopleManagementService.SendGenericIntList(intList);
ASP.NET AJAX异步通讯层将自动把这个JavaScript数组转换为服务器端的List<int>类型,在程序运行中,SendGenericIntList()方法根本不会有所察觉。图3-23显示了传入参数在Visual Studio调试器中显示出的结构。
图3-23 客户端JavaScript数组可被自动转换为服务器端List<int>类型
而若是泛型集合类型中的类型T为复杂类型,那么我们则需要为Web Service类添加[GenerateScriptType(typeof([TypeName]))]属性,其中[TypeName]表示该复杂类型的名称。我们还是以前面的Employee类为例,考虑下面这个返回一个List<Employee>类型的Web Service方法:
[WebMethod]
public List<Employee> GetGenericEmployeeList()
{
List<Employee> employeeList = new List<Employee>();
for (int i = 0; i < 10; ++i)
{
Employee em = new Employee(
i,
string.Format("name {0}", i),
string.Format("name{0}@some.com", i),
5000
);
employeeList.Add(em);
}
return employeeList;
}
客户端调用该Web Service方法的代理之后,ASP.NET AJAX异步通讯层将自动把返回的List<Employee>类型转换为JavaScript中的数组,图3-24显示了返回值在Visual Studio调试器中显示出的结构。
图3-24 服务器端List<Employee>类型在客户端的结构
考虑如下接收一个List<Employee>参数的Web Service方法:
[WebMethod]
public void SendGenericEmployeeList(List<Employee> employeeList)
{
// ......
}
我们即可用如下客户端代码将某个包含客户端Employee对象的JavaScript数组传递到该SendGenericEmployeeList()方法中:
var employeeList = new Array();
for (var i = 0; i < 10; ++i) {
var em = new Employee();
em.Id = i;
em.Name = "name " + i;
em.Email = "name" + i + "@some.com";
em.Salary = 9000;
employeeList.push(em);
}
PeopleManagementService.SendGenericEmployeeList(employeeList);
ASP.NET AJAX异步通讯层将自动把这个JavaScript数组转换为服务器端的List<Employee>类型,SendGenericEmployeeList()方法同样不会有所察觉。图3-25显示了传入参数在Visual Studio调试器中显示出的结构。
图3-25 客户端包含Employee对象的JavaScript数组可被自动转换为服务器端List<Employee>类型
对于Dictionary<TKey, TValue>类型,ASP.NET AJAX异步通讯层也可以将其自动转换为客户端的相应类型——当然前提是如果TKey或TValue属于复杂类型,我们仍需要为Web Service类添加[GenerateScriptType(typeof([TypeName]))]属性,其中[TypeName]表示TKey或TValue复杂类型的名称。
我们还是以前面的Employee类为例,考虑如下服务器端Web Service方法:
[WebMethod]
public Dictionary<string, Employee> GetGenericEmployeeDictionary()
{
Dictionary<string, Employee> employeeDict = new Dictionary<string, Employee>();
for (int i = 0; i < 10; ++i)
{
Employee em = new Employee(
i,
string.Format("name {0}", i),
string.Format("name{0}@some.com", i),
5000
);
employeeDict[em.Id.ToString()] = em;
}
return employeeDict;
}
若是为该Web Service添加了[ScriptService]属性,且用ScriptManager控件将其引入到了页面中的话,那么在客户端调用该Web Service方法的代理即可得到Dictionary<string, Employee>相应的客户端JavaScript对象。客户端调用该Web Service方法的代码如下:
function pageLoad() {
PeopleManagementService.GetGenericEmployeeDictionary(onSucceeded);
}
onSucceeded()回调函数的代码如下,将GetGenericEmployeeDictionary()方法的返回值显示成一个表格,注意其中的for (var key in result)语句,用来遍历该客户端Dictionary中的键/值对:
function onSucceeded(result) {
var tableBuilder = new Sys.StringBuilder("<table border=1>");
// 创建表格标题行
tableBuilder.append(
"<tr><td>Id</td><td>Name</td><td>Email</td><td>Salary</td></tr>"
);
for (var key in result) {
var employee = result[key];
// 创建表格内容行
var rowString =
String.format(
"<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td></tr>",
employee.Id,
employee.Name,
employee.Email,
employee.Salary
);
tableBuilder.append(rowString);
}
tableBuilder.append("</table>");
$get("result").innerHTML = tableBuilder.toString();
}
运行本程序,我们将看到如图3-26所示的界面。
图3-26 取得服务器端Dictionary<string, Employee>类型的数据,并显示成表格