2014-07-25 126 views
4

如何在派生類型的集合項上設置驗證器?FluentValidation派生類型的SetCollectionValidator

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()); 

回答

3

可以使用的規則條件的包裹,以驗證集合,其中包含的對象不同的派生類型。

假設你有下一個類層次結構:

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()); 
    } 
} 
2

我創造了這個使應付這種情況下簡單:

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>()); 
    } 

    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>(); 
    } 
} 

使用中:

RuleFor(v => v.BaseClasses).SetCollectionValidator(new CommonBaseClassValidator()); 

這樣我就可以重新使用派生類的現有驗證器,我可能會在其他地方使用它們,並且無需麻煩地映射它們。