2011-11-13 55 views
1

我們有泛型物業驗證通用屬性驗證應用程序塊

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的通用屬性,並獲得錯誤:

值不是預期類型

有人可以幫忙嗎?

回答

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

我還沒有廣泛的測試它,但它似乎工作。它確實有一些缺點:

  • 它不靈活。例如,它不支持複合驗證程序或其他更復雜的場景。你也許可以實現所有這些情況,但會變得混亂。
  • 我的實現是使用反射,這將更好地避免。
  • 價值類型的潛在拳擊
+0

感謝您的回覆。當我實現這個代碼時,出現錯誤「Method'Level2.MyProperty'1 [[System.String,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]。在方法中:public override void DoValidate –

+0

@ H.N.Mishra:既然您沒有發佈'MyProperty'類,我只是猜測它可能是什麼樣子的例子。您需要將屬性「Value」更改爲您需要在「MyProperty」中進行驗證的任何實際屬性。 –

+0

感謝你!它工作得很好。 –

0

我認爲這裏的問題是驗證器是如何工作的。 StringLengthValidator需要一個字符串在特定參數(最小和最大長度)內。然而,你把這個驗證器的屬性不是一個字符串,這是你的問題。你的類型是一個通用的T <>,如果你想使用驗證屬性對這個屬性進行一些排序字符串長度驗證,你需要創建一個自定義驗證器屬性。

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