【发布时间】:2015-04-29 14:35:51
【问题描述】:
在 FluentValidation 中是否有扩展或其他方式来根据正在验证的属性的类型/值来推迟选择子验证器?
我的情况是我有一个要验证的通知类。这个类有一个 Payload 属性,它可以是许多 Payload 类型之一,例如SmsPayload、EmailPayload 等。这些 Payload 子类中的每一个都有自己关联的验证器,例如分别是 SmsPayloadValidator 和 EmailPayloadValidator。除了上述之外,核心库中没有对各个通知提供程序的引用。从本质上讲,这意味着我可以根据需要添加提供程序并使用 IoC 连接所有内容。
考虑以下类:
public class Notification
{
public Payload Payload { get; set; }
public IEnumerable<string> Details { get; set; }
}
public abstract class Payload
{
public string Message { get; set; }
public abstract string Type { get; }
}
public class SmsPayload : Payload
{
public List<string> Numbers { get; set; }
public string Region { get; set; }
public string Provider { get; set; }
}
有一个Notification验证器和SmsPayloadValidator如下:
public class NotificationValidator : AbstractValidator<Notification>
{
public NotificationValidator(IValidator<Payload> payloadValidator)
{
RuleFor(notification => notification.Payload).NotNull().WithMessage("Payload cannot be null.");
RuleFor(notification => notification.Payload).SetValidator(payloadValidator);
}
}
public class SmsPayloadValidator : AbstractValidator<SmsPayload>
{
public SmsPayloadValidator()
{
RuleFor(payload => payload.Provider)
.Must(s => !string.IsNullOrEmpty(s))
.WithMessage("Provider is required.");
RuleFor(payload => payload.Numbers)
.Must(list => list != null && list.Any())
.WithMessage("Sms has no phone numbers specified.");
RuleFor(payload => payload.Region)
.Must(s => !string.IsNullOrEmpty(s))
.WithMessage("Region is required.");
}
}
正如我提到的 NotificationValidator 所在的程序集不引用各个 Payload 验证器类所在的程序集。所有的接线都由 Ioc(本项目的 Simple-Injector)负责。
基本上我想做如下的事情 - 首先在 Simple Injector 中注册一个工厂回调:
container.Register<Func<Payload, IValidator<Payload>>>(() => (payload =>
{
if (payload.GetType() == typeof(SmsPayload))
{
return container.GetInstance<ISmsPayloadValidator>();
}
else if (payload.GetType() == typeof(EmailPayload))
{
return container.GetInstance<IEmailPayloadValidator>();
}
else
{
//something else;
}
}));
这样我就可以选择合适的验证器如下:
public class NotificationValidator : AbstractValidator<Notification>
{
public NotificationValidator(Func<Payload, IValidator<Payload>> factory)
{
RuleFor(notification => notification.Payload).NotNull().WithMessage("Payload cannot be null.");
RuleFor(notification => notification.Payload).SetValidator(payload => factory.Invoke(payload));
}
}
有什么建议吗?还是有更好的方法来做我提议的事情? 如果没有,我将 fork FluentValidation 存储库并提交 PR。
【问题讨论】:
标签: .net validation expression-trees fluentvalidation simple-injector