如何在派生类型的集合项上设置验证器?
class BaseClass
{
}
class DerivedClass : BaseClass
{
}
class SomeClass
{
public IEnumerable<BaseClass> BaseClasses { get; set; }
}
class DerivedClassValidator : AbstractValidator<DerivedClass>
{
}
class SomeClassValidator : AbstractValidator<SomeClass>
{
public SomeClassValidator()
{
RuleFor(x => x.BaseClasses).????.SetCollectionValidator(new DerivedClassValidator);
}
}
只是想知道......
有没有办法将它投射到像
这样的特定类型RuleFor(x => x.SomeCollection).CastTo(typeof(SomeDerivedType)).SetCollectionValidator(new SomeDerivedValidator());
答案 0 :(得分:4)
您可以使用条件包装规则来验证集合,其中包含不同派生类型的对象。
假设您有下一个类层次结构:
public class BaseClass
{
public string Name { get; set; }
}
public class DerivedClassOne : BaseClass
{
public int Count { get; set; }
}
public class DerivedClassTwo : BaseClass
{
public double Price { get; set; }
}
包含BaseClass
个对象集合的容器类:
public class ContainerClass
{
public List<BaseClass> Collection { get; set; }
}
主要思想是创建一个验证器类,负责所有类层次结构验证:
public class CommonBaseClassValidator : AbstractValidator<BaseClass>
{
public CommonBaseClassValidator()
{
//common rule for all BaseClass types
RuleFor(x => x.Name)
.NotEmpty();
// special rules for base type
When(model => model.GetType() == typeof (BaseClass), () =>
{
RuleFor(x => x.Name)
.Length(0, 10);
// add rules here
});
//special rules for derived types
When(model => model.GetType() == typeof(DerivedClassOne), () =>
{
RuleFor(model => ((DerivedClassOne) model).Count)
.ExclusiveBetween(1, 9);
// add rules here
});
When(model => model.GetType() == typeof(DerivedClassTwo), () =>
{
RuleFor(model => ((DerivedClassTwo) model).Price)
.GreaterThan(1000);
// add rules here
});
}
}
将此类注册为集合项验证器:
public class ContainerValidator : AbstractValidator<ContainerClass>
{
public ContainerValidator()
{
RuleFor(model => model.Collection)
.SetCollectionValidator(new CommonBaseClassValidator());
}
}
答案 1 :(得分:3)
我创建了这个,以便更简单地处理这个场景:
public class DerivedValidatorBase<TBase> : AbstractValidator<TBase>
{
public void MapDerivedValidator<TType, TValidatorType>()
where TValidatorType : IEnumerable<IValidationRule>, IValidator<TType>, new()
where TType: TBase
{
When(t => t.GetType() == typeof(TType), () => AddDerivedRules<TValidatorType>());
}
public void MapDerivedValidator<TType, TValidatorType>(TValidatorType validator)
where TValidatorType : IEnumerable<IValidationRule>, IValidator<TType>
where TType: TBase
{
When(t => t.GetType() == typeof(TType), () => AddDerivedRules<TValidatorType>(validator));
}
private void AddDerivedRules<T>(T validator)
where T : IEnumerable<IValidationRule>
{
foreach (var rule in validator)
{
this.AddRule(rule);
}
}
private void AddDerivedRules<T>()
where T : IEnumerable<IValidationRule>, new()
{
IEnumerable<IValidationRule> validator = new T();
foreach (var rule in validator)
{
this.AddRule(rule);
}
}
}
然后我只创建一个基本验证器类:
public class CommonBaseClassValidator : DerivedValidatorBase<BaseClass>
{
public CommonBaseClassValidator()
{
MapDerivedValidator<DerivedClass, DerivedClassValidator>();
}
}
或使用依赖注入时:
public class CommonBaseClassValidator : DerivedValidatorBase<BaseClass>
{
public CommonBaseClassValidator(DerivedClassValidator validator)
{
MapDerivedValidator<DerivedClass, DerivedClassValidator>(validator);
}
}
使用中:
RuleFor(v => v.BaseClasses).SetCollectionValidator(new CommonBaseClassValidator());
这样我就可以为派生类重用现有的验证器,我可能会在其他地方使用它们,并毫不费力地映射它们。
答案 2 :(得分:1)
6年后:请查看this link。
按照说明进行操作,并在底部显示:
此方法也适用于集合,集合中的每个元素可能是不同的子类。
答案 3 :(得分:0)
我想添加一些帮助他人的东西。我受到Evgeny Levin解决方案的启发。
我更倾向于分隔每个验证器,而不是When
中的规则列表。
public class CommonBaseClassValidator : AbstractValidator<BaseClass>
{
public CommonBaseClassValidator()
{
//All rules for shared properties
RuleFor(x => x.Name)
.NotEmpty();
RuleFor(x => x.Name)
.Length(0, 10);
//special rules for derived types
When(model => model.GetType() == typeof(DerivedClassOne),
() => RuleFor(entity => entity as DerivedClassOne)
.SetValidator(new DerivedClassOneValidator()));
When(model => model.GetType() == typeof(DerivedClassTwo),
() => RuleFor(entity => entity as DerivedClassTwo)
.SetValidator(new DerivedClassTwoValidator()));
}
}
希望有帮助。