C# 使用不同的方法和参数捕获基类中的派生类异常

C# 使用不同的方法和参数捕获基类中的派生类异常,c#,asp.net-mvc,C#,Asp.net Mvc,我试着做一些类似于基本“异常处理程序”的东西。因此,当派生类中的任何方法(具有任意数量的参数)被调用时,该基类将尝试捕获异常。我不擅长用文字来描述这一点,所以下面是一个场景: public abstract BaseClass { Exception _ex; public Exception LastKnownException { get { return this._ex; } }

我试着做一些类似于基本“异常处理程序”的东西。因此,当派生类中的任何方法(具有任意数量的参数)被调用时,该基类将尝试捕获异常。我不擅长用文字来描述这一点,所以下面是一个场景:

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();
        }       
    }
}
公共抽象基类
{
例外情况;
公共异常LastKnownException
{
得到
{
把这个还给我;
}
}
//...
//当派生类中发生一些随机异常时,我在这里如何分配上述属性的值?
//...
//我能得到的最接近的。。。
公共无效运行方法(操作方法)
{
尝试
{
方法调用();
}
捕获(例外情况除外)
{
这个;
}
}
}
公共类派生类:基类
{   
public void或andommethod(int可以是任意类型、布尔值和不确定的数量)
{
布尔结果=假;
var someObject=new OtherClass(可以是任何类型的、其中的out和indefinitenenumberof);

某个对象。DoInternalWork(结果);//< P>我认为你应该考虑使用事件

每当发生未处理的异常时,将引发此事件

由于您的代码不会因异常的可能性而变得杂乱无章,因此您的代码的可读性会更好。此外,如果派生类预期会出现异常,那么它将为它们提供捕获异常的机会,而不会干扰您的自动异常捕获器

您的设计是这样的,如果有人调用派生类的多个函数,然后检查是否存在异常,调用方将不知道是哪个函数导致了异常。我假设调用方对哪个函数导致了异常并不感兴趣。如果您只想记录异常,直到有人调查他们

如果是这样的话,考虑做如下的事情:

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; }
}
公共抽象基类
{
私有列表未处理异常=新列表();
受保护基类()
{
AppDomain.CurrentDomain.UnhandledException+=UnhandledException;
}
私有void UnhandledException(对象发送方,UnhandledExceptionEventArgs e)
{
var ex=e.ExceptionObject作为异常;
如果(ex!=null)
this.UnhandledExceptions.Add(ex);
}
公共列表LastKnownExceptions
{
获取{返回this.unhandledExceptions;}
}

<>代码>我想你应该考虑使用事件

每当发生未处理的异常时,将引发此事件

由于您的代码不会因异常的可能性而变得杂乱无章,因此您的代码的可读性会更好。此外,如果派生类预期会出现异常,那么它将为它们提供捕获异常的机会,而不会干扰您的自动异常捕获器

您的设计是这样的,如果有人调用派生类的多个函数,然后检查是否存在异常,调用方将不知道是哪个函数导致了异常。我假设调用方对哪个函数导致了异常并不感兴趣。如果您只想记录异常,直到有人调查他们

如果是这样的话,考虑做如下的事情:

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; }
}
公共抽象基类
{
私有列表未处理异常=新列表();
受保护基类()
{
AppDomain.CurrentDomain.UnhandledException+=UnhandledException;
}
私有void UnhandledException(对象发送方,UnhandledExceptionEventArgs e)
{
var ex=e.ExceptionObject作为异常;
如果(ex!=null)
this.UnhandledExceptions.Add(ex);
}
公共列表LastKnownExceptions
{
获取{返回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;
    }
}
公共类异常处理程序
{
//公开上次捕获的异常
公共异常CaughtException{get;private set;}
//允许快速检查以查看是否捕获了异常
//例如,如果(ExceptionHandler.HasCaughtException){…做点什么…}
public bool HasCaughtException{get;private set;}
//执行操作并捕获任何预期的异常
public void TryAction(Action Action,参数类型[]可捕获异常类型)
{
重置();
尝试
{
动作();
}
捕获(异常)
{
if(异常可捕获(异常、可捕获异常类型))
{
返回;
}
投掷;
}
}
//执行函数并捕获任何预期的异常
//如果捕获到异常,则返回null
公共T TryFunction(Func函数,参数类型[]可捕获异常类型),其中T:class
{
重置();
尝试
{
返回函数();
}
捕获(异常)
{
if(异常可捕获(异常、可捕获异常类型))
{
返回null;
}
投掷;
}
}
bool ExceptionScachable(Exception caughtException,参数类型[]可捕获ExceptionTypes)
{
对于(var i=0;i