【问题标题】:Get value from basetype of validation context in custom validator从自定义验证器中验证上下文的基本类型获取值
【发布时间】:2014-02-07 13:36:46
【问题描述】:

我正在尝试编写自己的验证属性,但我无法从继承的类中获取属性的值。这是我的代码:

protected override ValidationResult IsValid(object value, ValidationContext context)
{
    if (context.ObjectType.BaseType == typeof(AddressModel))
    {
        PropertyInfo property = context.ObjectType.BaseType.GetProperty(_propertyName);

        // this is the line i'm having trouble with:
        bool isRequired = (bool)property.GetValue(context.ObjectType.BaseType); 

        return base.IsValid(value, context);
    }

    return ValidationResult.Success;
}

我不知道我要传递到 GetValue 的意思是什么,因为它需要一个对象,但是我传递的所有内容都给了我一个属性类型与目标不匹配异常

我必须转到基类型,因为我试图从继承的类中获取属性的值,而 context.ObjectInstance 不包含必要的属性

【问题讨论】:

  • 我不知道验证框架是如何工作的,所以我无能为力,但GetProperty 期待您正在调用其属性的对象的实例。
  • @Vache 有什么办法可以得到它,因为context.ObjectInstance 返回当前对象,但没有从基本模型类继承的任何属性
  • context.ObjectInstace 只是一个Object,您不能将它转换为AddressModel(或您正在使用的任何类型)并使用对象本身吗?正如我所说,我从未使用过该框架,但我会尝试...
  • 为什么context.ObjectInstance 不能访问它所继承的对象的属性?他们是私人的吗?如果是这样,您将无法获取它们的值,因为这些属性根本不适用于您的物化派生对象。
  • @Vache,刚刚尝试将其转换为基本模型并且它可以工作 - 即使对象实例没有显示任何所需的属性,当它被转换时它们都会显示出来!如果你想回答这个问题,我会给你赏金。谢谢!

标签: c# validation asp.net-mvc-4 c#-4.0


【解决方案1】:

您可以简单地将对象转换为 AddressModel 并像这样使用它。

protected override ValidationResult IsValid(object value, ValidationContext context)
{
    var addressModel = context.ObjectInstance as AddressModel
    if (addressModel != null)
    {
        // Access addressModel.PROPERTY here

        return base.IsValid(value, context);
    }

    return ValidationResult.Success;
}

context.ObjectInstanceobject 类型而不是您模型的类型,因为验证框架不是为了显式验证您的模型而创建的,但它是正确的对象实例。投出后就可以正常使用了。

附带说明一下,property.GetValue(context.ObjectType.BaseType) 出现错误的原因是 GetValue 方法需要您正在调用其属性的对象的实例。

【讨论】:

  • 我必须等一天才能获得赏金,只要它允许我就行。再次感谢!
  • @Pete 和 Vache 我试图将 ObjectInstance 转换为 ObjectType(而不是被限制为特定模型 [本问题/答案中的地址模型])——两者都是 ValidationContext 的成员。关于为什么它不允许我的任何想法?我的问题有意义吗?如果需要,我可以开始一个新的帖子。谢谢!
  • @srinivas.naik ObjectType 是一个表示类型的变量,而不是可以转换为的真实类型。如需更多信息,请提出一个新问题并向我们展示您的代码
  • 我不知道我是否正确,但你会为AddressModel工作。如果我在不同的模型(即PersonModel)中使用相同的验证怎么办。然后呢?
  • @barnes 如果您在PersonModelAddressModel 上验证的属性相同,可以尝试在它们之间放置一个接口或基类。否则,您可能必须进行两个不同的验证。很难说没有看到完整的场景。
【解决方案2】:

您可以将ObjectInstance 转换为它的基本类型,所以您可以试试这个:

protected override ValidationResult IsValid(object value, ValidationContext context)
{
    if (context.ObjectType.BaseType == typeof(AddressModel))
    {
        AddressModel model = (AddressModel)context.ObjectInstance;
        PropertyInfo property = typeof(AddressModel).GetProperty(_propertyName);

        bool isRequired = (bool)property.GetValue(model, null); 

        //OR YOU CAN INTERROGATE THE MODEL DIRECTLY
        var x = model.SomeProperty == true;

        return base.IsValid(value, context);
    }

    return ValidationResult.Success;
}

【讨论】:

    【解决方案3】:

    您应该软转换为所需的对象类型并为自己保存反射,当您在编译时知道所需的类型时,这是不必要的。

    此代码假定您将自定义属性放置在模型的类定义中(而不是单个属性)。 value 将是您放置属性的属性或类的实例:

    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        var addressModel = value as AddressModel;
        if (addressModel != null)
        {
            // Do some stuff against addressModel here to determine if valid...
    
            return base.IsValid(value, context);
        }
    
        return ValidationResult.Success;
    }
    

    【讨论】:

    • 嗨,我尝试使用该值,因为我认为它是对象(因为我查看了很多其他人的使用该值的帖子)但出于某种原因,在我的情况下它总是空
    • @Pete 调试器说value 对象是什么?
    • 什么都没有 - 它只是说它是空的,然后如果我尝试对其执行 typeof 它说它在这个范围内无效
    • @Pete 向我们展示一些您使用自定义属性的代码。
    • 我只是用它在我的模型中标记属性:[AddressRequired(ErrorMessage = "请输入您的邮政编码")] public string Postcode { get;放; }
    猜你喜欢
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多