2009-02-21 71 views
0

所以我有一個簡單的驗證規則模式,用於對實體對象進行驗證。這裏是我的有效性規則類:我在仿製藥方面遇到了一些麻煩,並在C#中鑄造了一些問題。

public class ValidationRule { 

    public Func<object, bool> Rule { get; set; } 
    public string ErrorMessage { get; set; } 

    public ValidationRule(string errorMessage, Func<object, bool> rule) { 
     Rule = rule; 
     ErrorMessage = errorMessage; 
    } 

    public bool IsValid(object obj) { 
     return Rule(obj); 
    } 
} 

我有一個基類封裝執行驗證,看起來像這樣的方式,我的實體對象:

public abstract class ModelBase { 

    private List<ValidationRule> _validationRules; 
    public List<ValidationRule> ValidationRules { 
     get { 
      if (_validationRules == null) 
       _validationRules = new List<ValidationRule>(); 
      return _validationRules; 
     } 
     set { _validationRules = value; } 
    } 

    public ValidationResult Validate() { 
     var result = new ValidationResult(); 
     rules.ForEach(r => { 
      if (!r.IsValid(this)) 
       result.Errors.Add(
        new ValidationError(r.ErrorMessage, r.PropertyName));    
      }); 
     return result; 
    } 
} 

而現在這裏是真正的問題,我試圖解決。當我創建一個從ModelBase繼承的新類時,添加驗證規則有點尷尬。例如:

public class Client : ModelBase { 

    public int ID{ get; set; } 
    public string Name { get; set; } 
    public Address MailingAddress { get; set; } 

    public Client() { 
     CreateValidationRules(); 
    } 

    private void CreateValidationRules() { 

     ValidationRules.Add(new ValidationRule("Client 'Name' is required.", 
      c => !string.IsNullOrEmpty(((Client)c).Name))); 
    } 
} 

注意我在創建驗證規則列表。在lambda表達式中,我必須將「c」轉換爲「Client」,因爲我的規則基本上是Func<object, bool>。我已經嘗試了很多方法來通過類似ValidationRule<Client>的方法來使這個通用,但我總是遇到在ModelBase類中調用Validate()的問題。任何想法如何解決這個鑄造?

+0

作爲邊注,Func鍵<對象,布爾>是相同的謂詞 bendewey 2009-02-21 19:17:53

+0

‘同’類型的功能。但出於某種奇怪的原因,它們在類型系統中不一樣。 – MichaelGG 2009-02-21 19:19:10

回答

4

您可以使ValidationRule類爲通用,但將IsValid方法的參數保留爲對象,並在方法中執行強制轉換。這樣你就可以獲得泛型,而無需使ModelBase具有通用性。

您還需要一個ModelBase的接口,以便能夠在不知道實際類型的情況下保留驗證規則的列表。然後,只需將ModelBase中的列表和屬性的類型更改爲IValidationRule。

(注意:您可以使用性質的私人二傳手,使他們只讀)現在

public Interface IValidationRule { 
    bool IsValid(object); 
} 

public class ValidationRule<T> : IValidationRule { 

    public Func<T, bool> Rule { get; private set; } 
    public string ErrorMessage { get; private set; } 

    public ValidationRule(string errorMessage, Func<object, bool> rule) { 
     Rule = rule; 
     ErrorMessage = errorMessage; 
    } 

    public bool IsValid(object obj) { 
     return Rule((T)obj); 
    } 
} 

,在LAMDA表達式的參數的類型是泛型類型,所以你不要「T必須將其丟:

ValidationRules.Add(
     new ValidationRule<Client>(
      "Client 'Name' is required.", 
      c => !string.IsNullOrEmpty(c.Name) 
    ) 
); 
1

我懷疑ModelBase也需要變得通用。但我不清楚這裏到底發生了什麼 - 不是每個客戶端的驗證規則都是一樣的嗎?驗證規則覺得它們應該與整個類型相關聯,而不是某個類型的單個實例。無可否認,他們對驗證了

我想知道您是否應該沒有Validator<T>類型,並創建(一次)Validator<Client>,然後可以針對Client的任何實例進行驗證。

相關問題