简体   繁体   中英

Adding Global Try Catch Exception

I implemented a Global Try Catch mechanism in this way. I added a seperate class called HandleException.cs

public static class HandleException
{
    public static void GlobalTryCatch(Action action, object obj)
    {
        try
        {
            action.Invoke();
        }
        catch(SqlException ex)
        {
            obj.GetType().GetProperty("Success").SetValue(obj.GetType(), false);
            obj.GetType().GetProperty("FailureMessage").SetValue(obj.GetType(), ex);
        }
        catch(Exception ex)
        {
            obj.GetType().GetProperty("Success").SetValue(obj.GetType(), false);
            obj.GetType().GetProperty("FailureMessage").SetValue(obj.GetType(), ex);
        }
    }
}

And this way calling it.

public override Result<int> Update(UserProfile data)
    {

        var result = new Result<int> { Success = false };

        HandleException.GlobalTryCatch(() =>
                                           {
                                               SqlParameter[] sParam =
                                                   {
                                                       DbHelper.CreateParameter("@UserId", ParameterDirection.Input, SqlDbType.Int, data.UserId),
                                                       DbHelper.CreateParameter("@FirstName", ParameterDirection.Input, SqlDbType.VarChar,100, data.FirstName),
                                                       DbHelper.CreateParameter("@LastName", ParameterDirection.Input, SqlDbType.VarChar,100, data.LastName),
                                                       DbHelper.CreateParameter("@Gender", ParameterDirection.Input, SqlDbType.Char,1, data.Gender),
                                                       DbHelper.CreateParameter("@Dob", ParameterDirection.Input, SqlDbType.Date, data.DateOfBirth),
                                                       DbHelper.CreateParameter("@ImageUrl", ParameterDirection.Input, SqlDbType.VarChar, 150, data.ImageUrl),
                                                   };

                                               using(var sql = new DbHelper())
                                               {
                                                   sql.ExecuteSpReturnScalar("UserProfile_Update", sParam);
                                               }
                                               result.Success = true;
                                           }, result);
        return result;

}

My questions are

  1. Is this a standard practice for implementing global try catch mechanism or Is there any other standard way to implement this?
  2. I had used this in GlobalTryCatch method. Whether this way we can assign value to a property by passing Generic Object?

    obj.GetType().GetProperty("Success").SetValue(obj.GetType(), false);

Is this a standard practice for implementing global try catch mechanism

No, it is not. Moreover, mentioned "global try-catch mechanism" is a bad practice. Wrapping every method in try-catch assumes, that you definitely know, what to do after any exception has been thrown. In the real world this is false. Look at this sample:

void AnyMethod()
{
    var result = // ...

    HandleException.GlobalTryCatch(() => { /* action 1 */}, result);

    // should we check result to continue?
    // if so, this is a typical error-code approach, which annihilates 
    // all preferences, provided by .NET exceptions;
    // if we shouldn't check it, what would be the behavior of our code,
    // if the state is broken after action 1? 

    HandleException.GlobalTryCatch(() => { /* action 2 */}, result);

    // the same questions

    HandleException.GlobalTryCatch(() => { /* action 3 */}, result);
}

Similar approach from time-to-time being used to log exceptions (due to absence of out-of-box aspects inmplementation in .NET):

void Execute(Action action)
{
    try
    {
        action();
    }
    catch (Exception e)
    {
        Logger.Log(e);
        throw;
    }
}

T Execute<T>(Func<T> func)
{
    try
    {
        return func();
    }
    catch (Exception e)
    {
        Logger.Log(e);
        throw;
    }
}

but:
1) it logs full exception information (eg, your code is missing stack trace and inner exceptions);
2) it re-throws the same exception (this allows to use all benefits from .NET exceptions);
3) it wraps only limited number of top-level methods, not every method.

Whether this way we can assign value to a property by passing Generic Object?

You could do something like this:

interface IActionResult
{
    bool Success { get; set; }
    string FailureMessage { get; set; }
}

public static void GlobalTryCatch<T>(Action action, T obj)
    where T : IActionResult
{
    // ...
}

but this doesn't cancel answer on your 1st question.

You can use http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx (or http://msdn.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception.aspx for WPF applications).

Generally it is not a bad idea to do something meaningful during this events - logging the exceptions (or sending them to admin) and displaying a message to user (something like "Sorry, error occurred, contact your admin please").

But as others said - you should handle the excpetions in your methods where you can do something meaningful with them, not on global level. And even if it is not mandatory in c#, it's a good idea to add to comments that your method can throw some kind of exception on certain circumstances.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM