2014-05-21 77 views
3

有時,我有很多字符串屬性的複雜模型,需要在設置時進行驗證,但驗證通常不會比IsNotNullOrWhitespace更進一步。自動屬性驗證

這通常會導致不必要的代碼重複,所以我想知道是否有辦法自動驗證屬性設置值,最好沒有任何額外的框架。

可能的解決方案

  • AOP(例如用PostSharp)
  • 流利驗證
  • 數據註釋

數據註釋的感覺是最自然的方式對我來說,作爲驗證與模型非常接近,並且因爲它是.Net-Framework的一部分,所以屬性是可以的。但是,如果我在MVC或序列化之外使用模型,則必須使用驗證器手動進行驗證。所以我必須在許多地方(存儲庫,API,服務)進行驗證,如果我忘了在某處執行此操作,我的域規則可能會被破壞。

AOP可能是一種完美的方式,但是在C#中沒有直接的東西,並且我的域模型與PostSharp或Ninject等基礎設施組件緊密結合(截取)是一個禁忌。

+1

驗證何時需要進行?當@ setter,是的,你應該使用AOP。你可以看看Fody(https://github.com/Fody/Fody),它是免費的..也許這會減少你對耦合到基礎設施組件的顧慮。無論如何,我必須問:你願意有更多的代碼併爲它付出代價,而且它一次又一次的維護,還是你更願意依靠基礎架構組件,加速開發並減少漏洞的機會?什麼是基礎架構組件,哪些不是?你是否依賴VS,或者你是否使用(任何)文本編輯器,因爲耦合讓你感到困擾? ;-) – BatteryBackupUnit

回答

1

嘗試NConcern AOP Framework

這個新的最低運行時的AOP框架(關於這一點我積極工作)可以幫助你通過AOP來管理驗證沒有聯軸器域裝配。

在您的驗證程序集中,定義您自己的驗證屬性以及如何驗證它。

自定義屬性來定義/識別電子郵件

[AttributeUsage(AttributeTargets.Property)] 
public class Email : Attribute 
{ 
    //validation method to use for email checking 
    static public void Validate(string value) 
    { 
     //if value is not a valid email, throw an exception! 
    } 
} 

驗證方面,檢查合同代碼

//Validation aspect handle all my validation custom attribute (here only email) 
public class EmailValidation : IAspect 
{ 
    public IEnumerable<IAdvice> Advise(MethodInfo method) 
    { 
     yield return Advice.Before((instance, arguments) => 
     { 
      foreach (var argument in arguments) 
      { 
       if (argument == null) { continue; } 
       Email.Validate(argument.ToString()); 
      } 
     }); 
    } 
} 

你的域裝配

public class Customer 
{ 
    [Email] 
    public string Login { get; set; } 
} 

在另外一個組件(驗證之間的聯繫和域

//attach validation to Customer class. 
foreach (var property in typeof(Customer).GetProperties()) 
{ 
    if (property.IsDefined(typeof(Email), true)) 
    { 
     Aspect.Weave<Validation>(property.GetSetMethod(true)); 
    } 
}