首页 > 解决方案 > 类定义错误

问题描述

我想将我的错误分开,因为定义它们时有很多细节,这是一个错误模型:

public interface IErrorResult : IResult
{
    string Code { get; set; }
    string Message { get; set; }
    string Description { get; set; }
}

一个这样的例子:

public static class CheckoutError
{
    public static ErrorResult Purchased = new ErrorResult
    {
        Code = CheckoutErrors.AlreadyPurchased,
        Message = "License already bought.",
        Description = "A license for this account already exists."
    };

    public static ErrorResult Expired = new ErrorResult
    {
        Code = CheckoutErrors.Expired,
        Message = "Checkout Expired.",
        Description = "The checkout session expired, please try again."
    };

    public static ErrorResult NotFound = new ErrorResult
    {
        Code = CheckoutErrors.NotFound,
        Message = "Checkout not found.",
        Description = "This checkout session doesn't exist."
    };
}

我将这些单独定义的原因是它们可以重复使用,并且在必要时更容易修改它们。

这些错误在调用业务逻辑之前调用的验证器中使用,如下所示:

public class CheckoutValidator : ICheckoutValidator
{
    private readonly ICheckoutSessionRepository _checkoutSessionRepository;
    private readonly ILicenseValidator _licenseValidator;

    public CheckoutValidator(ICheckoutSessionRepository checkoutSessionRepository)
    {
        _checkoutSessionRepository = checkoutSessionRepository;
    }

    public async Task<IResult> ValidateSession(string userId)
    {
        var checkout = await _checkoutSessionRepository.GetBySession(userId);
        if (checkout == default(CheckoutSession) || checkout.User.AspNetUserId != userId)
        {
            var error = CheckoutError.NotFound;
            error.Status = ResultStatusEnum.NotFound;
            return error;
        }

        if (DateTime.Now > checkout.Expires)
        {
            var error = CheckoutError.Expired;
            error.Status = ResultStatusEnum.Invalid;
            return error;
        }

        return new Result
        {
            Status = ResultStatusEnum.Valid
        };
    }
}

我想知道,这种设计是常用的吗?我觉得它可以变得更简单,我已经完成了复杂的事情,但我正在努力寻找可以改变和改进的地方和哪些部分

标签: c#validationerror-handling

解决方案


我见过并使用过一些错误模型

简单成功/失败的替代方案

  1. bool Try*(out T result)- 图案
  2. 返回空
  3. 返回一个Maybe Monad

提供有关故障的附加信息的替代方案

  1. 抛出异常
  2. 返回一个结果对象

每个选项都有各种缺点/优点。关于异常与结果对象,一种观点是异常应该用于“异常”,即意外和罕见的错误,而结果对象应该用于常见和/或预期的错误。内存不足可能是前者的示例,而无效用户可能是预期错误的示例。

关于您的具体实施,有几个问题:

  1. 您的结果对象不是通用的,那么如果您需要返回一些任意对象,您会怎么做?似乎调用者必须进行一些强制转换才能从返回的对象中获取任何有用的东西,这通常会导致代码混乱。我建议将结果对象设为通用,查看此实现以获取灵感
  2. 您有错误是静态(即全局)对象,但有公共设置器。这是一个很大的禁忌,很容易导致奇怪的行为。例如,考虑是否从多个线程访问错误对象(属性可能随时更改),或者如果您忘记设置其中一个属性(它将保留最后一个值)。要么使对象不可变,要么将它们更改为返回新对象的方法。

推荐阅读