【问题标题】:Validation is throwing "Unable to cast object of type 'BaseModel' to type 'DerivedModel'."验证抛出“无法将'BaseModel'类型的对象转换为'DerivedModel'类型。”
【发布时间】:2019-03-28 01:30:18
【问题描述】:

当我尝试编写验证器时,我发现 FluentValidation (v8.2.0) 存在一个奇怪的问题:

System.InvalidCastException H结果=0x80004002 消息=无法将“BaseModel”类型的对象转换为“DerivedModel”类型。 来源=FluentValidation 堆栈跟踪: 在 FluentValidation.Internal.ConditionBuilder1.<>c__DisplayClass2_0.<When>g__Condition|0(ValidationContext context) in C:\Projects\FluentValidation\src\FluentValidation\Internal\ConditionBuilder.cs:line 62 at FluentValidation.Internal.PropertyRule.<Validate>d__67.MoveNext() in C:\Projects\FluentValidation\src\FluentValidation\Internal\PropertyRule.cs:line 270 at System.Linq.Enumerable.SelectManySingleSelectorIterator2.MoveNext() 在 System.Linq.Enumerable.WhereEnumerableIterator1.MoveNext() at FluentValidation.AbstractValidator1.Validate(ValidationContext`1 context) 在 C:\Projects\FluentValidation\src\FluentValidation\AbstractValidator.cs:line 115 在 C:\Users\john\Documents\Visual Studio 2017\Projects\TestApp\TestApp\Program.cs:line 76 中的 TestApp.Program.d__4.MoveNext() 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 TestApp.Program.(String[] args)

我的模型和验证器:

public class BaseModel
{
    public string Name { get; set; }
    public bool IsAlive { get; set; }
}

public class DerivedModel : BaseModel
{
    public int Age { get; set; }
}

public class BaseModelValidator : AbstractValidator<BaseModel>
{
    public BaseModelValidator()
    {
        RuleFor(o => o.Name).Length(1, 20);
    }
}

public class DerivedModelValidator : AbstractValidator<DerivedModel>
{
    public DerivedModelValidator(BaseModelValidator baseValidator)
    {
        foreach (var rule in baseValidator)
        {
            AddRule(rule);
        }

        RuleFor(o => o.Age).GreaterThanOrEqualTo(0);
    }
}

我正在使用的代码:

var baseModelValidator = new BaseModelValidator();
var derivedModelValidator = new DerivedModelValidator(baseModelValidator);

var baseModel = new BaseModel
{
    IsAlive = true,
    Name = "test2"
};
Console.WriteLine(baseModelValidator.Validate(baseModel).IsValid);

如您所见,我使用BaseModelValidator 来验证BaseModel,而这个引用DerivedModel 没有。

有趣的是,如果我删除 var derivedModelValidator = new DerivedModelValidator(baseModelValidator); 行,它可以正常工作。

是什么导致了这个异常以及如何解决它?

【问题讨论】:

    标签: c# fluentvalidation


    【解决方案1】:

    实际上,我偶尔会在我的 Web 应用程序中看到这个问题 - 99% 的时间它都可以正常工作,但有时我会遇到这个问题。我reached out 致作者或 FluentValidation 的 Jeremy Skinner,他解释了正在发生的事情:

    规则本质上与定义它们的验证器相关联。它们并非旨在从一个验证器复制到另一个验证器。它们本质上与定义它们的验证器以及它们所针对的类型相关联。

    每个条件块都有一个与之关联的唯一 ID(它允许缓存条件的结果,因此它只执行一次,而不是针对其中的每个规则执行)。当您将规则从一个验证器复制到另一个验证器时,条件也会随之出现。

    简而言之:您不能在验证器之间共享单个规则对象。

    有问题的代码是来自DerivedModelValidator的这段代码:

    foreach (var rule in baseValidator)
    {
        AddRule(rule);
    }
    

    Jeremy 为这个问题提供了两种不同的解决方案:

    1。从包含共享规则的公共基础验证器类派生两个验证器类:

    public abstract class CommonModelValidator<T> : AbstractValidator<T> where T : BaseModel
    {
        protected CommonModelValidator()
        {
            RuleFor(o => o.Name).Length(1, 20);
        }
    }
    
    public class BaseModelValidator : CommonModelValidator<BaseModel>
    {
    }
    
    public class DerivedModelValidator : CommonModelValidator<DerivedModel>
    {
        public DerivedModelValidator(BaseModelValidator baseValidator) 
            : base()
        {
            RuleFor(o => o.Age).GreaterThanOrEqualTo(0);
        }
    }
    

    2。从BaseModelValidator 使用SetValidator 编写DerivedModelValidator

    public class BaseModelValidator : AbstractValidator<BaseModel>
    {
        public BaseModelValidator()
        {
            RuleFor(o => o.Name).Length(1, 20);
        }
    }
    
    public class DerivedModelValidator : AbstractValidator<DerivedModel>
    {
        public DerivedModelValidator(BaseModelValidator baseValidator)
        {
            RuleFor(o => o).SetValidator(baseValidator);
            RuleFor(o => o.Age).GreaterThanOrEqualTo(0);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-06
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-19
      相关资源
      最近更新 更多