Welcome to AspAdvice Sign in | Join | Help

Alessandro Gallo

.NET & Beyond
Strongly typed collections with JavaScript and Microsoft Ajax?

Not exactly, but we can achieve a similar result by using the parameter validation mechanism provided by Microsoft Ajax.

Introduction

The core library defines Function._validateParams(parameters, descriptors), that is a function responsible for validating a list of parameters passed as an argument. The second argument is an array of parameter descriptors:

 [ param1_descriptor, param2_descriptor, ... ]

Each descriptor is a dictionary (in JavaScript, a dictionary is a set of name:value pairs separated by a comma and enclosed in {}) used to provide information about the expected parameter. If one of the parameters doesn't match the corresponding descriptor, the function raises an exception of type Sys.ArgumentTypeException.

Scenario

Let's see how we can take advantage of this mechanism to create an array that accepts only instances of a particular class. We want to build a CustomerCollection class that holds a list of Customer objects and allows to add and remove them, in a manner similar to a strongly typed collection in the .NET framework.

The Customer class

Our Customer class is pretty simple. It contains only a fullName field and a property to access it:

 

Type.registerNamespace('Samples');
Samples.Customer = function() {
    this._fullName;
}
Samples.Customer.prototype = {
    set_fullName : function(value) {
        this._fullName = value;
    },
    
    get_fullName : function() {
        return this._fullName;
    }
}
Samples.Customer.registerClass('Samples.Customer');

 

Implementing the CustomerCollection class

The CustomerCollection class holds a _innerList field that is the private list of Customers. The access to the inner list happens through the addCustomer() and removeCustomer() methods. Both these methods accept an instance of the Customer class as an argument.

Since JavaScript doesn't perform any check on the type or number of the parameters passed to a method, we are invoking a method called _validateCustomer() inside the body of both addCustomer and removeCustomer.

 

Samples.CustomerCollection = function() {
    this._innerList = [];
}
Samples.CustomerCollection.prototype = {
    addCustomer : function(customer) {
        this._validateCustomer(arguments);
        
        Array.add(this._innerList, customer);
    },
    
    removeCustomer : function(customer) {
        this._validateCustomer(arguments);
        
        Array.remove(this._innerList, customer);
    },
    
    get_count : function() {
        return this._innerList.length;
    },
    
    _validateCustomer : function(args) {
        var e = Function._validateParams(args,
            [{name: 'customer', type: Samples.Customer, mayBeNull: false, isOptional: false}]);
            
        if(e) throw e;
    }
}
Samples.CustomerCollection.registerClass('Samples.CustomerCollection');

 

Let's take a closer look at _validateCustomer. This function takes the list of parameters to validate and matches them with the corresponding descriptors.

The first thing to notice is that, both in addCustomer and removeCustomer, we are passing arguments to _validateCustomer. The arguments reference is created by JavaScript and holds the list of the parameters passed to a method. In our example, arguments holds the customer parameter.

As a consequence, _validateCustomer receives the customer parameter and calls _validateParams with the array of parameter descriptors:

 

[{name: 'customer', type: Samples.Customer, mayBeNull: false, isOptional: false}]

 

This array contains one descriptor because we are validating one parameter. As you can see, a descriptor is a dictionary that holds the "description" of the parameter: this parameter is associated a "customer" name (just for identification purposes), it must be of type Samples.Customer, it can't be null (mayBeNull) and it can't be omitted (isOptional).

If the given parameter doesn't match the descriptor, the variable e holds an exception that will be thrown in the if statement.

Testing the bits

The following is a simple snippet that tests the CustomerCollection class:

function pageLoad() {
    var c1 = new Samples.Customer();
    c1.set_fullName('John Doe');
    
    var c2 = new Samples.Customer();
    c2.set_fullName('John Smith');
    
    var coll = new Samples.CustomerCollection();
    coll.addCustomer(c1);
    coll.addCustomer("blah"); // This will throw.
    
    coll.removeCustomer(c1);
    alert(coll.get_count());
}
Sponsor
Posted: Wednesday, November 08, 2006 3:55 PM by Garbin

Comments

Scott Cate's WebLog said:

Garbin has a great post that explains the possibility of creating a strongly typed collection in JavaScript.

# November 8, 2006 10:45 AM

Rodrigo said:

Hi nice code. It gave me the idea to try to make a generic collection class in pure javascript(without depending on asp.net ajax).

And the result is

http://www.rodrigodiniz.qsh.eu/Collection.aspx

A very small script and more similar to .net List. Feel free to blog about it...but if you do please put a link to my site.

Thanks

# November 10, 2006 6:41 AM

Christopher Steen said:

EJ: Essential JavaScript The Library [Via: Dion Almaer ] Apache Axis2 1.1 Released [Via: Anil John ]...

# November 14, 2006 11:11 PM

Aldwis said:

UH~ Excuse me please,

but why we need typed collections in JavaScript?

for the possible to compile it?

# November 18, 2006 2:04 PM

Garbin said:

Aldwis: to ensure that items in the collection are of a unique type.

# November 18, 2006 2:49 PM

Aldwis said:

Ah~~ For now~ I don't understand why we need it~

# November 19, 2006 3:53 AM

Hristo Deshev said:

I'm with Aldwis on this one.  That's way too much code for a single type check.  I would not want to have ~20 lines of code for a collection that does not have a way for its clients to enumerate its contents.

I'd take a simple Array any day of the week.

By the way, Garbin, have you tried "inheriting" from the built-in Array type?  You can get a typed collection in much less code:

function CustomerCollection()

{

}

CustomerCollection.prototype = new Array();

CustomerCollection.prototype.addCustomer = function(customer)

{

this.validate(customer)

this.push(customer);

}

CustomerCollection.prototype.validate = function(customer)

{

//check something here...

}

=====================

var collection = new CustomerCollection();

collection.addCustomer(new Customer());

alert(collection[0].length)

# December 4, 2006 4:39 PM

Stefan's Blog said:

Gute Sites & Blogs Alex on Asp.nethttp://blogs.dotnetgerman.com/alexonasp.net/Nikhilik.netExtrem...

# January 12, 2007 2:32 PM

Google排名 said:

Good ! thank the author.

# May 25, 2007 9:20 AM

WamBlog said:

Ajax.NET BLOCKED SCRIPT Validazione dei parametri

# May 27, 2008 7:01 PM

WamBlog said:

Esiste una funzione nascosta nell'ajax.net che si occupa della validazione dei parametri: Function

# November 1, 2008 7:47 AM
New Comments to this post are disabled