1

我有一个看起来像这样的验证器

public class ImageValidator : AbstractValidator<Image>
{
    public ImageValidator()
    {
        RuleFor(e => e.Name).NotEmpty().Length(1, 255).WithMessage("Name must be between 1 and 255 chars");

        RuleFor(e => e.Data).NotNull().WithMessage("Image must have data").When(e => e.Id == 0);

        RuleFor(e => e.Height).GreaterThan(0).WithMessage("Image must have a height");

        RuleFor(e => e.Width).GreaterThan(0).WithMessage("Image must have a width");
    }
}

现在我的单元测试失败了,因为高度和宽度是根据数据中的值填充的。

Data 包含一个字节数组,它创建一个位图图像。如果 Data 不为空(并且 Id 等于 0,因此它是一个新图像),我可以创建一个位图图像并获取高度和宽度值。更新后,Height 和 Width 已经被填充,Data 可能为空,因为它已经存储在数据库中。

如果数据的验证规则在我的验证器中为真,我是否可以填充高度和宽度的值?

在我有支票之前

if (myObject.Data == null) throw new ApplicationException(...

但我认为这是一个验证规则,应该在验证器中,还是我只需要拆分规则?

4

2 回答 2

2

感谢约翰·彼得斯(John Peters)为我指明了正确的方向,但这是我最终按照建议所做的。

首先,我创建了一个新的验证器来测试字节数组是否有效。此验证器接受将对象和位图作为输入的操作。仅当验证器有效时才调用此操作。

public class IsImageValidator<T> : PropertyValidator
{
    private Action<T, Bitmap> _action;

    public IsImageValidator(Action<T, Bitmap> action) : base("Not valid image data")
    {
        _action = action;
    }

    protected override bool IsValid(PropertyValidatorContext context)
    {
        var isNull = context.PropertyValue == null;

        if (isNull)
        {
            return false;
        }

        try
        {
            // we need to determine the height and width of the image
            using (var ms = new System.IO.MemoryStream((byte[])context.PropertyValue))
            {
                using (var bitmap = new System.Drawing.Bitmap(ms))
                {
                    // valid image, so call action
                    _action((T)context.Instance, bitmap);                        
                }
            }

        }
        catch (Exception e)
        {
            return false;
        }

        return true;
    }
}

为了更容易调用这个验证器,我创建了一个简单的扩展,就像这样

public static class SimpleValidationExtensions
{
    public static IRuleBuilderOptions<T, TProperty> IsImage<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, Action<T, Bitmap> action)
    {
        return ruleBuilder.SetValidator(new IsImageValidator<T>(action));
    }
}

现在我可以在我的 ImageValidator 中调用验证器方法,所以我的 ImageValidator 现在看起来像这样。如您所见,我现在可以设置高度和宽度属性。

public ImageValidator()
{
    RuleFor(e => e.Name).NotEmpty().Length(1, 255).WithMessage("Name must be between 1 and 255 chars");

    RuleFor(e => e.Data).IsImage((e, bitmap) =>
    {
        e.Height = bitmap.Height;
        e.Width = bitmap.Width;
    }).WithMessage("Image data is not valid").When(e => e.Id == 0);

    RuleFor(e => e.Height).GreaterThan(0).WithMessage("Image must have a height");

    RuleFor(e => e.Width).GreaterThan(0).WithMessage("Image must have a width");
}
于 2015-02-18T10:37:23.037 回答
2

当前代码如下所示,注意 .NotNull() 流畅接口作用于 RuleFor 的结果。

  RuleFor(e => e.Data)
 .NotNull()
 .WithMessage("Image must have data")
 .When(e => e.Id == 0);

假设你可以这样做:

var rf = RuleFor(e => e.Data)
.CheckNull(p=>{
   if(p){ 
       // this is the true branch when data is null don't set height/width}
       rf.WithMessage("Image must have data");
       .When(e=>e.id==0); 
   else{  
       //data is not null set the height and with. 
        rf(e => e.Height).GreaterThan(0).WithMessage("Image must have a height");
        rf(e => e.Width).GreaterThan(0).WithMessage("Image must have a width");
   });

为了让您能够做到这一点,新的 CheckNull 例程必须能够采用与今天的 .NotNull() 方法相同的类型。

于 2015-02-17T18:57:06.507 回答