验证通用属性验证应用程序块

时间:2011-11-13 10:55:17

标签: .net validation generics enterprise-library

我们有Generics Property

 public class BE
    {
        private List<Admin_Fee> _Admin_Fee = new List<Admin_Fee>();
        [StringLengthValidator(3,
        MessageTemplate = "Fund City Can't be more than 3 Chars")]  
        public MyProperty<string> FUND_CITY { get; set; }

        public MyProperty<int> SomeOtherProperty { get; set; }

        public List<MyPropertyBase> MyDataPoints { get; set; }

    }

我想将StingLengthValidator using VAB放在Generic Property上,并收到错误:

  

值不是预期类型

有人能帮忙吗?

2 个答案:

答案 0 :(得分:0)

我认为这里的问题是验证器的工作原理。 StringLengthValidator要求字符串在某些参数(最小和最大长度)内。但是,您使用此验证器的属性不是字符串,这是您的问题。如果要使用创建自定义验证器属性所需的验证属性对此属性执行某种字符串长度验证,则您的类型是通用T&lt;&gt ;.

  

MVC示例(属性部分不需要MVC) -   http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx

     

一般例子 -   http://odetocode.com/Blogs/scott/archive/2011/02/21/custom-data-annotation-validator-part-i-server-code.aspx

答案 1 :(得分:0)

您收到错误的原因非常简单:您正在尝试对不是字符串的类型使用StringLengthValidator(实际上是MyProperty<string>)。

问题是如何验证财产?这很棘手,因为该设计并不完全适合验证应用程序块设计。

通常,您只需应用ObjectValidator来验证MyProperty类,但这种情况并不适用于此情况,因为您的目标似乎是使用MyProperty来保存各种值每个都有不同的规则,因此您无法将验证器属性真正应用于MyProperty

我认为您可以通过自定义验证器实现您想要的效果。我想你可以在自定义验证器中包装现有的验证器。

这里我假设MyProperty看起来像:

public class MyProperty<T>
{
    public T Value { get; set; }
}

然后您可以创建自定义验证器MyPropertyValidator:

public class MyPropertyValidatorAttribute : ValidatorAttribute
{
    Microsoft.Practices.EnterpriseLibrary.Validation.Validator validator;

    public MyPropertyValidatorAttribute(Type validator, params object[] validatorArgs)
    {
        this.validator = Activator.CreateInstance(validator, validatorArgs) 
            as Microsoft.Practices.EnterpriseLibrary.Validation.Validator;    
    }

    protected override Microsoft.Practices.EnterpriseLibrary.Validation.Validator DoCreateValidator(Type targetType)
    {
        return new MyPropertyValidator(validator);
    }
}

public class MyPropertyValidator : Microsoft.Practices.EnterpriseLibrary.Validation.Validator
{
    Microsoft.Practices.EnterpriseLibrary.Validation.Validator validator;

    public MyPropertyValidator(Microsoft.Practices.EnterpriseLibrary.Validation.Validator validator)
        : this(validator.MessageTemplate, validator.Tag)
    {
        this.validator = validator;
    }

    public MyPropertyValidator(string message, string tag) : base(message, tag)
    {
    }

    protected override string DefaultMessageTemplate
    {
        get { return ""; }
    }

    public override void DoValidate(object objectToValidate, object currentTarget, string key, ValidationResults validationResults)
    {
        var val = objectToValidate;

        Type t = objectToValidate.GetType();
        var propInfo = t.GetProperty("Value");

        if (propInfo != null)
        {
            val = propInfo.GetValue(objectToValidate, null);
        }

        validator.DoValidate(val, currentTarget, key, validationResults);
    }
}

然后你可以这样注释你的课程:

public class BE
{
    [MyPropertyValidator( 
        typeof(StringLengthValidator), 
        0, RangeBoundaryType.Ignore,
        3, RangeBoundaryType.Inclusive,
        "Fund City Can't be more than 3 Chars",
        false)]
    public MyProperty<string> FUND_CITY { get; set; }

    [MyPropertyValidator(
        typeof(RangeValidator),
        0, RangeBoundaryType.Inclusive,
        10, RangeBoundaryType.Inclusive,
        "Must be between 0 and 10", 
        false)]
       public MyProperty<int> SomeOtherProperty { get; set; }
}

我没有广泛测试它,但它似乎工作。它确实有一些缺点:

  • 这是不灵活的。例如,它不支持复合验证器或其他更复杂的场景。你可以实现所有这些案件,但它会变得混乱。
  • 我的实现是使用反射,最好避免。
  • 价值类型的潜在装箱