首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使用IValidatableObject?

如何使用IValidatableObject?
EN

Stack Overflow用户
提问于 2010-08-04 04:32:24
回答 7查看 135.6K关注 0票数 197

据我所知,IValidatableObject是用来验证一个对象的,它让人们可以相互比较属性。

我仍然希望使用属性来验证单个属性,但在某些情况下,我希望忽略某些属性上的失败。

在下面的案例中,我是否尝试错误地使用它?如果不是,我该如何实现呢?

代码语言:javascript
复制
public class ValidateMe : IValidatableObject
{
    [Required]
    public bool Enable { get; set; }

    [Range(1, 5)]
    public int Prop1 { get; set; }

    [Range(1, 5)]
    public int Prop2 { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (!this.Enable)
        {
            /* Return valid result here.
             * I don't care if Prop1 and Prop2 are out of range
             * if the whole object is not "enabled"
             */
        }
        else
        {
            /* Check if Prop1 and Prop2 meet their range requirements here
             * and return accordingly.
             */ 
        }
    }
}
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2010-08-04 06:14:45

首先,感谢@paper1337为我提供了正确的资源...我没有注册,所以我不能投票支持他,如果其他人读到了这篇文章,请投他的票。

下面是如何完成我想要做的事情。

可验证类:

代码语言:javascript
复制
public class ValidateMe : IValidatableObject
{
    [Required]
    public bool Enable { get; set; }

    [Range(1, 5)]
    public int Prop1 { get; set; }

    [Range(1, 5)]
    public int Prop2 { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var results = new List<ValidationResult>();
        if (this.Enable)
        {
            Validator.TryValidateProperty(this.Prop1,
                new ValidationContext(this, null, null) { MemberName = "Prop1" },
                results);
            Validator.TryValidateProperty(this.Prop2,
                new ValidationContext(this, null, null) { MemberName = "Prop2" },
                results);

            // some other random test
            if (this.Prop1 > this.Prop2)
            {
                results.Add(new ValidationResult("Prop1 must be larger than Prop2"));
            }
        }
        return results;
    }
}

如果验证失败,则使用Validator.TryValidateProperty()将添加到结果集合中。如果没有失败的验证,则不会向结果集合添加任何内容,这表示成功。

执行验证:

代码语言:javascript
复制
    public void DoValidation()
    {
        var toValidate = new ValidateMe()
        {
            Enable = true,
            Prop1 = 1,
            Prop2 = 2
        };

        bool validateAllProperties = false;

        var results = new List<ValidationResult>();

        bool isValid = Validator.TryValidateObject(
            toValidate,
            new ValidationContext(toValidate, null, null),
            results,
            validateAllProperties);
    }

要使此方法起作用,将validateAllProperties设置为false非常重要。当validateAllProperties为false时,仅检查具有[Required]属性的属性。这允许IValidatableObject.Validate()方法处理条件验证。

票数 189
EN

Stack Overflow用户

发布于 2014-03-26 13:47:29

我只想补充几点:

因为Validate()方法签名返回IEnumerable<>,所以该yield return可用于延迟生成结果-如果某些验证检查是IO密集型的或CPU密集型的,这是有益的。

代码语言:javascript
复制
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
    if (this.Enable)
    {
        // ...
        if (this.Prop1 > this.Prop2)
        {
            yield return new ValidationResult("Prop1 must be larger than Prop2");
        }

此外,如果您使用的是MVC ModelState,则可以将验证结果失败转换为ModelState条目,如下所示(如果您在custom model binder中执行验证,这可能会很有用):

代码语言:javascript
复制
var resultsGroupedByMembers = validationResults
    .SelectMany(vr => vr.MemberNames
                        .Select(mn => new { MemberName = mn ?? "", 
                                            Error = vr.ErrorMessage }))
    .GroupBy(x => x.MemberName);

foreach (var member in resultsGroupedByMembers)
{
    ModelState.AddModelError(
        member.Key,
        string.Join(". ", member.Select(m => m.Error)));
}
票数 39
EN

Stack Overflow用户

发布于 2015-11-21 07:25:24

我实现了一个用于验证的通用用法抽象类。

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace App.Abstractions
{
    [Serializable]
    abstract public class AEntity
    {
        public int Id { get; set; }

        public IEnumerable<ValidationResult> Validate()
        {
            var vResults = new List<ValidationResult>();

            var vc = new ValidationContext(
                instance: this,
                serviceProvider: null,
                items: null);

            var isValid = Validator.TryValidateObject(
                instance: vc.ObjectInstance,
                validationContext: vc,
                validationResults: vResults,
                validateAllProperties: true);

            /*
            if (true)
            {
                yield return new ValidationResult("Custom Validation","A Property Name string (optional)");
            }
            */

            if (!isValid)
            {
                foreach (var validationResult in vResults)
                {
                    yield return validationResult;
                }
            }

            yield break;
        }


    }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3400542

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档