当前位置:  开发笔记 > 编程语言 > 正文

拦截IDisposable.Dispose中的异常

如何解决《拦截IDisposable.Dispose中的异常》经验,为你挑选了3个好方法。

在该IDisposable.Dispose方法中有一种方法可以确定是否抛出异常?

using (MyWrapper wrapper = new MyWrapper())
{
    throw new Exception("Bad error.");
}

如果在using语句中抛出异常,我想在处理IDisposable对象时知道它.



1> Kelqualyn..:

您可以IDisposable使用方法扩展Complete并使用以下模式:

using (MyWrapper wrapper = new MyWrapper())
{
    throw new Exception("Bad error.");
    wrapper.Complete();
}

如果在using语句中抛出异常,则Complete之前不会调用该语句Dispose.

如果您想知道抛出了什么确切的异常,那么订阅AppDomain.CurrentDomain.FirstChanceException事件并将最后抛出的异常存储在ThreadLocal变量中.

这种模式在TransactionScope课堂上实施.



2> Sam Saffron..:

,在.Net框架中没有办法做到这一点,你无法弄清楚finally子句中正在抛出的当前异常.

在我的博客上看到这篇文章,为了与Ruby中的类似模式进行比较,它突出了我认为存在于IDisposable模式中的差距.

Ayende有一个技巧,可以让你检测到发生的异常,但是,它不会告诉你它是哪个异常.



3> Jo VdB..:

这是不可能捕获的异常Dispose()的方法.

但是,可以检查Marshal.GetExceptionCode()Dispose以检测是否确实发生了异常,但我不会依赖它.

如果您不需要类并且只想捕获Exception,则可以创建一个接受在try/catch块中执行的lambda的函数,如下所示:

HandleException(() => {
    throw new Exception("Bad error.");
});

public static void HandleException(Action code)
{
    try
    {
        if (code != null)
            code.Invoke();
    }
    catch
    {
        Console.WriteLine("Error handling");
        throw;
    }
}

例如,您可以使用自动执行事务的Commit()或Rollback()并执行某些日志记录的方法.通过这种方式,您并不总是需要try/catch块.

public static int? GetFerrariId()
{
    using (var connection = new SqlConnection("..."))
    {
        connection.Open();
        using (var transaction = connection.BeginTransaction())
        {
            return HandleTranaction(transaction, () =>
            {
                using (var command = connection.CreateCommand())
                {
                    command.Transaction = transaction;
                    command.CommandText = "SELECT CarID FROM Cars WHERE Brand = 'Ferrari'";
                    return (int?)command.ExecuteScalar();
                }
            });
        }
    }
}

public static T HandleTranaction(IDbTransaction transaction, Func code)
{
    try
    {
        var result = code != null ? code.Invoke() : default(T);
        transaction.Commit();
        return result;
    }
    catch
    {
        transaction.Rollback();
        throw;
    }
}

推荐阅读
放ch养奶牛
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有