Wednesday, March 4, 2009

Remote Component Variable Injection

While working on creating my own extension of ColdSpring's BeanFactory, I discovered a little trick that allowed me to inject and modify variables in a component without the use of public getters or setters. While it came in pretty handy for what I was doing, I think it might be a little too powerful. I've created a simple example to show what I'm talking about.

Application.cfc:

<cfcomponent output="false">

<cfset this.name = "moodswing" />

<cffunction name="onApplicationStart">

<cfset application.happy = createObject("component","mood").init("happy") />
<cfset application.sad = createObject("component","mood").init("sad") />
<cfset application.moodswing = createObject("component","moodswing") />

</cffunction>

<cffunction name="onRequestStart">

<cfif StructKeyExists(url,"init")>
<cfset onApplicationStart() />
</cfif>

</cffunction>

</cfcomponent>


mood.cfc:

<cfcomponent>

<cffunction name="init" returntype="any">
<cfargument name="mood" required="true" type="string" />

<cfset variables.mood = arguments.mood />

<cfreturn this />

</cffunction>

<cffunction name="currentMood" returntype="string">

<cfreturn variables.mood />

</cffunction>

</cfcomponent>


moodswing.cfc:


<cfcomponent output="false">

<cffunction name="changeMood" returntype="void">

<cfset application.sad.changeVariable = changeVariable />

<cfset application.sad.changeVariable("mood",application.happy.currentMood()) />

<cfset StructDelete(application.sad,"changeVariable") />

</cffunction>

<cffunction name="changeVariable" returntype="void">
<cfargument name="key" required="true" />
<cfargument name="value" required="true" />

<cfset variables[arguments.key] = arguments.value />

</cffunction>

</cfcomponent>


default.cfm:

<cfoutput>
Before mood swing:<br />
happy: #application.happy.currentMood()# <br />
sad: #application.sad.currentMood()#<br />

#application.moodswing.changeMood()#

<br />
After mood swing:<br />
happy: #application.happy.currentMood()# <br />
sad: #application.sad.currentMood()#<br />
</cfoutput>


The code doesn't do a whole lot. I create a happy mood and a sad mood on the application page, as well as a moodswing object. Then I output the current mood of each of the objects, before and after a moodswing.

If you run the above code, you'll get something that looks like this:

Before mood swing:
happy: happy
sad: sad

After mood swing:
happy: happy
sad: happy


If you look at the moodswing object, it's copying a reference to a function into the sad object that allows me to directly access the sad object's variables scope, which lets me change the "mood" variable from "sad" to "happy".

Again, I'm not sure how great of a feature this is since it completely breaks encapsulation, but I thought it was worth mentioning.

No comments:

Post a Comment