具有动态描述的Exception Helper工厂

时间:2019-01-07 14:10:26

标签: c# exception-handling

如何创建使用字符串模板为助手的调用者提供动态字符串元素的ExceptionHelper类?

以下是我目前的操作方式示例:

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
        try
        {
            throw ExceptionHelper.CreateTechnicalException(1001);
        }
        catch (TechnicalException ex)when (ex.ErrorSeverity > Severity.Warning)
        {
            Console.WriteLine($"{ex.ErrorCode} {ex.Message}");
        }

        try
        {
            throw ExceptionHelper.CreateTechnicalException(2002);
        }
        catch (TechnicalException ex)when (ex.ErrorSeverity > Severity.Warning)
        {
            Console.WriteLine($"{ex.ErrorCode} {ex.Message.Replace("$id$", "1").Replace("$type$", "myType")}");
        }
    }
}

public static class ExceptionHelper
{
    private static Dictionary<int, string> TechnicalErrorDictionary = new Dictionary<int, string>{{1001, "User with id $id$ does not exist"}, {1002, "Created user with id $id$"}, {2002, "User with id $id$ with type $type$ is invalid"}, {3003, "Unexpected server error"}, {4001, "Some text with $param1$ and another $param2$ included on $param3$"}};
    /// <exception cref = "KeyNotFoundException">the errorCode did not exist in dictionary</exception>
    public static TechnicalException CreateTechnicalException(int errorCode)
    {
        return new TechnicalException(errorCode, TechnicalErrorDictionary[errorCode]);
    }
}

public class TechnicalException : Exception
{
    public int ErrorCode
    {
        get;
    }

    public Severity ErrorSeverity
    {
        get;
    }

    public TechnicalException(int errorCode, string errorDescription): base (errorDescription)
    {
        ErrorCode = errorCode;
        ErrorSeverity = Severity.Error;
    }
}

public enum Severity
{
    Warning,
    Error
}

输出为:

> Hello World 
> 1001 User with id $id$ does not exist 
> 2002 User with id 1
> with type myType is invalid

是否有可能以更好的方式实现这一目标?

我觉得让每个使用此Helper类的开发人员在参数上进行字符串替换的想法似乎太多余了,这有点消除了使用Helper类来封装所有异常消息的想法。

我想首先为开发人员提供某种字典,他们可以通过errorCode选择异常,并且对于某些错误消息,将使用参数。

dotNetFiddler:https://dotnetfiddle.net/BEFS80

2 个答案:

答案 0 :(得分:3)

这是不一定要“正确”的方法之一,但是我可以看到您的方法逐渐成为维护问题,所有这些代码无处不在....

对于这样的事情,我绝对会使用Enum而不是原始的int错误代码-我不想尝试确定是应该抛出“ 9003”还是“ 9030”错误。如果您真的想那样做,可以使用Enum代替,而不是试图引导用户记住参数的魔术字符串,只需使用显式构造函数创建异常的子类即可:

public enum ExceptionCode
{
    IncorrectUser = 1001,
    InvalidPassword= 1002,
    RanOutOfBeer = 9999,
}

public enum Severity
{
    Warning,
    Error
}

public class TechnicalException : Exception
{
    public ExceptionCode ErrorCode
    {
        get;
    }

    public Severity ErrorSeverity
    {
        get;
    }

    public TechnicalException(ExceptionCode errorCode, string errorDescription) : base(errorDescription)
    {
        ErrorCode = errorCode;
        ErrorSeverity = Severity.Error;
    }
}

public class InvalidUserException : TechnicalException
{
    public InvalidUserException(string username, string password) 
        : base(ExceptionCode.IncorrectUser, $"User {username} with password {password} is invalid")
    {

    }
}

public class test
{
    public void throwit()
    {
        throw new InvalidUserException("bob", "abc123");
    }
}

如果执行此操作,则仍然可以捕获/列出/登录“ TechnicalExceptions”,但是代码更清晰,更简单且FAR也不那么脆弱。

答案 1 :(得分:1)

您可以使用字符串格式实现此目的,并添加占位符{0} {1}。例如:

    public static class ExceptionHelper
    {
        private static Dictionary<int, string> TechnicalErrorDictionary = new Dictionary<int, string> {{ 1001, "User with id {0} does not exist" }, { 1002, "Created user with id {0}" }, { 2002, "User with id {0} with type {1} is invalid" }, { 3003, "Unexpected server error" }, { 4001, "Some text with {0} and another {1} included on {2}" } };
        /// <exception cref = "KeyNotFoundException">the errorCode did not exist in dictionary</exception>
        public static TechnicalException CreateTechnicalException(int errorCode, params object[] para)
        {
            return new TechnicalException(errorCode, string.Format(TechnicalErrorDictionary[errorCode], para));
        }
    }

唯一的缺点是,开发人员必须准确知道每个错误代码的最低要求参数,否则可能会崩溃。