Crazy Fun with CFCs and Functions: StructToBean()
This totally defeats all purposes of OO encapsulation, and a variety of other principles, but it was a fun time to play around with.
Basically, i wanted to see if I could turn a Struct into a Bean object on the fly. Strangely enough, it was pretty simple considering the flexibility you have with functions and CFCs.
The code works out like follows:<cfscript>
//helper functions
function identityHashCode(object)
{
var system = createObject("java", "java.lang.System");
return system.identityHashCode(arguments.object);
}
function setInstance(instance)
{
variables.instance = arguments.instance;
}
</cfscript>
<cffunction name="structToObject" hint="Converts a structure to a object with getters and setters" access="public" returntype="WEB-INF.cftags.component" output="false">
<cfargument name="inputStruct" hint="Struct to convert" type="struct" required="Yes">
<cfscript>
var obj = createObject("component", "WEB-INF.cftags.component");
var lKeys = StructKeyList(arguments.inputStruct);
var hash = identityHashCode(arguments.inputStruct);
var key = ""; var path = GetDirectoryFromPath(CGI.PATH_TRANSLATED);
var nl = chr(10) & chr(13);
var buffer = createObject("java", "java.lang.StringBuffer").init("<cfscript>#nl#");
//move variable scope to inside the CFC
obj.setInstance = setInstance;
obj.setInstance(arguments.inputStruct);
StructDelete(obj, "setInstance");
</cfscript>
<cfloop list="#lKeys#" index="key">
<!--- write out the function to get and set --->
<cfscript>
buffer.append("function get#key#() { return instance.#key#; }#nl#");
buffer.append("function set#key#(#key#) { instance.#key# = arguments.#key#; }#nl#");
</cfscript>
</cfloop>
<cfscript>
buffer.append("</cfscript>");
</cfscript>
<!--- make the file - use the hash to ensure uniqueness --->
<cffile action="write" file="#path##hash#.functions" output="#buffer.toString()#">
<!--- import the file --->
<cfinclude template="#hash#.functions">
<!--- delete the file --->
<cffile action="delete" file="#path##hash#.functions">
<!--- add it to the object --->
<cfloop list="#lKeys#" index="key">
<cfscript>
obj["get#key#"] = variables["get#key#"];
obj["set#key#"] = variables["set#key#"];
</cfscript>
</cfloop>
<cfreturn obj>
</cffunction>
To test this out:<!--- test code --->
<cfscript>
myStruct = StructNew();
myStruct.fred = "Fred";
obj = structToObject(myStruct);
</cfscript>
<cfoutput>
#obj.getFred()#
<hr>
<cfscript>
obj.setFred("blue");
</cfscript>
#obj.getFred()#
</cfoutput>
Essentially this function:,
- Creates a basic CFC (WEB-INF.cftags.component is the base CFC for all CFCs),
- Adds the 'setInstance()' function to the CFC, and sets the Struct to the instance data of the CFC with it,
- Removes 'setInstance()' function from the CFC,
- The function loops through the Struct Keys,
- It writes a series of getter and setter functions to an external file,
- Imports in the file, placing these functions into the variables scope,
- Deletes the file (cleanup!)
- Adds all these functions to the CFC,
- Returns the CFC.
And look at that, we have created a CFC at run time! Totally defeats some core OO concepts, but it was interesting to note that you can do it.






Comments
No comments have been entered for this post.