Как выполнить глубокое копирование (клонирование) структуры, игнорируя при этом компоненты - PullRequest
3 голосов
/ 17 сентября 2011

В версиях ColdFusion до 8 функция дублирования выдает ошибку, если в структуре есть какие-либо компоненты. В 8 и выше он будет работать, но есть проблемы при копировании компонентов.

Итак, мне нужен способ создания глубокой копии структуры, игнорирующей компоненты. Для моих целей это для отладки, мне нужен снимок области видимости переменных в определенной точке кода, поэтому эффективность не имеет значения, так как это никогда не выйдет из среды разработки. В настоящее время, используя CF 7, я бы взял то, что предлагает 8, хотя бы для решения этой неотложной проблемы, но я не контролирую обновление: (

Ответы [ 2 ]

5 голосов
/ 17 сентября 2011

Пока вы убивали клетки мозга, я попробовал рекурсивную функцию;) Она исключает компоненты и объекты java / com.Ни один из которых MX7 не может дублировать.Я бросил функции в компонент, чтобы избежать вмешательства в область действия variables.Затем сохранил экземпляр в области действия request.

Это не строго проверено.Поэтому я уверен, что есть возможности для улучшения.

Использование

<cfset request.util = createObject("component", "Util")>
<cfset request.copy = request.util.duplicateStructMinusObjects(variables)>
<cfdump var="#request.copy#">

Util.cfc

<cfcomponent>
    <cfscript>
            function duplicateArrayMinusObjects(input) {
                    var x      = "";
                    var value  = "";
                    var output = arrayNew(1);

                    for (x = 1; x lte arrayLen(arguments.input); x = x + 1) {
                            value = arguments.input[x];

                            // note components are considered structures
                            if (IsStruct(value) and not IsObject(value)) {
                                    arrayAppend(output, duplicateStructMinusObjects(value));
                            }
                            else if (IsArray(value)) {
                                    arrayAppend(output, duplicateArrayMinusObjects(value));                
                            }
                            else if (not IsObject(value)){        
                                    arrayAppend(output, duplicate(value));
                            }
                    }        
                    return output;
            }

            function duplicateStructMinusObjects(input) {
                    var key    = "";
                    var value  = "";
                    var output = structNew();

                    for (key in arguments.input) {
                            value = arguments.input[key];

                            // note components are considered structures
                            if (IsStruct(value) and not IsObject(value)) {
                                    output[key] = duplicateStructMinusObjects(value);
                            }
                            else if (IsArray(value)) {
                                    output[key] = duplicateArrayMinusObjects(value);
                            }
                            else if (not IsObject(value)){        
                                    output[key] = duplicate(value);
                            }
                    }

                    return output;
            }
    </cfscript>
</cfcomponent> 
1 голос
/ 17 сентября 2011

Не имеет значения, как долго вы думаете / ищите, вы всегда найдете ответ сразу после того, как задаете вопрос.

Мне удалось решить эту проблему путем преднамеренного неправильного использования try / catch, поэтому я перебрал структуру, попытался создать объект из каждого элемента, как если бы он был компонентом, и по ошибке скопировал его. к моей структуре снимка. Мне также пришлось хранить его в другой области, в моем случае я использовал сессию, поскольку, если я позволю ему перейти к переменным по умолчанию, будет циклическая ссылка, которая приведет к структуре с бесконечным числом дочерних элементов.

РЕДАКТИРОВАТЬ: ЭТО НЕ ДЕЛАЕТ, ЧТО Я ДУМАЛ, ЧТО ЭТО ДЕЛАЛ, СМОТРИ НИЖЕ

<cfset session.varSnapShot = StructNew()>
<cfset loopList = StructKeyList(variables)>
<cfloop from="1" to="#ListLen(loopList)#" index="i">
    <cftry>
        <cfobject name="x#i#" component="#variables[ListGetAt(loopList,i)]#">
        <cfcatch>
            <cfset session.varSnapShot[ListGetAt(loopList,i)]= variables[ListGetAt(loopList,i)]>
        </cfcatch>
    </cftry>
</cfloop>

РЕДАКТИРОВАТЬ: Поскольку вышеприведенное на самом деле не делает глубокую копию (спасибо Ли), я придумал это:

<cfloop from="1" to="#ListLen(loopList)#" index="i">
    <cfset metaData = GetMetaData(variables[ListGetAt(loopList,i)])>
    <cfif isStruct(metaData) AND isDefined("metaData.type") AND metaData.type EQ "component">
    <cfelse>
        <cfset session.varSnapShot[ListGetAt(loopList,i)]= duplicate(variables[ListGetAt(loopList,i)])>
    </cfif>
</cfloop>

Это делает глубокое копирование, но все равно будет проблемой, если компонент находится ниже первого уровня объекта. Я хотел создать рекурсивный метод, но в пятницу прошло уже полтора часа. Вместо этого я убью мозговые клетки в пабе и, возможно, обновлю это рекурсивным методом в понедельник, если я не забуду.

...