The practice of using a struct to store instance data certainly makes a lot of sense when you want to implement a clone method since the duplicate function works correctly on a struct. I would certainly advocate that approach and additionally, I would suggest Nathan add this information to his document.

-Matt


On Apr 5, 2004, at 12:34 PM, Nathan Dintenfass wrote:


There's no built-in way to do it.

It's fairly easy to build a clone() method that creates a new instance of
the same CFC and then copies the instance data over. As an aside, this is
one of the reasons I like to create a sub-struct inside of the VARIABLES
scope for my private instance data -- so it can be copied as a single unit
to a cloned instance.


So, for instance, you might have "package" methods that look like:

getInstanceData();
setInstanceData(struct);
hasInstanceData();

If you had a "virtual scope" in your Variables scope called "instance",
these might look like:

<cffunction name="getInstanceData"
                        access="private"
                        output="no"
                        returnType="struct"
                        hint="returns the instance data of this component">
        <cfreturn duplicate(instance)>
</cffunction>

<cffunction name="setInstanceData"
<!--- make it package access, so that we can call it on a clone! --->
access="package"
output="no"
returnType="void"
hint="Given a structure, overwrites any existing instance data with
that">
<cfargument name="data"
type="struct"
required="yes">
<cfset structAppend(instance,arguments.data,true)>
</cffunction>


<cffunction name="hasInstanceData"
                        access="private"
                        output="no"
                        returnType="boolean"
                        hint="Tells whether the current component has instance data">
        <cfreturn isDefined("instance")>
</cffunction>

You can then make a public method called clone() that might look like:

<cffunction name="clone"
access="public"
output="no"
returnType="yourComponentType"
hint="makes a clone of this component">
<!--- make a new component instance of whatever type the current component
is --->
<cfset var anInstance = createObject("component","yourComponentType")>
<!--- now populate the instance data of that component, if there is
any --->
<cfif hasInstanceData()>
<cfset anInstance.setInstanceData(getInstanceData())>
</cfif>
<cfreturn anInstance>
</cffunction>


The only complication will be if you end up with other CFCs/Objects in your
instance variables, since the duplicate(instance) line in getInstanceData
will fail. In that case you'd need to somehow determine which CFCs/Objects
they were and have a way to clone each of them.


I also once built a general purpose duplicateCFC() UDF, but it doesn't take
into account the scenario of CFCs as instance variables (and had some other
issue I can't remember now), but it might help you:


<cfscript>
function duplicateCFC(instance){
        var newInstance = "";
        var error = "";
        var templateProxyFactory = "";
        var fileObject = "";
        var instanceData = "";
        var key = "";
        //if THIS is defined, we must be attached to a CFC, so act that way
        if(isDefined("this")){
                //if the argument is a struct, set the variables in this instance
                if(isStruct(arguments.instance))
                        structAppend(Variables,arguments.instance);
                //otherwise, just return Variables to get them out of this instance
                else
                        return Variables;
        }
        //if THIS is not defined, we are being called on the instance
        else{
                //take the method onto the instance

arguments.instance.temporaryMethodNameThatNobodyWillEverUseBecauseItRun sDupl
icateCFC = duplicateCFC;
//first, try making it with the "path", because that's fastest
try{
newInstance =
createObject("component",getMetaData(arguments.instance).name);
}
//if something goes wrong, try making the instance based on the absolute
file path
catch("Application" error){
templateProxyFactory =
createObject("java","coldfusion.runtime.TemplateProxyFactory");
fileObject = createObject("java","java.io.File");
fileObject.init(getMetaData(arguments.instance).path);
newInstance = templateProxyFactory.resolveFile(getPageContext(),
fileObject);
}
//now, we attach this method to the new instance as a temporary method
name


newInstance.temporaryMethodNameThatNobodyWillEverUseBecauseItRunsDuplic ateCF
C = duplicateCFC;
//grab the instance data from the original
//THIS SHOULD POSSIBLY DO A DEEP INSPECTION TO ACCOUNT FOR OBJECT
INSTANCES INSIDE THE VARIABLES OF THE INSTANCE
instanceData =
duplicate(arguments.instance.temporaryMethodNameThatNobodyWillEverUseBe cause
ItRunsDuplicateCFC(""));
//clean off the instanceData -- delete THIS
structDelete(instanceData,"this");
//loop through the rest and grab everything that's not a function
for(key in instanceData){
if(isCustomFunction(instanceData[key]))
structDelete(instanceData,key);
}
//put the the variables from one into the other


newInstance.temporaryMethodNameThatNobodyWillEverUseBecauseItRunsDuplic ateCF
C(instanceData);
//now kill the temporary methods from the component instances


structDelete(arguments.instance,"temporaryMethodNameThatNobodyWillEverU seBec
auseItRunsDuplicateCFC");


structDelete(newInstance,"temporaryMethodNameThatNobodyWillEverUseBecau seItR
unsDuplicateCFC");
return newInstance;
}
}
</cfscript>



-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]
Behalf Of Alexander Sherwood
Sent: Monday, April 05, 2004 8:56 AM
To: [EMAIL PROTECTED]
Subject: [CFCDev] Copying a CFC instance?!


Please help:


Just realized that using Duplicate() on an instance of a CFC
returns a bare struct. Apart from creating a new object, is there
a way to copy create an instance of a CFC from an existing
instance (that copied by value, no by reference)?

Any help would be massively appreciated.

Thanks!

----------------------------------
Alex Sherwood
PHS Collection Agency
THE COLLECTORS
P:   813-283-4579
F:   301.664.6834
W: www.phs-net.com

----------------------------------------------------------
You are subscribed to cfcdev. To unsubscribe, send an email
to [EMAIL PROTECTED] with the words 'unsubscribe cfcdev'
in the message of the email.

CFCDev is run by CFCZone (www.cfczone.org) and supported
by Mindtool, Corporation (www.mindtool.com).

An archive of the CFCDev list is available at
www.mail-archive.com/[EMAIL PROTECTED]


---------------------------------------------------------- You are subscribed to cfcdev. To unsubscribe, send an email to [EMAIL PROTECTED] with the words 'unsubscribe cfcdev' in the message of the email.

CFCDev is run by CFCZone (www.cfczone.org) and supported
by Mindtool, Corporation (www.mindtool.com).

An archive of the CFCDev list is available at www.mail-archive.com/[EMAIL PROTECTED]


----------------------------------------------------------
You are subscribed to cfcdev. To unsubscribe, send an email
to [EMAIL PROTECTED] with the words 'unsubscribe cfcdev' in the message of the email.


CFCDev is run by CFCZone (www.cfczone.org) and supported
by Mindtool, Corporation (www.mindtool.com).

An archive of the CFCDev list is available at www.mail-archive.com/[EMAIL PROTECTED]

Reply via email to