Update Panel .NET

Exploring Microsoft ASP.NET AJAX and jQuery

Posts Tagged ‘addMethod

Adding sweetness to the Microsoft AJAX Library

with 2 comments

A few months back, I reviewed some code by a colleague, and I noticed how she used helper functions to generate property accessors in component “classes”.  At first I dismissed her approach as unnecessary, but after writing property accessors for the n’th time, I have finally succombed to her way of thinking.

The simplest implementation of a property accessor looks something like this:

MyNamespace.MyComponent = function() {
    ...
    this._myProperty = 12345;
    ...
}
MyNamespace.MyComponent.prototype = {
    ...
    get_myProperty: function() {
        return this._myProperty;
    },
    set_myProperty: function(value) {
        this._myProperty = value;
    },
    ....
}

Wouldn’t it be nice if you don’t have to repeat that code for every property?  Well, you can create a Visual Studio code snippet to help with the typing, or add some sugar and write this instead:

MyNamespace.MyComponent = function() {
    ...
}
MyNamespace.MyComponent.addProperty("myProperty", 12345);

Here is the sugar:

Function.prototype.addField = function(name, value) {
    /// <param name="name" type="String"></param>
    /// <param name="value" mayBeNull="true"></param>
    /// <returns type="String"></returns>
    var e = Function._validateParams(arguments, [
        { name: "name", type: String },
        { name: "value", mayBeNull: true }
    ]);
    if (e) throw e;
    var fieldName = "_" + name;
    if (!(fieldName in this.prototype)) {
        this.prototype[fieldName] = value;
    }
    return fieldName;
}
Function.prototype.addMethod = function(name, method) {
    /// <param name="name" type="String"></param>
    /// <param name="method" type="Function"></param>
    var e = Function._validateParams(arguments, [
        { name: "name", type: String },
        { name: "method", type: Function }
    ]);
    if (e) throw e;
    if (!(name in this.prototype)) {
        this.prototype[name] = method;
    }
}
Function.prototype.addProperty = function(name, initialValue, raisePropertyChanged) {
    /// <param name="name" type="String"></param>
    /// <param name="initialValue" mayBeNull="true"></param>
    /// <param name="raisePropertyChanged" type="Boolean" optional="true"></param>
    var e = Function._validateParams(arguments, [
        { name: "name", type: String },
        { name: "initialValue", mayBeNull: true },
        { name: "raisePropertyChanged", type: Boolean, optional: true }
    ]);
    if (e) throw e;
    var fieldName = this.addField(name, initialValue);
    this.addMethod("get_" + name, function() {
        return this[fieldName];
    });
    if (raisePropertyChanged) {
        this.addMethod("set_" + name, function(value) {
            if (value !== this[fieldName]) {
                this[fieldName] = value;
                this.raisePropertyChanged(name);
            }
        });
    } else {
        this.addMethod("set_" + name, function(value) {
            this[fieldName] = value;
        });
    }
}

Save this script and include it in your page.  Because this script uses JavaScript extensions provided by the Microsoft AJAX Library, please ensure that is included first!  I suggest you use <asp:ScriptManager>.

For example:

<asp:ScriptManager runat="server">
    <Scripts>
        <asp:ScriptReference Path="Sugar.js" />
    </Scripts>
</asp:ScriptManager>

Type.addField(name, value)

Adds a property value field to your component “class”.

For example:

MyNamespace.MyComponent.addField("count", 1);

This is equivalent to:

MyNamespace.MyComponent = function() {
    ...
    this._count = 1;
    ...
}

Type.addMethod(name, method)

Adds a method to your component “class”.

For example:

MyNamespace.MyComponent.addMethod("sayHello", function (name) {
    alert("Hello " + name);
});

This is equivalent to:

MyNamespace.MyComponent.prototype = {
    sayHello: function(name) {
        alert("Hello " + name);
    }
}

Type._addGetter(name, method)

Adds a property getter method to your component “class”.  This method is for internal use only!

Type._addSetter(name, method)

Adds a property setter method to your component “class”.  This method is for internal use only!

While writing my next post, I decided to factor out the above two “internal” methods, as they don’t add much value.

Type.addProperty(name, initialValue, raisePropertyChanged)

Adds a property to your component “class”.  This includes the value field, the getter method and the setter method.

Parameters:

  • name – The name of the property, specified as a string in camel case.
  • initialValue – The initial value of the property.
  • raisePropertyChanged – A boolean to indicate whether you wish to raise the property changed event.

For example:

MyNamespace.MyComponent.addProperty("count", 1, true);

This is equivalent to:

MyNamespace.MyComponent = function() {
    ...
    this._count = 1;
    ...
}
MyNamespace.MyComponent.prototype = {
    ...
    get_count: function() {
        return this._count;
    },
    set_count: function(value) {
        if (value !== this._count) {
            this._count = value;
            this.raisePropertyChanged("count");
        }
    },
    ...
}

Download Sugar.js from my SkyDrive.

Written by tzkuei

November 26, 2008 at 3:45 pm