在 .Net 中,是否有可能在类中的任何方法传递到调用堆栈之前捕获所有未处理的异常?
问题:
我想捕获类中任何方法的任何异常,以便在将类特定数据传递到堆栈之前将其记录到异常中以进行记录。我知道我可以在类的每个方法中放置一个try-catch,但是方法很多,似乎应该有一种更有效的方法。
我当前正在做的事情的示例:
public class ClassA
{
private int x;
private int y;
public void Method1()
{
try
{
//Some code
}
catch(Exception ex)
{
ex.Data.Add("x", x);
ex.Data.Add("y", y);
throw;
}
}
public void Method2()
{
try
{
//Some code
}
catch (Exception ex)
{
ex.Data.Add("x", x);
ex.Data.Add("y", y);
throw;
}
}
}
我想要做的事情的示例:
public class ClassB : IUnhandledErrorHandler
{
private int x;
private int y;
public void Method1()
{
//Some code
}
public void Method2()
{
//Some code
}
void IUnhandledErrorHandler.OnError(Exception ex)
{
ex.Data.Add("x", x);
ex.Data.Add("y", y);
throw;
}
}
public interface IUnhandledErrorHandler
{
void OnError(Exception ex);
}
注意: 此类是 WCF 项目中的一个服务,并实现 ServiceContract。我尝试将 ErrorHandler 添加到服务的 ChannelDispatcher 中。但是,当错误到达 ErrorHandler 时,它已经超出了发生错误的类的范围,因此我无法访问类的详细信息。
解决方案:
public class ClassC
{
public ClassC()
{
AppDomain.CurrentDomain.FirstChanceException += OnError;
}
private int x;
private int y;
public void Method1()
{
//Some code
}
public void Method2()
{
//Some code
}
private void OnError(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
{
e.Exception.Data["x"] = x;
e.Exception.Data["y"] = y;
}
}
Problem:
I would like to catch any exceptions from any method in a class so that I may record class specific data to the exception for logging before it is passed up the stack. I know that I can put a try-catch in every method of the class, but there are many methods and It seems there should be a more efficient way.
Example of what I am currently doing:
public class ClassA
{
private int x;
private int y;
public void Method1()
{
try
{
//Some code
}
catch(Exception ex)
{
ex.Data.Add("x", x);
ex.Data.Add("y", y);
throw;
}
}
public void Method2()
{
try
{
//Some code
}
catch (Exception ex)
{
ex.Data.Add("x", x);
ex.Data.Add("y", y);
throw;
}
}
}
Example of what I would like to do:
public class ClassB : IUnhandledErrorHandler
{
private int x;
private int y;
public void Method1()
{
//Some code
}
public void Method2()
{
//Some code
}
void IUnhandledErrorHandler.OnError(Exception ex)
{
ex.Data.Add("x", x);
ex.Data.Add("y", y);
throw;
}
}
public interface IUnhandledErrorHandler
{
void OnError(Exception ex);
}
Note:
This class is a service in a WCF project and implements a ServiceContract. I have tried adding an ErrorHandler to the service's ChannelDispatcher. However, when the error reaches the ErrorHandler it is already beyond the scope of the class where the error occurred, so I cannot access the class details.
Solution:
public class ClassC
{
public ClassC()
{
AppDomain.CurrentDomain.FirstChanceException += OnError;
}
private int x;
private int y;
public void Method1()
{
//Some code
}
public void Method2()
{
//Some code
}
private void OnError(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
{
e.Exception.Data["x"] = x;
e.Exception.Data["y"] = y;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您在 .NET 4 上运行,则可以使用来自应用程序域。
If you run on .NET 4, you might use the FirstChanceException event from the AppDomain.
您可以通过继承 System.ContextBoundObject 来实现此目的。它并不像您希望的那么漂亮,而且我相信可能会产生一些与之相关的重大开销,但据我所知,这是执行您所描述的操作的唯一方法。
正如这里所要求的,是进一步的阐述......正如所提到的,它并不漂亮,但这里是完成这项工作所需的最小实现。我们感兴趣的主要方法是 AOPSink.SyncProcessMessage 方法。它在“Test”对象上的任何方法之前调用,并且对 NextSink.SyncProcessMessage(msg) 的调用实际上调用了最初调用的方法。您可以通过使用传递给 SyncProcessMessage 的 IMessage 参数来检查(和修改)调用了哪个方法以及传递的参数,并且可以通过使用从 NextSink.SyncProcessMessage 返回的 IMessage 来检查/修改返回值(或抛出的异常)。此功能会产生显着的性能开销,因此我不建议将其用于除调试目的之外的高流量对象。
You can accomplish this by inheriting from System.ContextBoundObject. It's not as pretty as you would hope, and I believe there probably is some significant overhead associated with it, but as far as I know it's the only way to do what you describe.
As requested here is further elaboration...as mentioned it ain't pretty, but here is a minimal implementation needed to make this work. The main method of interest is the AOPSink.SyncProcessMessage method. It is called prior to any method on a 'Test' object, and the call to NextSink.SyncProcessMessage(msg) is what actually invokes the originally called method. You can inspect (and modify) which method was called and the parameters passed by playing with the IMessage parameter passed to SyncProcessMessage, and you can inspect/modify the return value (or thrown Exception) by playing with the IMessage returned from NextSink.SyncProcessMessage. There is significant performance overhead for this functionality, so I wouldn't recommend it for high traffic objects outside of debugging purposes.