日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

验证能有多优雅

發(fā)布時間:2025/4/16 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 验证能有多优雅 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

背景

我們都知道ENTLIBVAB,也知道如果不在乎大量的XML損視力的話,VAB非常非常優(yōu)雅,但是在不大的項目中,很多情況下我們依舊自己寫著驗證的代碼

所以在這篇文章中,打算展示一下學(xué)習(xí).NET一年半以來,寫驗證代碼的各個階段,并展示一種個人覺得比較優(yōu)雅的驗證代碼的寫法,如果大家有別的方案,也請?zhí)岢鰜砼c大家分享哦

?

第一階段--強(qiáng)寫

所謂強(qiáng)寫,自然就是強(qiáng)行地寫了,從知道需要參數(shù)驗證(很慚愧,學(xué)了.NET整整1個月才知道這事)開始,好長一段時間都在強(qiáng)寫著驗證的代碼,也不記得什么時候開始覺得這么寫不舒服,什么時候開始換成了別的方法,總之早期的代碼中充斥著這樣的片斷

public?void?SomeMethod(string?s)
{
????
if?(s?==?null)
????{
????????
throw?new?ArgumentNullException("s");
????}
????
if?(s.Length?==?0)
????{
????????
throw?new?ArgumentException("s?cannot?be?empty?");
????}
}

最終的結(jié)果是,一個.cs文件中有整整1/2的內(nèi)容是這些可愛的if, throw和花括號

這個方案不用評價了,我自己會把他貶得很慘,再怎么說曾經(jīng)也是為了這些東西寫到手抽筋啊,痛苦啊

?

?

第二階段--Guard類

?

嗯,MS很多項目中都有這個Guard類,把一些主要的驗證的方法寫在了類中,方法直接拋出異常,大致是這樣的

public?class?Guard
{
????
public?void?NotNull(object?value,?string?argName)
????{
????????
if?(value?==?null)
????????{
????????????
throw?new?ArgumentNullException(argName);
????????}
????}

????
//其他驗證方法
}

?

調(diào)用的方法大致是這樣的

public?void?SomeMethod(string?s)
{
????Guard.NotNull(s,?
"s");
????Guard.NotEmpty(s,?
"s");
????Guard.ShorterThan(s,?
10,?"s");
????Guard.LongerThan(s,?
3,?"s");
????
//其他邏輯
}

看起來清爽多了,再也沒有if, throw和美麗的花括號了,可喜可賀~可喜可賀~

?

但是!并不是一切都這么美好的!每一次調(diào)用方法都需要值一個字符串以表示參數(shù)的名稱,這里寫了4”s”,當(dāng)然你會說4”s”沒什么,但是寫4”user.Name”再寫6”user.CreationDate”呢……

什么感覺?手酸?NO~NO~這不是最重要的,重要的是寫字符串的時候VS沒有自動提示啊!你敢保證寫10個不錯一個字母么?

其實(shí)對這個階段還是非常有感情的,怎么說都是對“把類似功能合在一起”的理念的嘗試呢

?

第三階段--擴(kuò)展方法

然后,然后就有了C# 3.0,就有了擴(kuò)展方法,然后Guard中的方法的第一個參數(shù)都加了一個this,調(diào)用就成了這樣

public?void?SomeMethod(string?s)
{
????s.NotNull(
"s");
????s.NotEmpty(
"s");
????s.ShorterThan(
10,?"s");
????s.LongerThan(
3,?"s");
????
//其他邏輯
}

基本我不認(rèn)可這是一個階段呢,只是用了點(diǎn)語法糖而已,最重要的字符串多次輸入?yún)?shù)名稱的問題根本沒有得到解決,少打幾個字會很快樂么……作為一個標(biāo)準(zhǔn)的程序員,我想說:NO!

?

?

第四階段--不知道怎么說

?

就是現(xiàn)在在用的方法啦,剛剛“發(fā)明”出來的哦,個人自我感覺良好,但實(shí)在不知道怎么從設(shè)計上去解釋,就先寫一下實(shí)現(xiàn)方案吧

很久很久以前,有一個孤獨(dú)的類,句叫ValidationHelper<T>,他的任務(wù)就是懲治世上所有不聽話的參數(shù),根據(jù)見過他的變量們的描述,他是長得這樣的

?

Code
public class ValidationHelper<T>
{
#region 成員

private T m_Value;

private string m_Name;

#endregion

#region 屬性

/// <summary>
/// 獲取待驗證的參數(shù)的值.
/// </summary>
public T Value
{
get
{
return m_Value;
}
}

/// <summary>
/// 獲取待驗證的參數(shù)的名稱.
/// </summary>
public string Name
{
get
{
return m_Name;
}
}

#endregion

#region 構(gòu)造函數(shù)

/// <summary>
/// 創(chuàng)建一個<see cref="ValidationHelper&lt;T&gt;"/>的對象.
/// </summary>
/// <param name="value">待驗證的參數(shù)的值.</param>
/// <param name="name">待驗證的參數(shù)的名稱.</param>
public ValidationHelper(T value, string name)
{
m_Value
= value;
m_Name
= name;
}

#endregion

#region 基本方法

/// <summary>
/// 驗證參數(shù)不為其默認(rèn)值.
/// </summary>
/// <returns>this指針以方便鏈?zhǔn)秸{(diào)用.</returns>
/// <exception cref="ArgumentException">參數(shù)為值類型且為默認(rèn)值.</exception>
/// <exception cref="ArgumentNullException">參數(shù)為引用類型且為null.</exception>
public ValidationHelper<T> NotDefault()
{
if (Value.Equals(default(T)))
{
if (Value is ValueType)
{
throw new ArgumentException(
String.Format(
"參數(shù){0}不能使用默認(rèn)值", Name), Name);
}
else
{
throw new ArgumentNullException(
String.Format(
"參數(shù){0}不能為null", Name), Name);
}
}

return this;
}

/// <summary>
/// 使用自定義方法進(jìn)行驗證.
/// </summary>
/// <param name="rule">用以驗證的自定義方法.</param>
/// <returns>this指針以方便鏈?zhǔn)秸{(diào)用.</returns>
/// <exception cref="Exception">驗證失敗拋出相應(yīng)異常.</exception>
/// <remarks><paramref name="rule"/>的第一個參數(shù)為參數(shù)值,第二個參數(shù)為參數(shù)名稱.</remarks>
public ValidationHelper<T> CustomRule(Action<T, string> rule)
{
rule(Value, Name);

return this;
}

#endregion
}

?

?

因為ValidationHelper<T>可以保存住參數(shù)的值和參數(shù)的名稱,因此就一下子地解決了多次輸入?yún)?shù)名稱的問題,真不虧是大俠啊

但是,很多人都不知道,為什么功能這么少的ValidationHelper<T>可以消滅幾乎所有的不規(guī)范參數(shù),其實(shí)秘訣還在于擴(kuò)展方法,通過擴(kuò)展方法的聯(lián)系,ValidationHelper<T>找到了很多伙伴,其實(shí)除暴安良的,是一個團(tuán)隊,而非一個人,下面來看看StringValidationHelper是怎么樣對付不規(guī)范的string的吧

Code
public static class StringValidationHelper
{
/// <summary>
/// 驗證<see cref="System.String"/>類型的參數(shù)不為空.
/// </summary>
/// <param name="current">用于驗證的<see cref="ValidationHelper&lt;T&gt;"/></param>
/// <returns><paramref name="current"/>的引用以方便鏈?zhǔn)秸{(diào)用.</returns>
public static ValidationHelper<string> NotEmpty(this ValidationHelper<string> current)
{
current.NotDefault();

if (current.Value.Length == 0)
{
throw new ArgumentException(
String.Format(
"{0}不可為空字符串", current.Name), current.Name);
}

return current;
}

/// <summary>
/// 驗證<see cref="System.String"/>類型的參數(shù)的長度小于一定值.
/// </summary>
/// <param name="current">用于驗證的<see cref="ValidationHelper&lt;T&gt;"/></param>
/// <param name="length">可行的最大長度(包括此值).</param>
/// <returns><paramref name="current"/>的引用以方便鏈?zhǔn)秸{(diào)用.</returns>
public static ValidationHelper<string> ShorterThan(this ValidationHelper<string> current, int length)
{
current.NotDefault();

if (current.Value.Length > length)
{
throw new ArgumentException(
String.Format(
"{0}的長度不可超過{1}", current.Name, length), current.Name);
}

return current;
}

/// <summary>
/// 驗證<see cref="System.String"/>類型的參數(shù)的長度大于一定值.
/// </summary>
/// <param name="current">用于驗證的<see cref="ValidationHelper&lt;T&gt;"/></param>
/// <param name="length">可行的最小長度(包括此值).</param>
/// <returns><paramref name="current"/>的引用以方便鏈?zhǔn)秸{(diào)用.</returns>
public static ValidationHelper<string> LongerThan(this ValidationHelper<string> current, int length)
{
current.NotDefault();

if (current.Value.Length < length)
{
throw new ArgumentException(
String.Format(
"{0}的長度不可小于{1}", current.Name, length), current.Name);
}

return current;
}

/// <summary>
/// 驗證<see cref="System.String"/>類型的參數(shù)的長度在一定值之間.
/// </summary>
/// <param name="current">用于驗證的<see cref="ValidationHelper&lt;T&gt;"/></param>
/// <param name="minLength">可行的最小長度(包括此值).</param>
/// <param name="maxLength">可行的最大長度(包括此值).</param>
/// <returns><paramref name="current"/>的引用以方便鏈?zhǔn)秸{(diào)用.</returns>
public static ValidationHelper<string> LengthBetween(this ValidationHelper<string> current, int minLength, int maxLength)
{
current.NotDefault();

if (current.Value.Length < minLength || current.Value.Length > maxLength)
{
throw new ArgumentException(
String.Format(
"{0}的長度必須在{1}和{2}之間", current.Name, minLength, maxLength), current.Name);
}

return current;
}
}

好了,伙伴找到了,現(xiàn)在的問題是,當(dāng)需要大俠幫助的時候,我們不得不使出全身的力氣使用new來召喚大俠……這顯然很不爽,因此又有了一擴(kuò)展方法,我們稱之為“工廠”

public?static?class?Validation
{
????
public?static?ValidationHelper<T>?InitValidation<T>(this?T?value,?string?argName)
????{
????????
return?new?ValidationHelper<T>(value,?argName);
????}
}

最后,我們是這樣來打敗黑暗勢力的

public?void?SomeMethod(string?s)
{
????s.InitValidation(
"s")
????????.NotDefault()
????????.NotEmpty()
????????.ShorterThan(
10)
????????.LongerThan(
3);
}

反正本人是找不到更好的方法了,還請大家指教了

轉(zhuǎn)載于:https://www.cnblogs.com/GrayZhang/archive/2008/09/01/1281526.html

總結(jié)

以上是生活随笔為你收集整理的验证能有多优雅的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。