Вызовите метод ColdFusion с явным получателем
Я пытаюсь написать миксин в 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 ответ
ColdFusion использует как this
а также variables
Области для хранения ссылок на функции. Используемая ссылка зависит от того, как вызывается функция. Если функция вызывается от родного брата, variables
ссылка используется. Если функция вызывается извне, то this
ссылка используется.
Следующий код использует базовый класс для обеспечения функциональности mixin.$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()