ASP.NET AJAX Programmer’s Reference - Chapter 10 pot

58 342 0
ASP.NET AJAX Programmer’s Reference - Chapter 10 pot

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Type Description Extensions The ASP.NET Framework provides you with two ways to inspect the metadata associated with a given type: reflection and TypeDescriptor . Metadata inspection plays a central role in the ASP.NET Framework. For example, metadata inspection is an integral part of the ASP.NET server controls such as GridView , where data records come from many different data sources. It is a well-known fact that different types of data stores expose different types of data records. For example, data records stored into or retrieved from a relational database via the ADO.NET layer normally are of type DataRow or DataRowView . Data records stored into or retrieved from an XML document via the .NET XML layer are of type XmlNode . If an ASP.NET server control such as GridView were to know about the actual type of the data records being retrieved or stored, it would be tied to a particular type of data record, and, consequently, a particular type of data store. For example, if an ASP.NET server control were to directly interact with the DataRow or DataRowView objects returned from the ADO.NET layer, it would not be able to interact with XmlNode objects returned from the .NET XML layer. In other words, the server control would only be able to retrieve data from and store data into a relational database via the ADO.NET layer and would not be able to retrieve data from and store data into an XML document via the .NET XML layer. The metadata inspection capabilities of the .NET Framework allows a server control such as GridView to interact with the data records in generic fashion without knowing their actual types. This allows the same server control to retrieve and store any type of data records. The ASP.NET AJAX client-side framework introduces two metadata inspection facilities that emulate their .NET counterparts, reflection and TypeDescriptor . Previous chapters covered the reflection capabilities of the ASP.NET AJAX client-side framework. This chapter discusses the ASP.NET AJAX type description capabilities, which emulate the .NET type description capabilities. As you’ll see later, the ASP.NET AJAX type descriptions provide the client controls with the same capabilities as their server counterparts. These capabilities enable the client controls to deal with data records in a generic fashion without having to know their actual types. The ASP.NET AJAX type description infrastructure consists of the following main components: ❑ TypeDescriptor ❑ ICustomTypeDescriptor c10.indd 349c10.indd 349 8/20/07 6:08:12 PM8/20/07 6:08:12 PM Chapter 10: Type Description Extensions 350 TypeDescriptor The ASP.NET AJAX client-side framework includes a client class named TypeDescriptor that emulates the ASP.NET server-side TypeDescriptor class. The following sections discuss the members of this client class. Constructor Listing 10-1 presents the implementation of the TypeDescriptor client class’s constructor. As the name suggests, a TypeDescriptor object describes a type. A type exposes up to three different kinds of members: properties, methods, and events. Every type can also be annotated with zero or more metadata attributes that provide more information about the type. A type also inherits the properties, methods, events, and attributes of its base types. Therefore, a com- plete description of a type must include the type’s and its ancestor type’s properties, methods, events, and attributes. That is why the TypeDescriptor client class in Listing 10-1 exposes four properties named properties , methods , events , and attributes . As the listing shows, the TypeDescriptor class also exposes four getter methods named _get _properties , _get_methods , _get_events , and _get_attributes that provide access to these four properties. The following sections discuss these properties. Listing 10-1: The Constructor of the TypeDescriptor Client Class Sys.Preview.TypeDescriptor = function Sys$Preview$TypeDescriptor() { var _properties = { }; var _events = { }; var _methods = { }; var _attributes = { }; this._getAttributes = function this$_getAttributes() { return _attributes; } this._getEvents = function this$_getEvents() { return _events; } this._getMethods = function this$_getMethods() { return _methods; } this._getProperties = function this$_getProperties() { return _properties; } } Sys.Preview.TypeDescriptor.registerClass(‘Sys.Preview.TypeDescriptor’); c10.indd 350c10.indd 350 8/20/07 6:08:12 PM8/20/07 6:08:12 PM Chapter 10: Type Description Extensions 351 _properties This property references a JavaScript object literal that contains one name/value pair for each property of the type (or its base type) that the TypeDescriptor object describes. The name part of each name/ value contains the name of the property associated with the pair. The value part of each name/value pair is a JavaScript object literal that describes the property associated with the pair. This JavaScript object literal contains up to five name/value pairs, where each pair provides a piece of metadata information about the property that the object literal describes, as follows: ❑ The first name/value pair specifies the name of the property. The name part of this name/value pair is name , and the value part is a string that contains the name of the property. ❑ The second name/value pair describes the type of the property. The name part of this name/ value pair is type , and the value part references the constructor of the property type. ❑ The third name/value pair specifies whether the property is read-only. The name part of this name/value pair is readOnly , and the value part is a Boolean value. ❑ The fourth name/value pair describes the metadata attributes that annotate the type of the property. The name part of this name/value pair is attributes , and the value part is an object that contains the attributes. ❑ The fifth name/value pair specifies whether the property references a DOM element. The name part of this name/value pair is isDomElement , and the value part is a Boolean value. For example, the Component base class exposes the properties shown in the following table. Property Name Property Type Read Only dataContext Object False id String False isInitialized Boolean True isUpdating Boolean True Based on this table, the _properties property of the TypeDescriptor object that describes the Component base class references the JavaScript object literal shown in Listing 10-2 . Listing 10-2: The JavaScript Object Literal Referenced by the _properties of the TypeDescriptor Object that Describes the Component Base Class { ‘dataContext’: {name: ‘dataContext’, type: Object, readOnly: false}, ‘id’: {name: ‘id’, type: String, readOnly: false}, ‘isInitialized’: {name: ‘isInitialized’, type: Boolean, readOnly: true}, ‘isUpdating’: {name: ‘isUpdating’, type: Boolean, readOnly: true} } This object literal contains five name/value pairs. The name part of each of these name/value pairs contains the name of a property — dataContext , id , isInitialized , and isUpdating . The value part of each of these name/value pairs contains the JavaScript object literal that describes the corresponding c10.indd 351c10.indd 351 8/20/07 6:08:13 PM8/20/07 6:08:13 PM Chapter 10: Type Description Extensions 352 property of the Component base class: ❑ {name: ‘dataContext’, type: Object, readOnly: false} ❑ {name: ‘id’, type: String, readOnly: false} ❑ {name: ‘isInitialized’, type: Boolean, readOnly: true} ❑ {name: ‘isUpdating’, type: Boolean, readOnly: true} Now, let’s take a look at the content of the TypeDescriptor object’s _properties property. Because the Control class derives from the Component base class, it inherits all the properties of its base class. The following table presents all the properties of the Control base class, including those that it inherits from its base class. Property Name Property Type Read Only dataContext Object false Id String false isInitialized Boolean true isUpdating Boolean true Element Object true Role String true Parent Object false Visible Boolean false visibilityMode Sys.UI.VisibilityMode false Based on this table, the _properties property of the TypeDescriptor object that describes the Control base class references the JavaScript object literal shown in Listing 10-3 . Listing 10-3: The JavaScript Object Literal Referenced by the _properties of the TypeDescriptor Object that Describes the Control Base Class { ‘dataContext’: {name: ‘dataContext’, type: Object, readOnly: false}, ‘id’: {name: ‘id’, type: String, readOnly: false}, ‘isInitialized’: {name: ‘isInitialized’, type: Boolean, readOnly: true}, ‘isUpdating’: {name: ‘isUpdating’, type: Boolean, readOnly: true}, ‘element’: {name: ‘element’, type: Object, readOnly: true}, ‘role’: {name: ‘role’, type: String, readOnly: true}, ‘parent’: {name: ‘parent’, type: Object, readOnly: false}, ‘visible’: {name: ‘visible’, type: Boolean}, ‘visibilityMode’: {name:’visibilityMode’, type: Sys.UI.VisibilityMode, readOnly:false} } Listing 10-4 shows a page that enables you to display the _properties property of the TypeDescriptor object associated with any ASP.NET AJAX client class, including your own custom classes. c10.indd 352c10.indd 352 8/20/07 6:08:13 PM8/20/07 6:08:13 PM Chapter 10: Type Description Extensions 353 Listing 10-4: A Page that Displays the _properties of the TypeDescriptor Object Associated with an ASP . NET AJAX Client Class <%@ Page Language=”C#” %> <!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 id=”Head1” runat=”server”> <title>Untitled Page</title> <style type=”text/css”> .properties { background-color: LightGoldenrodYellow; color: black; border-collapse: collapse; } .properties td, .properties th { border: 1px solid Tan; padding: 5px; } .header { background-color: Tan; } .odd { background-color: PaleGoldenrod; } </style> <script type=”text/javascript” language=”javascript”> function displayProperties(instance) { var td = Sys.Preview.TypeDescriptor.getTypeDescriptor(instance); var properties = td._getProperties(); var columns = [“Property Name”, “Property Type”, “ReadOnly”, “Property Attributes (Name/Value)”]; var table = document.createElement(“table”); Sys.UI.DomElement.addCssClass(table, “properties”); var headerRow = table.insertRow(0); Sys.UI.DomElement.addCssClass(headerRow, “header”); var headerCell = null; for (var i=0, length = columns.length; i<length; i++) { headerCell = document.createElement(“th”); headerCell.appendChild(document.createTextNode(columns[i])); headerRow.appendChild(headerCell); } for (var property in properties) { insertRow(table, properties[property]); } (continued) c10.indd 353c10.indd 353 8/20/07 6:08:14 PM8/20/07 6:08:14 PM Chapter 10: Type Description Extensions 354 Listing 10-4 (continued) var container = $get(“myDiv”); container.innerHTML=””; container.appendChild(table); } function insertRow(table, property) { var rowIndex = table.rows.length; var row = table.insertRow(rowIndex); if (rowIndex % 2 == 1) Sys.UI.DomElement.addCssClass(row, “odd”); insertCell(row, property[“name”]); insertCell(row, property[“type”]); insertCell(row, property[“readOnly”]); var attributesText=”No attributes are defined!”; if (property[“attributes”]) { var attributes = property[“attributes”]; var attrBuffer = []; for(var attribute in attributes) { attrBuffer.push(String.format(“{0}={1}”, attribute, attributes[attribute])); } attributesText = attrBuffer.join(); } insertCell(row, attributesText); } function insertCell(row, value) { var cell = row.insertCell(row.cells.length); cell.appendChild(document.createTextNode(value)); } function pageLoad() { var instance = new Sys.UI.Control($get(“forControl”)); displayProperties(instance); } </script> </head> <body> <form id=”form1” runat=”server”> <asp:ScriptManager runat=”server” ID=”ScriptManager1”> <Scripts> <asp:ScriptReference Assembly=”Microsoft.Web.Preview” Name=”PreviewScript.js” /> </Scripts> (continued) c10.indd 354c10.indd 354 8/20/07 6:08:14 PM8/20/07 6:08:14 PM Chapter 10: Type Description Extensions 355 Listing 10-4 (continued) </asp:ScriptManager> <div id=”myDiv”></div> <div id=”forControl”></div> </form> </body> </html> For example, if you run this page to view the _properties property of the TypeDescriptor object that describes the Control base class, you’ll get the result shown in Figure 10-1 . Figure 10-1 Now take a look at the implementation of the pageLoad and displayProperties JavaScript functions shown in Listing 10-4 . The pageLoad method instantiates an instance of the Control base class and invokes the displayProperties JavaScript function, passing in the instance as its argument: function pageLoad() { var instance = new Sys.UI.Control($get(“forControl”)); displayProperties(instance); } The displayProperties method has no knowledge of what the real type of the instance is. All it knows is that the parameter passed into it is an instance of an ASP.NET AJAX client class. The displayProperties function displays information about the properties of the instance passed into it as its arguments. Thanks to the TypeDescriptor class, the logic that the displayProperties uses to c10.indd 355c10.indd 355 8/20/07 6:08:14 PM8/20/07 6:08:14 PM Chapter 10: Type Description Extensions 356 inspect the properties of an ASP.NET AJAX client class instance is type-agnostic, meaning it can be used to inspect the properties of any ASP.NET AJAX client type. This logic is highlighted in the following code: function displayProperties(instance) { var td = Sys.Preview.TypeDescriptor.getTypeDescriptor(instance); var properties = td._getProperties(); for (var property in properties) { insertRow(table, properties[property]); } var container = $get(“myDiv”); container.innerHTML=””; container.appendChild(table); } function insertRow(table, property) { var rowIndex = table.rows.length; var row = table.insertRow(rowIndex); if (rowIndex % 2 == 1) Sys.UI.DomElement.addCssClass(row, “odd”); insertCell(row, property[“name”]); insertCell(row, property[“type”]); insertCell(row, property[“readOnly”]); var attributesText = ”No attributes are defined!”; if (property[“attributes”]) { var attributes = property[“attributes”]; var attrBuffer = []; for(var attribute in attributes) { attrBuffer.push(String.format(“{0}={1}”, attribute, attributes[attribute])); } attributesText = attrBuffer.join(); } insertCell(row, attributesText); } c10.indd 356c10.indd 356 8/20/07 6:08:15 PM8/20/07 6:08:15 PM Chapter 10: Type Description Extensions 357 Here’s how this logic works. The displayProperties function first needs to access the TypeDescriptor object that describes the type of the specified ASP.NET AJAX class instance in a generic fashion. You cannot use the new operator to create an instance of the TypeDescriptor class directly. Instead, you must call the getTypeDescriptor static method on the TypeDescriptor method. This static method is discussed in detail later in the chapter, but for now it suffices to say that this method takes an instance of an ASP.NET AJAX type as its argument, and instantiates and returns a TypeDescriptor object that describes the type: var td = Sys.Preview.TypeDescriptor.getTypeDescriptor(instance); The displayProperties function then calls the _getProperties method on the TypeDescriptor object to return a reference to its _properties property. As discussed previously, this property references a single object literal that contains one name/value pair for each property of the type that the TypeDescriptor object describes: var properties = td._getProperties(); The displayProperties function then iterates through the name/value pairs of this object literal: for (var property in properties) The function invokes the following method for each enumerated name/value pair: insertRow(table, properties[property]); The insertRow method inserts a new table row that displays information about the enumerated property or name/value pair. As discussed earlier, the name part of the enumerated name/value pair is a string that contains the name of the associated property. The displayProperties function uses this string as an index into the _properties property of the TypeDescriptor object to access the value part of the enumerated name/value pair. It then passes this value as the second argument into the insertRow method. As discussed earlier, the value part of an enumerated name/value pair references the object literal that describes the property associated with that name/value pair. This object literal contains five name/value pairs. The first name/value pair specifies the name of the property that the object literal describes. The name part of this name/value pair contains name , and the value part is a string that contains the name of the property. The insertRow method uses name as an index into this object literal to access the name of the property, which is then passed into the insertCell method to display it within the opening and closing tags of a <td> HTML element: insertCell(row, property[“name”]); The second name/value pair of this object literal specifies the type of the property that the object literal describes. As discussed earlier, the name part of this name/value pair contains type , and the value part references the constructor of the type of the property. The insertRow method uses type as an index into this object literal to access the reference to this constructor, which is then passed into the insertCell method to display it within the opening and closing tags of a <td> HTML element: insertCell(row, property[“type”]); The property[“type“] returns a reference to the actual constructor of the property type, which means that you can directly call the new operator on this reference to create a new instance of the property type. c10.indd 357c10.indd 357 8/20/07 6:08:15 PM8/20/07 6:08:15 PM Chapter 10: Type Description Extensions 358 As discussed earlier, the third name/value pair of this object literal specifies whether the property that the object literal describes is read-only. The name part of this name/value pair is a string that contains readOnly , and the value part is a Boolean value. The insertRow method uses the string readOnly as an index into the object literal to access this Boolean value, which is then passed into the insertCell method to display it within the opening and closing tags of a td HTML element: insertCell(row, property[“readOnly”]); The fourth name/value pair of this object literal describes the attributes that annotate the type of the property that the object literal describes. As discussed previously, the name part of this name/value pair contains attributes , and the value part references an object that contains the attributes. The insertRow uses attributes as an index into the object literal to access this value, iterates through the attributes that this value contains, and displays the value of each attribute within the opening and closing tags of a <td> HTML element: var attributesText = ”No attributes are defined!”; if (property[“attributes”]) { var attributes = property[“attributes”]; var attrBuffer = []; for(var attribute in attributes) { attrBuffer.push(String.format(“{0}={1}”, attribute, attributes[attribute])); } attributesText = attrBuffer.join(); } insertCell(row, attributesText); _methods This property references an object literal that contains one name/value pair for each method of the type (or base type) that the TypeDescriptor object describes. The name part of each name/value is a string that contains the name of the associated method. The value part of each name/value pair is an object literal that describes the associated method. This object literal contains two name/value pairs, and each pair provides a piece of metadata information about the method that the object literal describes, as follows: ❑ The first name/value pair specifies the name of the method. The name part of this name/value pair is name , and the value part is a string that contains the name of the method. ❑ The second name/value pair describes the parameters of the method. The name part of this name/value pair is parameters , and the value part is an array of object literals. Each object literal in the array describes a parameter of the method and contains two name/value pairs, as follows: ❑ The first name/value pair specifies the name of the parameter. The name part of this name/value pair is name , and the value part is a string that contains the name of the parameter. ❑ The second name/value pair describes the type of the parameter. The name part of this name/value pair is type , and the value part references the constructor of the type of the property. c10.indd 358c10.indd 358 8/20/07 6:08:15 PM8/20/07 6:08:15 PM [...]... Listing 1 0-8 shows the object literal that the _events property of the TypeDescriptor object references 364 c10.indd 364 8/20/07 6:08:18 PM Chapter 10: Type Description Extensions Listing 1 0-8 : The Object Literal Referenced by the _events Property of the TypeDescriptor Object that Describes Button Base Class References { ‘click’: {name: ‘click’}, ‘propertyChanged’: {name: ‘propertyChanged’} } Listing 1 0-9 ... type: String]} Listing 1 0-6 shows a page that enables you to display _methods property of the TypeDescriptor object associated with any ASP.NET AJAX client class, including your own custom classes Figure 1 0-2 shows what you’ll see in your browser when you access this page Listing 1 0-6 : A Page that Displays the _methods Property of the TypeDescriptor Object Associated with an ASP.NET AJAX Client Class 361 c10.indd 361 8/20/07 6:08:16 PM Chapter 10: Type Description Extensions Figure 1 0-2 As you can see in Listing 1 0-6 , the pageLoad method instantiates an instance of the... members, and why it is important to implement the descriptor property of your ASP.NET AJAX client classes Listing 1 0-1 1 contains the internal code for the generateDescriptor static method of the TypeDescriptor class This method takes a reference to a type and returns a TypeDescriptor object that describes the type Listing 1 0-1 1 : The generateDescriptor Static Method of the TypeDescriptor Class Sys.Preview.TypeDescriptor.generateDescriptor . the ASP. NET AJAX client-side framework. This chapter discusses the ASP. NET AJAX type description capabilities, which emulate the .NET type description capabilities. As you’ll see later, the ASP. NET. 6:08:12 PM Chapter 10: Type Description Extensions 350 TypeDescriptor The ASP. NET AJAX client-side framework includes a client class named TypeDescriptor that emulates the ASP. NET server-side. uses to c10.indd 355c10.indd 355 8/20/07 6:08:14 PM8/20/07 6:08:14 PM Chapter 10: Type Description Extensions 356 inspect the properties of an ASP. NET AJAX client class instance is type-agnostic,

Ngày đăng: 09/08/2014, 06:23

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan