ColdFusion是否支持代表?

Dan*_* T. 3 coldfusion delegates dry coldfusion-9

我有几个数据库访问方法包含在try/catch块中:

function GetAll() {
    try {
        entityLoad("Book");
    }
    catch (any e) {
        throw (type="CustomException", message="Error accessing database, could not read");
    }
}

function Save(Book book) {
    try {
        entitySave(book);
    }
    catch (any e) {
        throw (type="CustomException", message="Error accessing database, could not save);
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,try/catch块会重复多次,其中唯一不同的是消息.是否可以在ColdFusion中创建委托,以便我可以做这样的事情(使用C#lambda来表示匿名委托)?:

function GetAll() {
    DatabaseOperation(() => entityLoad("Book"), "could not read");
}

function Save(Book book) {
    DatabaseOperation(() => entitySave(book), "could not save");
}

function DatabaseOperation(delegate action, string error) {
    try {
        action.invoke();
    }
    catch (any e) {
        var message = "Error accessing database, " & error;
        throw (type="CustomException", message=message);
    }
}
Run Code Online (Sandbox Code Playgroud)

Pet*_*ton 6

根据您的示例,而不是CF9.

关闭将在CF10中出现,这可能会让你做类似的事情:

function GetAll() {
    DatabaseOperation( closure(){ entityLoad("Book") } , "could not read");
}

function Save(Book book) {
    DatabaseOperation( closure(){ entitySave(book) } , "could not save");
}

function DatabaseOperation(closure action, string error) {
    try {
        action();
    }
    catch (any e) {
        var message = "Error accessing database, " & error;
        throw (type="CustomException", message=message);
    }
}
Run Code Online (Sandbox Code Playgroud)

(语法可能会有所不同,不记得是否完全相同)


或者,你可以evaluate在这里使用,我猜......

function GetAll() {
    DatabaseOperation( 'entityLoad("Book")' , "could not read");
}

function Save(Book book) {
    DatabaseOperation( 'entitySave(book)' , "could not save");
}

function DatabaseOperation(string action, string error) {
    try {
        evaluate(action);
    }
    catch (any e) {
        var message = "Error accessing database, " & error;
        throw (type="CustomException", message=message);
    }
}
Run Code Online (Sandbox Code Playgroud)


我个人只是删除的try/catch和使用onErrorApplication.cfc-似乎并没有被掩盖原来的错误有用,而是抛出一个更通用的一个?


更新:两个可能的替代方案......

当前工作的另一个选项是有一个公共包装函数,它调用DatabaseOperation函数,传入一个私有函数的名称,它执行如下所示的实际逻辑:

function GetAll() {
    DatabaseOperation( real_GetAll , Arguments , "could not read");
}
private function real_GetAll() {
    entityLoad("Book")
}

function Save(Book book) {
    DatabaseOperation( real_Save , Arguments , "could not save");
}
private function real_Save(Book book) {
    entitySave(book)
}

function DatabaseOperation(any action, struct args , string error) {
    try {
        action( argumentcollection=args )
    }
    catch (any e) {
        var message = "Error accessing database, " & error;
        throw (type="CustomException", message=message);
    }
}
Run Code Online (Sandbox Code Playgroud)


如果你不喜欢两次定义函数的想法,但不介意模糊API,你可以将方法设置为private,然后使用onMissingMethod:

private function GetAll()
{
    entityLoad("Book")
}

private function Save(Book book)
{
    entitySave(book)
}

function onMissingMethod( string MethodName , struct MethodArgs )
{
    if ( NOT StructKeyExists(Variables,Arguments.MethodName) )
    {
        throw("The method #Arguments.MethodName# was not found");
    }

    try
    {
        var Meth = Variables[Arguments.MethodName];
        Meth( ArgumentCollection=Arguments.MethodArgs );
    }
    catch(any e)
    {
        var message = "Error accessing database, ";

        switch(MethodName)
        {
            case "GetAll":
                message &= "could not read";
            break;
            case "Save":
                message &= "could not save";
            break;
        }

        throw (type="CustomException,message=message);
    }
}
Run Code Online (Sandbox Code Playgroud)