ClassDelegate

Talking with my colleague Bruce Flowers we ran in to a situation of being able to execute an AS class from a JS call to the SWF component, sounds strange?

ok.. so.. we need to attach to a function the responsibility to create and execute a certain method form a custom class we pass to it.. why? maybe because of the fun of it, or maybe we have this case:

We are going to use ExternalInterface to communicate with the browser, and we want a class that will have all the callBack methods which we want exposed to the JS side. So far so good, now we want this class ONLY to register the methods but assign the callBack method to a class some where else in our code, let’s say using a Command Class.

Ok.. a simple approach would be:

package {
import flash.external.ExternalInterface;
import net.acatl.store.UpdateProductList;
class ExternalInterfaceLocator {
public function ExternalInterfaceLocator ():void
{
ExternalInterface.addCallback( "updateProductList" , updateProductList);
}
private function updateProductList(...rest:Array):void
{
// delegate job to an external command class
var command:UpdateProductList = new UpdateProductList();
command.execute.apply(command, rest);
}
}
}

And then the class com.dynamicflash.utils.Delegate used so much in AS2 came to my mind.
So I built this small class which will let you assign a class to a function, in a way that until the function gets called the class instance will be created and a method of the class will receive the parameters which where passed from the owner function.

To download the code: ClassDelegate


public class ClassDelegate
{
// Class object to be instantiated
public var classObject:Class;
//method to be called
public var method:String;
// constructor
public function ClassDelegate( classObject:Class, method:String="execute")
{
this.classObject = classObject;
this.method = method;
}
// create the delegate function
public function execute(...rest:Array):void
{
// we create the new instance
var instance:Object = new classObject();
// we pass the parameters to the assigned method
instance[this.method].apply(instance, rest);
}
public static function create (classObject:Class, method:String="execute"):Function
{
// we create the new instance and pass the Class object and the default method to be executed
var delegate:ClassDelegate= new ClassDelegate(classObject, method);
// notice: we pass the function as an 'Function' Object
return delegate.execute;
}
}

so now we want to implement this class on our previous example:

package {
import flash.external.ExternalInterface;
import net.acatl.utils.ClassDelegate;
class ExternalInterfaceLocator {
public function ExternalInterfaceLocator ():void
{
ExternalInterface.addCallback( "updateProductList" ,
ClassDelegate.create( net.acatl.store.UpdateProductList, "execute" ) );
}
}
}

And the class net.acatl.store.UpdateProductList would look something like this:

class UpdateProductList
{
public function UpdateProductList():void
{
}
// method executed by our ClassDelegate
public function execute():void
{
trace ("parameters passed:" + arguments[0] + "," + arguments[0] + "...");
}
}

So conclusion… we have a ExternalInterfaceLocator Class that will look much more clean and have no Business logic inside, it will only be responsible of adding callBack Methods to the ExternalInterface, this class can be used in many other cases which I will describe on next post. as for now I tested the class adding it to Collections and it worked pretty good. Please send me any feedback or comments on this.

Working Example: ClassDelegate Flex 3 Project example