在基类中使用不同的方法和参数捕获派生类异常
本文关键字:参数 派生 异常 方法 基类 | 更新日期: 2023-09-27 18:02:21
我想做一些像基础的"异常处理程序"的事情。因此,当派生类中的任何方法(具有任意数量的参数)被调用时,这个基类将尝试捕获异常。我不擅长用文字来描述,所以下面是场景:
public abstract BaseClass
{
Exception _ex;
public Exception LastKnownException
{
get
{
return this._ex;
}
}
//...
//what do I do here to assign the value of above property when some random exception occur in derived class?
//...
//The closest I can get...
public void RunMethod(Action method)
{
try
{
method.Invoke();
}
catch (Exception ex)
{
this._ex = ex;
}
}
}
public class DerivedClass : BaseClass
{
public void DoRandomMethod(int couldBeOfAnyTypeHere, bool andIndefiniteNumberOfThese)
{
bool result = false;
var someObject = new OtherClass(couldBeOfAnyTypeHere, out andIndefiniteNumberOfThese);
someObject.DoInternalWork(result); // <-- here is where I need the base class to take care if any exception should occur
}
public int AnotherMethod(int? id)
{
if (!id.HasValue)
id = Convert.ToInt32(Session["client_id"]);
var someOtherObject = new OtherClassB(id.Value);
return someOtherObject.CheckSomething(); // <-- and catch possible exceptions for this one too
}
//The closest I can get... (see base class implementation)
public List<RandomClass> GetSomeListBy(int id)
{
RunMethod(() =>
string[] whateverArgs = new[] { "is", "this", "even", "possible?" };
YetAnotherStaticClass.GetInstance().ExecuteErrorProneMethod(whateverArgs); // <-- Then when something breaks here, the LastKnownException will have something
);
}
}
public class TransactionController : Controller
{
public ActionResult ShowSomething()
{
var dc = new DerivedClass();
dc.DoRandomMethod(30, true);
if (dc.LastKnownException != null)
{
//optionally do something here
return RedirectToAction("BadRequest", "Error", new { ex = dc.LastKnownException });
}
else
{
return View();
}
}
}
EDIT:我的简单方法将起作用,只是,我不想一直用这个lambda驱动的RunMethod()
方法包装所有方法——我需要基类以某种方式拦截任何传入的异常,并将Exception
对象返回给派生类而不抛出错误。
任何想法都将非常感激。提前感谢!
我认为你应该考虑使用System.AppDomain.UnhandledException事件
每当发生未处理的异常时,将引发此事件。
由于您的代码不会因异常的可能性而混乱,因此您的代码将具有更好的可读性。此外,它将使派生类有机会在期望异常的情况下捕获异常,而不会干扰您的自动异常捕获器。
你的设计是这样的,如果有人调用你的派生类的几个函数,然后检查是否有任何异常,调用者不会知道是哪个函数引起了异常。我假设调用者对导致异常的函数并不真正感兴趣。如果您只想记录异常,直到有人调查它们时,通常会出现这种情况。
如果是这种情况,可以考虑这样做:
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = e.ExceptionObject as Exception;
if (ex != null)
logger.LogException(ex);
// TODO: decide whether to continue or exit.
}
如果你真的只想为你的抽象基类做这个
public abstract BaseClass
{
private List<Exception> unhandledExceptions = new List<Exception>();
protected BaseClass()
{
AppDomain.CurrentDomain.UnhandledException += UnhandledException;
}
private void UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = e.ExceptionObject as Exception;
if (ex != null)
this.UnhandledExceptions.Add(ex);
}
public List<Exception> LastKnownExceptions
{
get { return this.unhandledExceptions; }
}
我对捕获异常有类似的需求,但使用了特定的实现(即不是抽象类)来封装错误处理。
请注意,对于任何预期的异常(params Type[] catchableExceptionTypes),这需要一个参数,当然你可以修改以适应你自己的需求。
public class ExceptionHandler
{
// exposes the last caught exception
public Exception CaughtException { get; private set; }
// allows a quick check to see if an exception was caught
// e.g. if (ExceptionHandler.HasCaughtException) {... do something...}
public bool HasCaughtException { get; private set; }
// perform an action and catch any expected exceptions
public void TryAction(Action action, params Type[] catchableExceptionTypes)
{
Reset();
try
{
action();
}
catch (Exception exception)
{
if (ExceptionIsCatchable(exception, catchableExceptionTypes))
{
return;
}
throw;
}
}
// perform a function and catch any expected exceptions
// if an exception is caught, this returns null
public T TryFunction<T>(Func<T> function, params Type[] catchableExceptionTypes) where T : class
{
Reset();
try
{
return function();
}
catch (Exception exception)
{
if (ExceptionIsCatchable(exception, catchableExceptionTypes))
{
return null;
}
throw;
}
}
bool ExceptionIsCatchable(Exception caughtException, params Type[] catchableExceptionTypes)
{
for (var i = 0; i < catchableExceptionTypes.Length; i++)
{
var catchableExceptionType = catchableExceptionTypes[i];
if (!IsAssignableFrom(caughtException, catchableExceptionType)) continue;
CaughtException = caughtException;
HasCaughtException = true;
return true;
}
return false;
}
static bool IsAssignableFrom(Exception exception, Type type)
{
if (exception.GetType() == type) return true;
var baseType = exception.GetType().BaseType;
while (baseType != null)
{
if (baseType == type) return true;
baseType = baseType.BaseType;
}
return false;
}
void Reset()
{
CaughtException = null;
HasCaughtException = false;
}
}