我希望能够在CFML/LUCEE组件中动态地编写一组getter和setter(没有硬编码的cfproperty标签)。
<!--- MyComp.cfc --->
<cfcomponent displayname="MyComp" hint="MyComp" accessors="true">
<cffunction name="init">
<cfargument name="dynamicprops" type="array">
<cfloop array="#dynamicprops#" index="item">
<!---
Now what? I cannot do a cfsavecontent and write props here.
It demands cfproperty just after the cfcomponent begins. I
tried to do with closures but they are not acually setters
and getters. Does anyone know how to better do it?
--->
</cfloop>
</cffunction>
</cfcomponent>
<!--- example call --->
<cfset mc = CreateObject("component","MyComp").init( [{"name"="a","default"=1}] ) />
然后我希望能够调用mc.setA(100)和mc.getA()。但不会发生。
所以我的拙劣问题是如何在组件上动态编写资源库和获取器?
PS:请记住,我已经尝试过关闭方式:
variables[item.name] = item.default;
variables["set"&item.name] = function(_val){ variables[item.name] =_val; }
variables["get"&item.name] = function(){ return variables[item.name; }
无法工作。我该怎么做? 谢谢:)
你可以为此使用onMissingMethod()
。
component name="myComponent" hint="myComponent.cfc"{
function init( struct dynamicProperties={} ){
dynamicProperties.each( function( name, default ){
variables[ name ] = default;
} );
return this;
}
function onMissingMethod( name, args ){
if( name.Left( 3 ) IS "get" )
return get( name );
if( ( name.Left( 3 ) IS "set" ) AND ( args.Len() IS 1 ) )
return set( name, args[ 1 ] );
cfthrow( type="NonExistentMethod", message="The method '#name#' doesn't exist" );
}
public any function get( required string accessorName ){
var propertyName = parsePropertyName( accessorName );
if( !variables.KeyExists( propertyName ) )
cfthrow( type="NonExistentProperty", message="The property '#propertyName#' doesn't exist" );
return variables[ propertyName ];
}
public void function set( required string accessorName, required any value ){
var propertyName = parsePropertyName( accessorName );
if( !variables.KeyExists( propertyName ) )
cfthrow( type="NonExistentProperty", message="The property '#propertyName#' doesn't exist" );
variables[ propertyName ] = value;
}
private string function parsePropertyName( accessorName ){
return accessorName.RemoveChars( 1, 3 );
}
}
将属性名称/默认值的结构传递给它,它将"侦听"匹配的 getter/setter。任何不这样做都会导致异常。
<cfscript>
myDynamicProperties = { A: 0, B: 0 }; // this is a struct of names and default values
mc = new myComponent( myDynamicProperties );
mc.setA( 100 );
WriteDump( mc.getA() ); // 100
WriteDump( mc.getB() ); // 0
WriteDump( mc.getC() ); // exception
</cfscript>
更新 1:属性名称数组替换为名称/默认值结构作为 init 参数,以允许设置默认值。
更新 2:如果您想传递包含您的名称/默认值对的结构数组,例如
dynamicProperties = [ { name: "A", default: 1 }, { name: "B", default: 2 } ];
那么 init() 方法将是:
function init( array dynamicProperties=[] ){
dynamicProperties.each( function( item ){
variables[ item.name ] = item.default;
} );
return this;
}
更新 3:如果您必须使用标签和<cfloop>
来设置动态属性,那么这就是您在 init 方法中所需要的一切:
<cfloop array="#dynamicProperties#" item="item">
<cfset variables[ item.name ] = item.default>
</cfloop>
如果尝试将动态方法调用为如下所示的属性,则不会触发onMissingMethod
:
method = mc[ "set#property#" ];
method( value );
相反,只需将组件中的set()
和get()
方法设为公共并直接调用它们:
mc.set( property, value );
mc.get( property );
考虑使用访问器
<cfcomponent displayname="MyComp" hint="MyComp" accessors="true">
来源: https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-tags/tags-c/cfcomponent.html