在 ColdFusion 中的另一个 cfc 的上下文中执行一个函数,同时遵守导入语句

Execute a function in the context of another cfc in ColdFusion while honoring import statements

背景

我正在尝试创建一个可以从 JSON 重构组件图的函数 componentFromJson。我采用了一种简单的方法,我使用 getMetaData 来查找组件属性以实例化正确的类型。

函数的用法如下:comp = componentFromJson(json, 'RootComponentType')

问题

问题是属性的类型不一定是完全限定的,因为命名空间可能已被导入,如下所示。

<cfimport path="some.namespace.Test">

<cfcomponent>
    <cfproperty name="test" type="Test">
</cfcomponent>

当我尝试从 componentFromJson 函数上下文执行 createObject('Test') 时,显然失败了,因为调用上下文没有导入。

我尝试了很多不同的方法来解决这个问题,包括临时在父组件上动态定义组件工厂函数,并使用 invoke 在父 CFC 的上下文中调用工厂函数,但是它没用。

例如

<cfscript>
    parentCmp = createObject('SomeCmp');
    parentCmp.createComponent = function (type) {
        return createObject(type);
    };
    childCmp = invoke(parentCmp, 'createComponent', { type = 'Test' });
</cfscript>

糟糕的解决方案

我现在能想到的解决这个问题的唯一方法是解析 CFC 的 ColdFusion 代码并提取导入语句,但我预计这对于这个目的来说太慢了。不仅如此,这还不能涵盖所有边缘情况。

想法?

我想知道是否有人对解决这个问题有更好的想法?我可以采取完全不同的方法吗?可能有一种方法可以使用 ColdFusion 运行时来执行此操作 类,但我还没有弄清楚。

好吧,事实证明,当您了解 ColdFusion 运行时的基础机制(我最初很难找到它)时,这并不难。

我终于发现表示为 coldfusion.runtime.TemplateProxy 的 ColdFusion 组件正在封装一个 coldfusion.runtime.CFPage 实例,该实例又具有 createObject 方法。

因此,这是我使用 Java 反射提出的解决方案:

<cfset host = new SomeComponent()>
<cfset pageField = createObject('java', 'coldfusion.runtime.TemplateProxy').getClass().getDeclaredField('page')>
<cfset pageField.setAccessible(true)>
<cfset page = pageField.get(host)>
<cfset test = page.createObject('Test')>