I would like to float a "BindingManager" concept past you all? (hope
thats ok), and would love it if anyone had any input for it as i'm
kind of a lone-coder here and in dire need of "idea bounce-offs" :)

Concept:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I basically have a situation where I want to create a BindingManager
where it allows views to bind to results in a transparent manner. An
example is when I have a mx:Tree control, and I want it to be
populated to update when I trigger a mx:RemoteObject call to
serverside.

Now, I have a way of attacking the "trigger" part, where I basically
create a RequestHandler, which inside that has the following:

[RequestHandler Object]
- resultKey
- onResult
- onFault
- screenID

When I invoke a service I basically have an inbetween step, in that i
call a Public Method -
getTreeData(callbackObject:ResultHandler,params:Object).

This getTreeData basically then invokes a relevant Remote Service. (ie
HTTPService, WebService, RemoteObject, LocalConnection etc).

It captures its own onResult/onFault if need be, but basically it may
do some minor adjustments to the data before handing to the
ResultHandler for its own processing (example taking an XML String
from CFC, cleaning up the ignoreWhite concept and then hands it to
ResultHandler.onResult())

Inside the ResultHandler.onResult, it does two things:

1) Dispatches an event stating that this object has new data (for any
that may subscribe)
2) Notifies BindManager.onData(this.resultKey,dataPacket);

The BindingManager basically iterates over its own internal Registry
for any keys that match the "resultKey" and basically sets the
destination points values to the new dataPacket.

To register a Binding in BindingManager, i have something like this:

com.SynergyFLEX.framework.managers.BindingManager extends Object {

        private var _bindings:Object;
        private var _maxIterations:Number;
        public function BindingManager() {
                this._bindings = new Object();
                this._maxIterations = 10;
        }
        
        public function registerBinding(source:String, destination:String,
endpointSRC:UIObject):Boolean {
                var isBindingAlreadyDefined:Boolean = false;
                var binding:Object = new Object();
                
                // Determine if the end pointer is defined.
                if(endpointSRC == undefined) {
                        
Application.FaultHandler.createException("BindingManager.registerBinding()
endpoint is undefined");
                        return false;
                }
                
                binding.destination = destination;
                binding.endpointSRC = endpointSRC;
                
                if(this._bindings[source] == undefined) {
                        this._bindings[source] = new Array();
                } else {
                        for(var i=0; i < this._bindings[source].length; i++) {
                                if(this._bindings[source][i] === binding) {
                                        return false;
                                }
                        }
                }
                this._bindings[source].push(binding);
                return true;
        }
        

        
        public function onData(source:String, dataPacket,cntr):Void {
                cntr = cntr || 0;
                
                if(this._bindings[source] == undefined) {
                        return;
                }
                
                // Iterate over the Binding Registry to see if any exist.
                for(var i=0; i < this._bindings[source].length; i++) {
                        var binding = this._bindings[source][i];
                        cntr++;
                        
                        // If there is a binding chain setup, then execute.
                        if(this._bindings[i] !== undefined & cntr < 
this._maxIterations) {
                                this.onData(i,dataPacket,cntr);
                        }
                        binding.endpointSRC[binding.destination] = dataPacket;
                }
        }
}

In theory, if this applies and holds water, a FLEX developer should be
able to bind any number of "views/controls" to multiple results from a
RemoteService with Minimal effort.

Now to bind a view to a service, i use an XML solution like this:

<event name="loadCustomView" etc..>
        <viewpod name="MyTreePanel" mappingKey="" containerKey="" etc..>
                <binding source="data_FromMyCFC" destination="treeDP"/>
        </viewpod>
        
        <viewpod name="MyMenuBar" mappingKey="" containerKey="" etc..>
                <binding source="data_FromMyCFC" destination="menuBarModel"/>
        </viewpod>
        
        <notifyservice name="MyPremadeServiceName" method="getTreeData"
resultKey="data_FromMyCFC"/>
        
</event>

What happens here, is that the event "loadCustomView" basically does
the following in sequence:


- Creates MyTreePanel via createChild(pathToViewPod). (ie var vp =
containerObj.createChild(fnTemplate,"MyTreePanel"));
- Registers the binding in BindingManager (ie
BindingManager.registerBinding('data_FromMyCFC','treeDP',vp))

- Creates MyMenuBar via createChild(pathToViewPod). (ie var vp =
containerObj.createChild(fnTemplate,"MyMenuBar"));
- Registers the binding in BindingManager (ie
BindingManager.registerBinding('data_FromMyCFC','menuBarModel',vp))

- Create an empty ResultHandler, populate it with resultKey.
- Find the Service "MyPremadeServiceName" from within ServiceManager.
- Once found, it then invokes the "getTreeData", passing in the
ResultHandler object, along with any additional arguments specified
within two scopes (_global.local, _global.request)

- getTreeData then does its own logic to basically determine where the
onResult will go (either directly to the ResultHandler or to its own
subroutine prior to handing it off to ResultHandler).

- getTreeData then invokes the relevant service (it knows what to do
and how to initate the invocation, feeding any relevant arguments).

- Data comes back, if its successful, eventually
ResultHandler.onResult() is called, with the new data passed into it.
- ResultHandler then dispatches the event "onResult" with appropriate
arguments (in case other classes want to "know")
- ResultHandler then invokes BindingManager.onData(this.resultKey,event.result);
- BindingManager.onData then of course iterates over its own registry
until its exhausted all or hit a maxthreshold.
- ViewPods are now automatically updated.

Questions:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1) I'm concerned with Memory Leaks, in that if i have a registry, i'll
need to clean it up aswell, in that if i destroy a "view" it also
needs to prior to being destroyed, unregister itself. What would folks
recommend i do? write my own GarbageCollection class? or
destroyerClass?

2) ResultHandlers are automatic, but can anyone think of why a
developer would need to make his/her own ResultHandler? in that do you
think i should provide an attribute like this:

<notifyservice name="MyPremadeServiceName" method="getTreeData"
resultKey="data_FromMyCFC">
        <customHandler path="{com.yourpath.resulthandlers.obj}"/>
</notifyservice>

3) Can anyone think of a fallout that may arise if one uses this
practice? in that is it bad coding, bad "best practices" etc.. any
thing i should be mindful of in terms of performance? As once used, I
can see it being used over and over and over and would love to tap
into existing development knowledgebank to give an early heads up.

4) What do you think?


-- 
Regards,
Scott Barnes
http://www.mossyblog.com
http://www.flexcoder.com (Coming Soon)


 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/flexcoders/

<*> To unsubscribe from this group, send an email to:
    [EMAIL PROTECTED]

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 


Reply via email to