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

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

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

3 ответа

Решение

Пока вы убивали клетки мозга, я попробовал рекурсивную функцию;) Она исключает компоненты и объекты 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> 

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

Я смог решить эту проблему путем намеренного неправильного использования 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>

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

современное обновление этого вопроса:

почему бы просто не использовать#serializeJSON(deserializeJson(theObject))#

таким образом вы получите глубокую копию без компонентов.

Другие вопросы по тегам