Вызовите метод ColdFusion с явным получателем - PullRequest
0 голосов
/ 19 октября 2018

Я пытаюсь написать миксин в ColdFusion.

ExampleMixin.cfc:

component {
    remote void function mixin(component, methodName) {
        var original = component[methodName];
        component[methodName] = function() {
            writeOutput("Mixin!");
            return original(arguments);
        };
    }
}

test.cfc:

component {
    new ExampleMixin().mixin(this, 'foo');

    remote string function foo() {
        return getOutput();
    }

    private string function getOutput() {
        return "Hello, World!";
    }
}

Запуск foo выдает ошибку, Variable GETOUTPUT is undefined..Если я закомментирую new ExampleMixin().mixin(this, 'foo');, он будет работать нормально.

Похоже, когда foo запускается из оболочки, он работает не в нужном контексте.В JavaScript можно написать foo.call(component, ...arguments), чтобы исправить это.Есть ли в ColdFusion аналог?

1 Ответ

0 голосов
/ 20 октября 2018

ColdFusion использует области this и variables для хранения ссылок на функции.Используемая ссылка зависит от того, как вызывается функция.Если функция вызывается с одного из братьев, используется ссылка variables.Если функция вызывается извне, используется ссылка this.

В следующем коде используется базовый класс для обеспечения функциональности смешивания.Функция $mixin принимает экземпляр компонента и внедряет все его функции.Если происходит конфликт имен, обертка сначала вызовет mixin, а затем оригинальную функцию.Я генерирую новые имена функций как для исходных функций, так и для функций mixin, поэтому ссылки могут быть установлены в обеих областях.

Это было проверено на Lucee 5.2.8.50.

mixable.cfc

component {
    function $mixin(obj) {
        var meta = getComponentMetadata(obj);

        for(var func in meta.functions) {
            if(structKeyExists(this, func.name)) {
                var orig = func.name & replace(createUUID(), '-', '', 'all');
                var injected = func.name & replace(createUUID(), '-', '', 'all');

                this[orig] = this[func.name];
                variables[orig] = this[func.name];

                this[injected] = obj[func.name];
                variables[injected] = obj[func.name];

                var wrapper = function() {
                    this[injected](argumentCollection=arguments);
                    return this[orig](argumentCollection=arguments);
                };
                this[func.name] = wrapper;
                variables[func.name] = wrapper;
            } else {
                this[func.name] = obj[func.name];
                return variables[func.name] = obj[func.name];
            }
        }
    }
}

test.cfc

component extends="mixable" {
    remote function foo() {
        writeOutput("foo(), calling bar()<br>");
        bar();
    }

    private function bar() {
        writeOutput("bar()<br>");
    }
}

mixin.cfc

component {
    function foo() {
        writeOutput("foo mixin, calling bar()<br>");
        bar();
    }

    function myfunc() {
        writeOutput("myfunc()<br>");
    }
}

index.cfm

<cfscript>
t = new test();
t.$mixin(new mixin());
t.myfunc();
t.foo();
</cfscript>

Выход

myfunc()
foo mixin, calling bar()
bar()
foo(), calling bar()
bar()
...