1. Trang chủ
  2. » Công Nghệ Thông Tin

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

58 344 0

Đ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

Thông tin cơ bản

Tiêu đề Type Description Extensions
Trường học University of Example
Chuyên ngành Computer Science
Thể loại Thesis
Năm xuất bản 2007
Thành phố Sample City
Định dạng
Số trang 58
Dung lượng 580,37 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

_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 describ

Trang 1

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

Trang 2

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()

Trang 3

_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

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}

Trang 4

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

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

Trang 5

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)

Trang 6

var rowIndex = table.rows.length;

var row = table.insertRow(rowIndex);

<form id=”form1” runat=”server”>

<asp:ScriptManager runat=”server” ID=”ScriptManager1”>

Trang 7

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

Trang 8

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:

var rowIndex = table.rows.length;

var row = table.insertRow(rowIndex);

Trang 9

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:

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

Trang 10

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!”;

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

Trang 11

For example, the Control base class exposes the methods shown in the following table

Method Name Parameter Name Parameter Type

removeCssClass className StringtoggleCssClass className String

Based on this table, the _methods property of the TypeDescriptor object that describes the Control base class references the object literal shown in Listing 10-5

Listing 10-5: The Object Literal Referenced by the _methods Property of the TypeDescriptor Object that Describes Control Base Class References

‘addCssClass’: {name: ‘addCssClass’, parameters: [{name: ‘className’, type: String]}, ‘removeCssClass’: {name: ‘removeCssClass’,

parameters: [{name: ‘className’, type: String]}, ‘toggleCssClass’: {name: ‘toggleCssClass’,

parameters: [{name: ‘className’, type: String]}

}

This object literal contains three name/value pairs The name part of each name/value pair contains the name of a method: ‘ addCssClass’ , ‘removeCssClass’ , and ‘toggleCssClass’ The value part of each name/value pair contains the object literal that describes the corresponding method of the Control base class, as follows:

❑ {name: ‘addCssClass’, parameters: [{name: ‘className’, type: String]}

❑ {name: ‘removeCssClass’, parameters: [{name: ‘className’, type: String]}

❑ {name: ‘toggleCssClass’, parameters: [{name: ‘className’, type: String]}

Listing 10-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 10-2 shows what you’ll see in your browser when you access this page

Listing 10-6: A Page that Displays the _methods Property of the TypeDescriptor Object Associated with an ASP NET AJAX Client Class

Trang 12

header { background-color: Tan; }

odd { background-color: PaleGoldenrod; }

var methods = td._getMethods();

var columns = [“Method Name”, “Parameter (Name/Type)”];

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++)

Trang 13

Listing 10-6 (continued)

function insertRow(table, method) {

var rowIndex = table.rows.length;

var row = table.insertRow(rowIndex);

if (rowIndex % 2 == 1) Sys.UI.DomElement.addCssClass(row, “odd”);

insertCell(row, method[“name”]);

var parametersText = ”No parameters are defined!”;

if (method[“parameters”]) {

var parameters = method[“parameters”];

var paramBuffer = [];

for(var parameter in parameters) {

paramBuffer.push(String.format(“({0} / {1})”, parameters[parameter].name, parameters[parameter].type.getName()));

} parametersText = paramBuffer.join();

} insertCell(row, parametersText);

} 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”));

displayMethods(instance);

} </script>

</head>

<body>

<form id=”form1” runat=”server”>

<asp:ScriptManager runat=”server” ID=”ScriptManager1”>

Trang 14

As you can see in Listing 10-6 , the pageLoad method instantiates an instance of the Control base class

and invokes the displayMethods JavaScript function, passing in the instance as its argument:

The displayMethods function 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 displayMethods function displays information about the methods of the instance passed into it as

its arguments Thanks to the TypeDescriptor class, the logic that displayMethods uses to inspect the

methods of an ASP.NET AJAX client class instance is type-agnostic, which means it can be used to

inspect the methods of any ASP.NET AJAX client type This logic is highlighted in the following code:

Trang 15

(continued)

function insertRow(table, method) {

var rowIndex = table.rows.length;

var row = table.insertRow(rowIndex);

if (rowIndex % 2 == 1) Sys.UI.DomElement.addCssClass(row, “odd”);

insertCell(row, method[“name”]);

var parametersText = ”No parameters are defined!”;

if (method[“parameters”]) {

var parameters = method[“parameters”];

var paramBuffer = [];

for(var parameter in parameters) {

paramBuffer.push(String.format(“({0} / {1})”, parameters[parameter].name, parameters[parameter].type.getName()));

} parametersText = paramBuffer.join();

} insertCell(row, parametersText);

var methods = td._ getMethods();

The displayMethods function then iterates through the name/value pairs of this object literal:

for (var m in methods)

As discussed earlier, the name part of the enumerated name/value pair is a string that contains the name

of the associated method The displayMethods function uses this string as an index into the _methods property of the TypeDescriptor object to access the value part of the enumerated name/value pair The value part references the object literal that describes the method associated with the name/value pair

The displayMethods then passes this object literal into the insertRow method:

insertRow(table, methods[m]);

Trang 16

This object literal contains two name/value pairs The first name/value pair specifies the name of the

method 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 method insertRow uses name as an index into

this object literal to access the name of the method, which is then passed into the insertCell method to

display it within the opening and closing tags of a <td> HTML element:

insertCell(row, method[“name”]);

The second name/value pair of this object literal describes the parameters of the method that the object

literal describes The name part of this name/value pair contains parameters , and the value part

references an array that contains one object for each parameter of the associated method Each of these

objects in turn contains two name/value pairs that describe the name and type of the parameter

insertRow iterates through these objects and displays the name and type of each parameter:

for(var parameter in parameters)

This property references an object literal that contains one name/value pair for each event 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 event associated with the pair The value part of each name/value pair is

an object literal that describes the event associated with the pair This object literal contains a single

name/value pair that specifies the name of the event The name part of this name/value pair is name ,

and the value part is a string that contains the name of the event

For example, the Control base class exposes a single event named propertyChanged Therefore, the

_events property of the TypeDescriptor object that describes the Control base class references

the object literal shown in Listing 10-7

Listing 10-7: The Object Literal Referenced by the _events Property of the

TypeDescriptor Object that Describes Control Base Class References

‘propertyChanged’: {name: ‘propertyChanged’}

}

This object literal contains a single name/value pair The name part of this name/value pair is a string

that contains the name of the event: ‘propertyChanged’ The value part of this name/value pair

con-tains the object literal that describes the event of the Control base class: {name: ‘propertyChanged’}

Now, let’s take a look at the _events property of the TypeDescriptor object that describes the Button

client control Because the Button control derives from the Control class, it inherits the propertyChanged

event from its base class The Button control also exposes an event of its own named click Listing 10-8

shows the object literal that the _events property of the TypeDescriptor object references

Trang 17

Listing 10-9: A Page that Displays the _events Property of the Type D escriptor Object Associated with an ASP NET AJAX Client Class

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 displayEvents(instance) {

var td = Sys.Preview.TypeDescriptor.getTypeDescriptor(instance);

var events = td._getEvents();

var columns = [“Event Name”];

var table = document.createElement(“table”);

Sys.UI.DomElement.addCssClass(table, “properties”);

var headerRow = table.insertRow(0);

Sys.UI.DomElement.addCssClass(headerRow, “header”);

(continued)

Trang 18

Listing 10-9 (continued)

var headerCell = null;

for (var i=0, length = columns.length; i<length; i++)

var rowIndex = table.rows.length;

var row = table.insertRow(rowIndex);

<form id=”form1” runat=”server”>

<asp:ScriptManager runat=”server” ID=”ScriptManager1”>

Trang 19

function pageLoad(){

var instance = new Sys.UI.Control($get(“forControl”));

Trang 20

var rowIndex = table.rows.length;

var row = table.insertRow(rowIndex);

if (rowIndex % 2 == 1)

Sys.UI.DomElement.addCssClass(row, “odd”);

insertCell(row, event[“name”]);

}

Here’s how this logic works The displayEvents function first calls the getTypeDescriptor static

method on the TypeDescriptor class, passing in the instance to access the TypeDescriptor object that

describes the type of the instance in a generic fashion:

var td = Sys.Preview.TypeDescriptor.getTypeDescriptor(instance);

The displayEvents function then calls the _getEvents method on the TypeDescriptor object to

return a reference to its _events property This property references a single object literal that contains

one name/value pair for each event of the type that the TypeDescriptor object describes:

var properties = td._getEvents();

The displayEvents function then iterates through the name/value pairs of this object literal:

for (var e in events)

The name part of the enumerated name/value pair is a string that contains the name of the associated

event The displayEvents function uses this string as an index into the _events property of the

TypeDescriptor object to access the value part of the enumerated name/value pair The value part

references the object literal that describes the event associated with the name/value pair The

displayEvents function then passes this object literal into the insertRow method:

insertRow(table, events[e]);

Trang 21

This object literal contains a single name/value pair The name part of the pair is name , and the value part is a string that contains the name of the event The insertRow function invokes the insertCell method to display this value:

insertCell(row, event[“name”]);

get TypeDescriptor

The previous sections provided several examples of how you can use the getTypeDescriptor method

in your own applications This section walks you through the internal implementation of this method to introduce its extensibility points, setting the stage for later discussions of why, when, and how to extend the getTypeDescriptor method

The getTypeDescriptor method takes an instance of a type as its argument and returns a

TypeDescriptor object that describes the type, as shown in Listing 10-10 Listing 10-10 : The get T ype D escriptor Static Method of the Type D escriptor Class

Sys.Preview.TypeDescriptor.getTypeDescriptor =function Sys$Preview$TypeDescriptor$getTypeDescriptor(instance){

var type = Object.getType(instance);

var td = type._descriptor;

if (!td && !type._descriptorChecked) {

}

The getTypeDescriptor method first calls the getType static method on the Object class, passing in the type instance to return a reference to the type itself:

var type = Object.getType(instance);

Next, it checks whether the type instance implements an interface named ITypeDescriptorProvider

If so, it delegates the responsibility of creating and initializing the TypeDescriptor object that sents the type to the getDescriptor method of the type itself If not, it calls the generateDescriptor static method on the TypeDescriptor class to create and initialize a TypeDescriptor object that describes the type In either case, the TypeDescriptor object is cached in an internal field named

repre-_descriptor for future access Subsequent calls to the getTypeDescriptor method will be serviced from the cache to improve performance

You can extend the functionality of the TypeDescriptor class by having your type implement the

ITypeDescriptorProvider interface This interface exposes a single method named getDescriptor

Trang 22

Your type’s implementation of this method must use whatever logic is necessary to create and initialize

an ICustomTypeDescriptor object and return the object to its caller

generate Descriptor

This section presents the internal implementation of the TypeDescriptor class’s generateDescriptor

static method to help you understand the significant role that the descriptor property of a type plays

in enabling others to inspect its members, and why it is important to implement the descriptor

property of your ASP.NET AJAX client classes

Listing 10-11 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 10-11 : The generate Descriptor Static Method of the TypeDescriptor Class

Then, starting with the type itself, the generateDescriptor method marches upward through the

ancestor types, calling the append static method on the TypeDescriptor class to append each type’s

descriptor property to the newly instantiated TypeDescriptor object

The default implementation of the getTypeDescriptor method (the method that calls the

generateDescriptor method) assumes that your ASP.NET AJAX type and its ancestor ASP.NET AJAX

types expose metadata information about their properties, methods, events, and attributes through a

static property named descriptor If your ASP.NET AJAX client type does not implement the

descriptor property, the clients of your type will not be able to use the TypeDescriptor class to

inspect its members If one of the ancestor ASP.NET AJAX client types of your ASP.NET AJAX client type

does not implement the descriptor property, the clients of your type will not be able to inspect the

members that your type inherits from that ancestor type

Trang 23

❑ How to implement the descriptor property of your own ASP.NET AJAX client types

❑ The four different kinds of metadata information that the descriptor static property of your ASP.NET AJAX class can expose to its clients

A descriptor static property of a type references an object literal that contains up to five name/value pairs, as follows:

❑ The first name/value pair describes the properties of the type The name part of this name/

value pair contains properties , and the value part references an array of object literals Each object literal in this array describes a property of the type and contains up to four name/value pairs, 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 specifies the type of the property The name part of this name/value pair is type , and the value part references the actual type of the property

❑ The third name/value pair specifies whether the property is read-only The name part of this name/value pair is the ‘readOnly’ string, and value part is a Boolean

❑ The fourth name/value pair specifies the attributes of the property

❑ 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

❑ The second name/value pair describes the methods of the type The name part of the pair is

methods , and the value part is an array of object literals Each object literal in this array describes a method of the type and contains two name/value pairs, as follows:

❑ The first name/value pair specifies the name of the method The name part of the 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 the pair is parameters , and the value part is an array of object literals Each object literal in this array describes a parameter of the method and contains two name/value pairs The first name/value pair specifies the name of the parameter where the name part of the pair

is name , and the value part is a string that contains the name of the parameter The second name/value pair specifies the type of the parameter where the name part of the pair is

type , and the value part references the actual type of the parameter

❑ The third name/value pair describes the events of the type The name part of the pair is events , and the value part is an array of object literals Each object literal in this array describes an event

Trang 24

of the type and contains a single name/value pair where the name part of the pair is name , and

the value part is a string that contains the name of the event

❑ The fourth name/value pair describes the attributes of the type The name part of the pair is

attributes , and the value part is an array of object literals Each object literal in this array

describes an attribute and contains two name/value pairs, as follows:

❑ The first name/value pair specifies the name of the attribute The name part of the pair is

name , and the value part is a string that contains the name of the attribute

❑ The second name/value pair specifies the value of the attribute The name part of the pair

is value , and the value part is the actual value of the attribute

Listing 10-12 shows the append static method of the TypeDescriptor class

Listing 10-12: The append Static Method of the TypeDescriptor Class

var length = descriptor.properties.length;

for (var i = 0; i < length; i++)

{

var property = descriptor.properties[i];

var propertyName = property.name;

var associatedAttributes = property.attributes;

var readOnly = property.readOnly? property.readOnly : false;

var isDomElement = !!(property.isDomElement);

var isInteger = !!(property.isInteger);

Trang 25

Listing 10-12 (continued)

if (descriptor.events) {

var length = descriptor.events.length;

for (var i = 0; i < length; i++) {

var eventName = descriptor.events[i].name

if (! td._getEvents()[eventName]) td.addEvent(eventName);

} }

if (descriptor.methods) {

var length = descriptor.methods.length;

for (var i = 0; i < length; i++) {

var methodName = descriptor.methods[i].name;

if (! td._getMethods()[methodName]) {

var params = descriptor.methods[i].params;

if(!params) params = descriptor.methods[i].parameters;

if (params) td.addMethod(methodName, params);

else td.addMethod(methodName);

} } }

if (descriptor.attributes) {

var length = descriptor.attributes.length;

for (var i = 0; i < length; i++) {

var attributeName = descriptor.attributes[i].name

if (! td._getAttributes()[attributeName]) td.addAttribute(attributeName, descriptor.attributes[i].value);

} }}

The append static method takes two arguments The first argument references the TypeDescriptor object that describes a type, and the second argument references the descriptor property of another type The main goal of the append method is to copy the contents of the descriptor property of the latter type into the TypeDescriptor object that describes the former type

The descriptor property contains up to four name/value pairs The name parts of these four pairs are

properties , events , methods , and attributes The value parts of these four pairs are arrays of object literals, where each object literal describes a property, event, method, or attribute of the type That is why the append static method consists of four major sections — each section copies the contents of the associated array into the specified TypeDescriptor object

Trang 26

After the completion of the call into the append method, the TypeDescriptor object contains the

contents of the descriptor property of the other type in addition to its original content As previously

discussed, the generateDescriptor method calls the append method to append the contents of the

descriptor properties of all the ancestor types of a given type into the TypeDescriptor object that

repre-sents the type Therefore, the _getProperties , _getMethods , _getEvents , and _getAttributes

methods of the TypeDescriptor object return all the properties, methods, events, and attributes of the

ancestor types of the type, in addition to the properties, methods, events, and attributes of the type itself

get Property

The TypeDescriptor class includes a static method named getProperty that takes up to three

parameters The first parameter references an instance of a type whose property value is being queried

The second parameter is a string that contains the name of a property whose value is being queried The

last parameter is optional The main responsibility of the getProperty method is to return the value of

the specified property of the specified instance of the type

This section walks you through the internal implementation of the getProperty method to help you

understand the following:

❑ The extensibility points of this method, which sets the stage for later discussions of why, when,

and how to extend the getProperty method of the TypeDescriptor class

❑ The role that the last argument of the getProperty method plays, and why and when you

should specify this argument

Listing 10-13 shows the getProperty static method

Listing 10-13: The get Property Static Method of the TypeDescriptor Class

var propertyInfo = td._getProperties()[propertyName];

var getter = instance[‘get_’ + propertyInfo.name];

var object = getter.call(instance);

The getProperty method first checks whether the instance implements the ICustomTypeDescriptor

interface If so, the method delegates the responsibility of retrieving the property value to the

getProperty method of the instance itself Note that the method simply returns the value returned

from the getProperty method of the instance:

Trang 27

if (Sys.Preview.ICustomTypeDescriptor.isImplementedBy(instance)) return instance.getProperty(propertyName, key);

Therefore, you can customize the functionality of the getProperty method by having your type implement the ICustomTypeDescriptor interface As you’ll see later, your type’s implementation of the getProperty method of this interface must use whatever logic necessary to retrieve the value of the property with the specified name

If the instance does not implement the ICustomTypeDescriptor interface, the getProperty method takes the following actions:

❑ It calls the getTypeDescriptor static method on the TypeDescriptor class, passing in the instance

to return a reference to the TypeDescriptor object that describes the type of the instance in a generic fashion:

var td = Sys.Preview.TypeDescriptor.getTypeDescriptor(instance);

This is the first step you must take every time you need to use the ASP.NET AJAX type inspection capabilities (This was also the first step taken in Listings 10-4 , 10-6 , and 10-9 )

❑ It calls the _getProperties method on the TypeDescriptor object to return a reference to the

_properties array property of the object It uses the property name as an index into this array

to return the object literal that describes the property with the specified name:

var propertyInfo = td._getProperties()[propertyName];

As discussed earlier, this object literal contains up to four name/value pairs where each pair provides a piece of metadata information about the property The first name/value pair specifies the name of the property where the name part of the pair is name , and the value part is a string that contains the name of the property The getProperty method uses name to access the value part (the string containing the name of the property) and appends this string to the string

“get_” to arrive at the name of the getter method that gets the value of the property

❑ It uses the name of the getter method as an index into the instance to return a reference to the getter method itself:

var getter = instance[‘get_’ + propertyInfo.name];

❑ It invokes the call method on the getter method, passing in the instance to return the value of the property:

var object = getter.call(instance);

The third optional parameter of the getProperty method is named key The meaning of key depends

on the implementation of the getProperty method The default implementation (which is what’s shown in Listing 10-13 ) interprets the key as the name of a descendant subproperty of the specified property The descendant subproperties of a property include the subproperties of the property, the subproperties of the subproperties of the property, the subproperties of the subproperties of the subproperties of the property, and so on Therefore, if you call the getProperty method with the third argument, the method assumes that you’re asking for the value of a descendant subproperty whose name is given by the key parameter

Trang 28

If the key does not contain the character dot ( ), the getProperty method assumes that you’re asking

for the value of the immediate subproperty, as shown in boldfaced portion of the following code

fragment:

object = key.indexOf(‘.’) === -1 ? (object[key]) :

(Sys.Preview.TypeDescriptor._evaluatePath(object, key));

Otherwise, the method calls the _evaluatePath method, where it iterates through the descendant

subproperties of the specified property to find the subproperty whose name is given by the key , as

var parts = path.split(‘.’);

var current = instance;

for(var i = 0; i < parts.length; i++)

The great thing about the getProperty method is that it enables you to access the value of the property

of an ASP.NET AJAX type instance without having to know the real type of the instance This enables

you to access the values of the properties of ASP.NET AJAX objects in type-agnostic fashion, which

means that you can write one set of JavaScript code to query the property values of any ASP.NET AJAX

object of any type

get Attribute

The TypeDescriptor class features a static method named getAttribute that takes two parameters The

first parameter references an instance of an ASP.NET AJAX type The second parameter is a string that

con-tains the name of an attribute of the type The main goal of the getAttribute method is to retrieve and

return the value of the specified attribute of a specified instance Listing 10-15 shows this method

Listing 10-15: The get Attribute Static Method of the TypeDescriptor Class

Trang 29

The getAttribute method first invokes the getTypeDescriptor static method on the TypeDescriptor class, passing in the instance to return a reference to the TypeDescriptor object that describes the type of the instance in a generic fashion:

var td = Sys.Preview.TypeDescriptor.getTypeDescriptor(instance);

Next, it invokes the _getAttributes method on the TypeDescriptor object to return a reference to the object’s _attributes collection, and uses the attribute name as an index into this collection to return the attribute’s value:

return td._getAttributes()[attributeName];

set Proper ty

The setProperty method of the TypeDescriptor class takes up to four parameters The first parameter references an instance of an ASP.NET AJAX type The second parameter is a string that contains the name of a property of the type The third parameter contains the value of the property The fourth parameter is optional The main goal of the setProperty method is to set the specified property

of the specified instance to a specified value

This section walks you through the internal implementation of the setProperty method to help you understand the following:

❑ The extensibility points of this method

❑ The role the last argument of the setProperty method plays, and why and when you should specify this argument

Listing 10-16 shows this method

Listing 10-16: The set Property Static Method of the TypeDescriptor Class

Sys.Preview.TypeDescriptor.setProperty =function Sys$Preview$TypeDescriptor$setProperty(instance, propertyName, value, key){

if (Sys.Preview.ICustomTypeDescriptor.isImplementedBy(instance)) {

instance.setProperty(propertyName, value, key);

return;

} var td = Sys.Preview.TypeDescriptor.getTypeDescriptor(instance);

var propertyInfo = td._getProperties()[propertyName]; if (key) {

var getter = instance[‘get_’ + propertyInfo.name];

var object = getter.call(instance);

if(key.indexOf(‘.’) === -1) object[key] = value;

(continued)

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