我知道这不是这样做的方式,而且根本不干净。我只是想知道是否可能。
如果我有一组带有一堆方法的课程
public class Foo {
methodA() {}
methodB() {}
methodC() {}
}
是否有可能捕获所有可能发生的异常,而无需在每种方法中编写try / catch?
答案 0 :(得分:23)
是的。最简单的方法是这个类的属性,如下所示:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class HandleErrorAttribute : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (filterContext.ExceptionHandled)
{
return;
}
var exception = filterContext.Exception;
// that need to be your current request object. In this case I use a custom one so I must fetch it from the items collection of the current request, where I had stored it before.
var request = filterContext.HttpContext.Items[Request.RequestKey] as Request;
if (request != null)
{
// overwrite ErrorResponse with a response object of your choice or write directly to the filterContext.HttpContext.Response
var errorResponse = new ErrorResponse(request, exception);
errorResponse.Write(filterContext.HttpContext.Response);
filterContext.ExceptionHandled = true;
}
}
}
// Or a just slightly modified version of the default ASP.Net MVC HandleError Attribute
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class CustomHandleErrorAttribute : FilterAttribute, IExceptionFilter
{
// Fields
private const string _defaultView = "Error";
private string _master;
private readonly object _typeId = new object();
private string _view;
// Methods
public virtual void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (!filterContext.IsChildAction && (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled))
{
Exception innerException = filterContext.Exception;
if ((new HttpException(null, innerException).GetHttpCode() == 500))
{
string controllerName = (string)filterContext.RouteData.Values["controller"];
string actionName = (string)filterContext.RouteData.Values["action"];
HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
ViewResult result = new ViewResult();
result.ViewName = this.View;
result.MasterName = this.Master;
result.ViewData = new ViewDataDictionary<HandleErrorInfo>(model);
result.TempData = filterContext.Controller.TempData;
filterContext.Result = result;
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.StatusCode = 500;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
}
}
}
public string Master
{
get
{
return (this._master ?? string.Empty);
}
set
{
this._master = value;
}
}
public override object TypeId
{
get
{
return this._typeId;
}
}
public string View
{
get
{
if (string.IsNullOrEmpty(this._view))
{
return "Error";
}
return this._view;
}
set
{
this._view = value;
}
}
}
用法(未经测试的原因我在已实现所有必需接口的控制器的上下文中使用它)
[HandleErrorAttribute]
public class Foo : IExceptionFilter // (I am not sure about this one IActionFilter)
{
public void MethodA()
{
// body
}
public void MethodB()
{
// body
}
public void MethodC()
{
// body
}
}
或者你可以这样做:
public class ExecuteHelper
{
public static void Catch(Action action)
{
try
{
action();
}
catch (Exception ex)
{
// Do what you want
}
}
}
并在函数体中使用它:
public void Foo(string something)
{
ExecuteHelper.Catch(() =>
{
// Do something with something or without something
});
}
答案 1 :(得分:5)
您可以编写一个更高阶的函数来处理异常,这会使它更加清晰。
private T FooExceptionHandler(Func<T> function)
{
try
{
return function();
}
catch
{
//handle it
}
}
如果没有返回值,可以将Func替换为Action。 您可以在函数之外以两种方式使用它:
FooExceptionHandler(MethodA);
或在每个函数内部:
MethodA()
{
return FooExceptionHandler(()=>
{
//Function body goes here
});
}
答案 2 :(得分:0)
不,没有。 try
/ catch
块只能出现在方法中。但是,您可以使用某种AOP框架来自动生成这些块。 postcrap是一个非常轻量级的AOP组件。
答案 3 :(得分:0)
您可以在调用这些方法的函数中处理它......
答案 4 :(得分:0)
默认情况下,在ASP.NET中,您可以覆盖OnError
方法,然后执行Server.ClearError
以处置异常。
我不确定它是否适用于您的情况(仅适用于Page
和Global.asax
)