ColdFusion 支持代表吗?

发布于 2024-12-03 05:35:35 字数 1000 浏览 1 评论 0原文

我有几种封装在 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);
    }
}

如您所见,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);
    }
}

I have several database access methods that are wrapped in a try/catch block:

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);
    }
}

As you can see, the try/catch block is repeated several times, where the only thing that varies is the message. Is it possible to create a delegate in ColdFusion so that I can do something like this instead (using a C# lambda to represent an anonymous delegate)?:

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);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

茶花眉 2024-12-10 05:35:35

根据您的示例,而不是 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);
    }
}

语法可能有所不同,不记得是否完全一样)

或者,我猜你可以在这里使用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);
    }
}

就我个人而言,我只是删除 try/catch 并在 Application.cfc 中使用 onError - 似乎对于掩盖原始错误没有用,而是抛出一个更通用的错误?

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

当前有效的另一个选择是使用一个公共包装函数,该函数调用 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);
    }
}

如果您不喜欢两次定义函数的想法,但不介意模糊 API,您可以将方法设置为私有,然后使用 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);
    }
}

Based on your example, not with CF9.

Closures are coming in CF10 which will probably allow you to do something like:

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);
    }
}

(syntax might vary, don't remember if it was exactly like that)

Alternatively, you could probably use evaluate here, I guess...

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);
    }
}

Personally I would just remove the try/catch and use onError in Application.cfc - doesn't seem to be useful to mask the original error and instead throw a more generic one?

Update: two more possible alternatives...

Another option that currently works is to have a public wrapper function, that calls the DatabaseOperation function, passing in the name of a private function that does the actual logic like this:

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);
    }
}

If you don't like the idea of defining functions twice, but don't mind obscuring the API, you could set the methods to private then use 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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文