1. 程式人生 > >.NET平臺開源專案速覽(6)FluentValidation驗證元件介紹與入門(一)

.NET平臺開源專案速覽(6)FluentValidation驗證元件介紹與入門(一)

    在文章:這些.NET開源專案你知道嗎?讓.NET開源來得更加猛烈些吧!(第二輯)中,給大家初步介紹了一下FluentValidation驗證元件。那裡只是概述了一下,並沒有對其使用和強大功能做深入研究,所以今天以及接下去的幾篇文章就專門介紹這個元件。不僅僅是它小,輕量級,優雅,而且一直在持續更新中。本人對這個感觸很深是源於4年前自己在做一個數據過濾軟體時,自己也設計了一套驗證過濾的東西,雖然勉強能用,但太複雜了,複雜到我看到就想吐。。。指導我遇到了FluentValidation,徹底顛覆了我的看法,原來程式碼是可以很優雅的。。。這就是所謂的架構技術吧,雖然我不是很懂,但一直追求中。

    為了保持內容的完整性,大部分內容我都是參考FluentValidation提供的幫助文件,自己經過翻譯和理解加工。更好的呈現給大家。

1.基本介紹

    FluentValidation是一個使用Linq表示式,非常流暢的小型業務物件驗證元件。流暢也可以說優雅。類似鏈式操作。易於理解,功能完善。還可以配合MVC使用直接在頁面進行驗證,當你看到它的語法時,非常優雅,非常令人心動。不僅可以使用Linq的操作,還能自帶驗證返回資訊。更重要的是,元件內部已經封裝好了10幾種驗證器。當然可以自定義一個複雜的哦。核心dll檔案也不大,130多k。如果好用,可以自己移植到自己的系統哦。直接更好。目前一直在更新中,主要是bug修復。

NuGet Packages:Install-Package FluentValidation

ASP.NET MVC整合包:Install-Package FluentValidation.MVC5

    下面我們將從一個簡單的驗證器的建立以及使用來介紹它的基本功能。

2.建立驗證器

    使用之前,要引用FluentValidation.dll,太簡單,就省略了吧。為了給特定的物件定義一組驗證規則,必須建立一個繼承AbstractValidator<T>的類,T是需要驗證的型別。例如,假設我們有一個Customer類,如下所示:

public class Customer {
  public int Id { get; set; }
  public string Surname { get; set; }
  public string Forename { get; set; }
  public decimal Discount { get; set; }
  public string Address { get; set; }
}

    所以按照上面要求,我們要給Customer定義一組驗證規則,就要繼承AbstractValidator<Customer>,如下面程式碼:

using FluentValidation;

public class CustomerValidator : AbstractValidator<Customer> 
{
}

    驗證規則本身在驗證器的建構函式中定義。為了給特定屬性指定一個驗證規則,需要呼叫RuleFor方法,通過屬性的lambda表示式來進行你想要的驗證。例如,確保Surname屬性不是null,驗證器應該這樣寫:

using FluentValidation;
//Customer驗證器
public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator() 
  {
     RuleFor(customer => customer.Surname).NotNull();
  }
}

3.針對相同屬性的鏈式程式設計驗證

    針對同一個屬性編寫驗證程式碼時,我們可以使用鏈式的方式進行,非常方便,也容易理解。如下面的程式碼:

using FluentValidation;
public class CustomerValidator : AbstractValidator<Customer> 
{
  public CustomerValidator() 
  {  //Surname不為空,且不等於foo
     RuleFor(customer => customer.Surname).NotNull().NotEqual("foo");
  }
}

    上面的註釋已經很明顯了,針對Surname屬性,直接進行判斷和編寫程式碼,同樣可以寫其他的,一直寫下去。。。為了執行驗證器,我們首先要建立一個驗證器的例項物件,然後將要驗證的物件傳遞給Validate方法,即可進行驗證。如下面程式碼:

//要驗證的物件例項
Customer customer = new Customer();
//驗證器例項
CustomerValidator validator = new CustomerValidator();
//進行驗證操作,獲取驗證結果
ValidationResult results = validator.Validate(customer);

     至於結果的內容,請接著往下看。

4.驗證結果

     在使用驗證器的Validate進行驗證後,獲取的ValidationResult物件裡面提供了2個主要資訊:

1.IsValid: 標記是否驗證成功

2.Errors :錯誤情況,驗證失敗的物件集合,包括所有驗證失敗物件的細節。

    例如下面的程式碼將驗證失敗的資訊打印出來:

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
//如果驗證失敗
if(! results.IsValid) {
  //遍歷所有的失敗物件
  foreach(var failure in results.Errors) {
  //失敗的屬性名稱,如錯誤資訊
    Console.WriteLine("Property " + failure.PropertyName + " failed validation. Error was: " + failure.ErrorMessage);
  }
}

5.異常與複雜驗證

5.1 如何丟擲異常

    上一節中,我們看到了驗證結果的處理情況,但是在很多情況下,如果驗證失敗的情況下,要及時丟擲異常給使用者,所以在驗證的時候就要注意丟擲異常,FluentValidation也提供了這樣的機制,它為驗證器提供了一個ValidateAndThrow 的擴充套件方法。使用這個方法後,如果碰到失敗的情況,會及時丟擲一個ValidationException 異常,讓業務驗證過程使用。主要程式碼如下:

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
validator.ValidateAndThrow(customer);

5.2 複雜驗證的處理

    我們前面處理的都是單個驗證器的使用,構成也基本清楚了,但如果在當前驗證的實體類中還有其他物件,也需要對這個物件進行各種屬性驗證,該怎麼辦。舉個例子,假設我們有一個 客戶類 Customer 以及地址類Address,在Customer 中包括了一個Address型別的屬性,用來儲存當前客戶的地址資訊,如下面所示程式碼:

//客戶類
public class Customer 
{
	public string Name { get; set; }
	public Address Address { get; set; }
}
//地址類
public class Address
{
	public string Line1 { get; set; }
	public string Line2 { get; set; }
	public string Town { get; set; }
	public string County { get; set; }
	public string Postcode { get; set; }
}

    由於我們也需要對Address類進行,驗證,所以先類似的構造一個Address驗證器:

public class AddressValidator : AbstractValidator<Address> 
{
	public AddressValidator() 
	{
		RuleFor(address => address.Postcode).NotNull();   
	}
}

    然後我們同理要構造CustomerValidator驗證器,在驗證Address的時候,及可以複用上面的AddressValidator,如下面程式碼:

public class CustomerValidator : AbstractValidator<Customer> 
{
	public CustomerValidator() 
	{
		RuleFor(customer => customer.Name).NotNull();
		//對Address使用驗證器直接進行驗證,可以重複使用程式碼
		RuleFor(customer => customer.Address).SetValidator(new AddressValidator())
	}
}

    過程比較簡單,更加複雜的處理也類似,應該沒啥問題了。值得注意的是,如果Address 是集合型別,如List<Address> ,則要使用SetCollectionValidator來進行驗證,和SetValidator的使用類似。

6.靈活的驗證規則組設定

    我們在編寫驗證過程中,可以編寫大量的驗證方法,針對不同使用場景,不同欄位。但隨著業務的複雜,並不是每一個驗證器的使用的時候都要執行所有的驗證規則。有的時候可能只需要執行一部分就可以了,否則需要針對同一個型別,編寫很多個不同業務場景的驗證器,顯然則是非常殘酷的。而FluentValidation則提供了處理這種問題的靈活性,將規則組集合在一起,並賦予一個名稱,在執行的時候,可以只執行指定名稱規則組的規則。看看下面的例子:

    假設一個Person類有3個屬性(Id,Surname,Forename),我們寫一個驗證器分別對幾個屬性進行驗證,並將其中2個的驗證規則放在一個規則集合裡面RuleSet,名稱為:Names,如下面程式碼:

public class PersonValidator : AbstractValidator<Person> 
{
	public PersonValidator()
	{   //名稱為 Names 的規則組
		RuleSet("Names", () => 
			{
				RuleFor(x => x.Surname).NotNull();
				RuleFor(x => x.Forename).NotNull();
			});
		//其他沒有集合的組名稱,預設為:default
		RuleFor(x => x.Id).NotEqual(0);
	}
}

    然後我們在驗證的時候,就可以靈活指定規則集的名稱了,一次可以指定單個或者多個,值得注意的是,沒有放在集合中的規則,預設在 default 組中。如下面的程式碼:

var validator = new PersonValidator();
var person = new Person();
//只執行 Names 規則集
var result = validator.Validate(person, ruleSet: "Names");
//執行 Names,MyRuleSet,SomeOtherRuleSet 規則集
validator.Validate(person, ruleSet: "Names,MyRuleSet,SomeOtherRuleSet")
//執行預設的規則(不在集合中的) 和 MyRuleSet
validator.Validate(person, ruleSet: "default,MyRuleSet")

    上面就是今天的內容,我們對驗證器的完整過程和使用細節進行了很深入的研究,相信自己構造一個強大的驗證器已經很容易了吧。接下來的內容,我們將繼續介紹內建的一些驗證方法和規則。對於該元件的原始碼可以直接從github獲取,本文將在後面的文章中釋出自己製作的CHM幫助文件。敬請關注!

相關推薦

.NET平臺開源專案(6)FluentValidation驗證元件介紹入門()

    在文章:這些.NET開源專案你知道嗎?讓.NET開源來得更加猛烈些吧!(第二輯)中,給大家初步介紹了一下FluentValidation驗證元件。那裡只是概述了一下,並沒有對其使用和強大功能做深入研究,所以今天以及接下去的幾篇文章就專門介紹這個元件。不僅僅是它小,輕量級,優雅,而且一直在持續更新中

.NET平臺開源專案(10)FluentValidation驗證元件深入使用(二)

    在上一篇文章:.NET平臺開源專案速覽(6)FluentValidation驗證元件介紹與入門(一) 中,給大家初步介紹了一下FluentValidation驗證元件的使用情況。文章從構建間的驗證器開始,到最後的結果,以及複雜驗證等都做了比較深入的講解和使用。但其實一個完整的元件是麻雀雖小五臟俱全

.NET平臺開源專案(13)機器學習元件Accord.NET框架功能介紹

    Accord.NET Framework是在AForge.NET專案的基礎上封裝和進一步開發而來。因為AForge.NET更注重與一些底層和廣度,而Accord.NET Framework更注重與機器學習演算法以及提供計算機視訊、音訊、訊號處理以及統計應用相關的解決方案。該專案使用C#語言編寫,專

.NET平臺開源專案-最快的物件對映元件Tiny Mapper之專案實踐

心情小札:近期換了工作,苦逼於22:00後下班,房間一篇狼藉~ 小翠鄙視到:"你就適合生活在垃圾堆中!!!" 看評論也是挺有價值,同時也看到許多新手同學問道在實際專案中使用的情況。 下面就原作者的程式碼的基礎上略作調整,闡述一下在實際專案場景中的使用: 第一步:瞭解類庫方法:TinyMapper 主

.NET平臺開源專案(14)最快的物件對映元件Tiny Mapper

    好久沒有寫文章,工作甚忙,但每日還是關注.NET領域的開源專案。五一休息,放鬆了一下之後,今天就給大家介紹一個輕量級的物件對映工具Tiny Mapper:號稱是.NET平臺最快的物件對映元件。那就一起看看呢。 臨時更新:感謝@ 的意見,為了避免新手誤解,這裡說明一下,Tiny Mappe

.NET平臺開源專案(20)Newlife.Core中簡單靈活的配置檔案

如果用知乎,可以關注專欄: 記得5年前開始拼命翻讀X元件的原始碼,特別是XCode,但對Newlife.Core 的東西瞭解很少,最多隻是會用用,而且用到的只是九牛一毛。裡面好用的東西太多了。 最近一年時間,零零散散又學了很多,也瞭解了很多,不會寫那總要學會用吧,今天就給大家介紹裡面非常好用的自定義配置檔

.NET平臺開源專案(19)Power BI神器DAX Studio

  PowerBI更新頻繁,已經有點更不上的節奏,一直在關注和學習中,基本的一些操作大概是沒問題,更重要的是注重Power Query,M函式,以及DAX的使用,這才是核心。     上個月研究了DAX的一些語法和公式,發現這玩意看起來簡單,但其實功能非常強大,所以就想和寫程式碼一樣,弄個工具試一下。

.NET平臺開源專案(21)Cron任務排程CronNET

Quartznet大名鼎鼎應該很少有人不知道,相關的開源專案很多,不過那東東對新手來說,有點晦澀,加上哪個Cron表示式,可能一進去雲裡霧裡的。今天給大家介紹一個簡單的在.NET平臺上執行Cron計劃任務的元件CronNET。同時也給大家推介幾個Cron表示式的工具。 1.Cron介紹和工具

.NET平臺開源專案(7)關於NoSQL資料庫LiteDB的分頁查詢解決過程

  在文章:這些.NET開源專案你知道嗎?讓.NET開源來得更加猛烈些吧!(第二輯) 與 .NET平臺開源專案速覽(3)小巧輕量級NoSQL檔案資料庫LiteDB中,介紹了LiteDB的基本使用情況以及部分技術細節,我還沒有在實際系統中大量使用,但文章釋出後,有不少網友( )反應在實際專案中使用過,效果還

.NET平臺開源專案(11)KwCombinatorics排列組合使用案例(1)

    今年上半年,我在KwCombinatorics系列文章中,重點介紹了KwCombinatorics元件的使用情況,其實這個元件我5年前就開始用了,非常方便,麻雀雖小五臟俱全。所以一直非常喜歡,才寫了幾篇文章推薦給大家。最近在計算足球彩票結果組合過程中,使用的到了其功能,生成排列,非常具有代表性,而且也

.NET平臺開源專案(1)SharpConfig配置檔案讀寫元件

在.NET平臺日常開發中,讀取配置檔案是一個很常見的需求。以前都是使用System.Configuration.ConfigurationSettings來操作,這個說實話,搞起來比較費勁。不知道大家有沒有同感。所以更多時候我還是喜歡使用開源的東西,更加方便簡潔,也穩定。省去自己的麻煩。今天就介紹一個非常精緻

.NET平臺開源專案(3)小巧輕量級NoSQL檔案資料庫LiteDB

    今天給大家介紹一個不錯的小巧輕量級的NoSQL檔案資料庫LiteDB。本部落格在2013年也介紹過2款.NET平臺的開源資料庫:     上面2個數據庫我的實際的專案中用過,還不錯。當然資料量很小,主要是客戶比較變態,必須要用xml檔案儲存,就想到了,另外NDatabase只是自己覺得好玩,

.NET平臺開源專案(9)軟體序列號生成元件SoftwareProtector介紹使用

  在文章:這些.NET開源專案你知道嗎?讓.NET開源來得更加猛烈些吧!(第二輯)中,給大家初步介紹了一下Software Protector序列號生成元件。今天就通過一篇簡單的文章來預覽一下其強大的功能。雖然我人為其已經基本滿足了一個軟體序列號的所有要素,但至於大家用不用得上,還得看大家的需求。總的來

.NET平臺開源專案(2)Compare .NET Objects物件比較元件

    .NET平臺開源專案速覽今天介紹一款小巧強大的物件比較元件。可以更詳細的獲取2個物件的差別,並記錄具體差別,比較過程和要求可以靈活配置。 1.Compare .NET Objects介紹     Compare .NET Objects元件是.NET平臺用於深入比較2個.NET物件的開源元

.NET平臺開源專案(5)深入使用擴充套件SharpConfig元件

  上個月在文章:這些.NET開源專案你知道嗎?讓.NET開源來得更加猛烈些吧  和 .NET平臺開源專案速覽(1)SharpConfig配置檔案讀寫元件 中都提到了SharpConfig元件,簡單輕量級,速度快,而且還有比較深入的使用介紹。在文章釋出後,也有網友提到一些問題,當時我也沒仔細去分析,在這次我親

.NET平臺開源專案(8)Expression Evaluator表示式計算元件使用

  在文章:這些.NET開源專案你知道嗎?讓.NET開源來得更加猛烈些吧!(第二輯)中,給大家初步介紹了一下Expression Evaluator驗證元件。那裡只是概述了一下,並沒有對其使用和強大功能做深入研究,所以今天就通過一篇簡單的文章來預覽一下其強大的功能。本文曾在【原創】.NET開源表示式計算元

.NET平臺開源專案(4).NET文件生成工具ADB及使用

    很久以前就使用ADB這個工具來生成專案的幫助文件。功能強大,在學習一些開源專案的過程中,官方沒有提供CHM幫助文件,所以為了快速的瞭解專案結構和註釋。就生成文件來自己看,非常好用。這也是一個學習方法吧。例如本文在:   上述2篇文章中最後的資源中就手動製作了CHM幫助文件。有時候我們還可

.NET平臺開源專案(12)雜湊演算法集合類庫HashLib

    .NET的System.Security.Cryptography名稱空間本身是提供加密服務,雜湊函式,對稱與非對稱加密演算法等功能。實際上,大部分情況下已經滿足了需求,而且.NET實現的都是目前國際上比較權威的,標準化的演算法,所以還是安全可靠的。但也有一些場合,需要自己實現一些安全雜湊演算法。

.NET平臺開源專案(18)C#平臺JSON實體類生成器JSON C# Class Generator

    去年,我在一篇文章用原始方法解析複雜字串,json一定要用JsonMapper麼?中介紹了簡單的JSON解析的問題,那種方法在當時的環境是非常方便的,因為不需要生成實體類,結構很容易解析。但隨著業務的變化,也會碰到超級變態的JSON,如果還按照以前的思路,會把人搞抽風掉,一旦結構變化,又要重來。所

.NET平臺開源專案(16)C#寫PDF檔案類庫PDF File Writer介紹

    1年前,我在文章:這些.NET開源專案你知道嗎?.NET平臺開源文件與報表處理元件集合(三)中(第9個專案),給大家推薦了一個開源免費的PDF讀寫元件 PDFSharp,PDFSharp我2年前就看過,用過簡單的例子,不過程式碼沒有寫成專門的文章。最近在查詢資料的時候,又發現一款小巧的寫PDF檔案