gpt4 book ai didi

c# - 将对象的一个​​元素传递给 FluentValidation SetValidator 的构造函数

转载 作者:可可西里 更新时间:2023-11-01 08:33:35 28 4
gpt4 key购买 nike

我正在使用 FluentValidation 来验证对象内部的集合,将集合项的元素与父对象的元素进行比较。

目标输出是接收集合中每个失败项的 ValidationFailures,而不仅仅是集合失败。

我有一份软件订单,其中包含软件项目列表。如果订单是遗留系统,则所选软件只能是遗留软件,反之,非遗留系统只能有非遗留软件。

我的模型:

public class SoftwareOrder
{
public bool IsLegacySystem;
public List<SoftwareItem> Software;
(...other fields...)
}
public class SoftwareItem
{
public bool Selected;
public bool IsLegacySoftware;
public int SoftwareId;
}

验证器:

public class SoftwareOrderValidator : AbstractValidator<SoftwareOrder>
{
public SoftwareOrderValidator()
{
(..other rules..)

When(order => order.IsLegacySystem == true, () =>
{
RuleForEach(order => order.SoftwareItem)
.SetValidator(new SoftwareItemValidator(true));
});
When(order => order.IsLegacySystem == false, () =>
{
RuleForEach(order => order.SoftwareItem)
.SetValidator(new SoftwareItemValidator(false));
});
}
}
public class SoftwareItemValidator : AbstractValidator<SoftwareItem>
{
public SoftwareItemValidator(bool IsLegacySystem)
{
When(item => item.Selected, () =>
{
RuleFor(item => item.IsLegacySoftware)
.Equal(IsLegacySystem).WithMessage("Software is incompatible with system");
});
}
}

如您所见,我通过为每个条件设置一个 When 来完成此操作。它有效,但它违反了 DRY,并且在不止两个条件的情况下使用是不切实际的。

理想情况下,我希望有一个 RuleForEach 可以做到这一点,不需要什么时候,比如:

RuleForEach(order => order.SoftwareItem)
.SetValidator(new SoftwareItemValidator(order => order.IsLegacySystem));

但我看不出有什么方法可以将 IsLegacySystem 传递给该构造函数。

最佳答案

2 年后,在看到这个未回答的问题获得了多少浏览量后,我决定再试一次。我想出了两个答案。

第一个答案是问题中描述的情况的最佳解决方案。

public class SoftwareOrderValidator : AbstractValidator<SoftwareOrder>
{
public SoftwareOrderValidator()
{
RuleForEach(order => order.SoftwareItem)
.Must(BeCompatibleWithSystem)
.WithMessage("Software is incompatible with system");

}

private bool BeCompatibleWithSystem(SoftwareOrder order, SoftwareItem item)
{
if (item.Selected)
return (order.IsLegacySystem == item.IsLegacySoftware);
else
return true;
}
}

Predicate Validators (a.k.a Must) 可以将对象和属性作为参数。这使您可以直接与 IsLegacySystem 或父对象的任何其他属性进行比较。

您可能不应该使用第二个答案。如果您认为需要将参数传递给 AbstractValidator 的构造函数,我鼓励您重新评估并找到不同的方法。有了这个警告,这是一种实现它的方法。

基本上,使用虚拟的 Must() 允许您在构造函数之外的 lambda 之外设置变量。然后您可以使用它将该值放入第二个验证器的构造函数中。

public class SoftwareOrderValidator : AbstractValidator<SoftwareOrder>
{
private bool _isLegacySystem;

public SoftwareOrderValidator()
{
RuleFor(order => order.IsLegacySystem)
.Must(SetUpSoftwareItemValidatorConstructorArg);

RuleForEach(order => order.SoftwareItem)
.SetValidator(new SoftwareItemValidator(_isLegacySystem));

}

private bool SetUpSoftwareItemValidatorConstructorArg(bool isLegacySystem)
{
_isLegacySystem = isLegacySystem;
return true;
}
}
public class SoftwareItemValidator : AbstractValidator<SoftwareItem>
{
public SoftwareItemValidator(bool IsLegacySystem)
{
When(item => item.Selected, () =>
{
RuleFor(item => item.IsLegacySoftware)
.Equal(IsLegacySystem).WithMessage("Software is incompatible with system");
});
}
}

关于c# - 将对象的一个​​元素传递给 FluentValidation SetValidator 的构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18664943/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com