[英]Get value of an Attribute-decorated property
我想在課堂上做一些驗證,所以我想我可以使用屬性。 像這樣:
public class someClass
{
[Lenght(200)]
public string someStr { get; set; }
}
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
sealed class Lenght : Attribute
{
public Lenght(int Lenght)
{
//some code
}
}
但我知道我不能這樣做,因為這不是屬性的工作方式。 而且,如果有辦法,它會使用我想要避免的某種重反射和kludges。
我想要做的驗證是這樣的:
public class someClass
{
public string someStr
{
get
{
return _someStr;
}
set
{
if (value.Length > 200)
{
throw new Exception("Max Length is 200!");
}
else _someStr = value;
}
}
private string _someStr { get; set; }
}
但我想更快地完成它,沒有所有這些代碼。 我想要與使用屬性一樣快。
我有辦法做到這一點嗎?
屬性的目的是將關於程序集,類型,成員,參數等的元數據聲明到其他組件,工具,編譯器等。當然,你可以做你所要求的,但這將涉及反思自己哪個要像在第二個例子中那樣斷言價值,還有很長的路要走。
您應該考慮的是一個驗證框架,其中包含所有這些內容,並允許您單獨和外部驗證。
有許多驗證框架可供選擇。 我最喜歡的兩個流行的是FluentValidation和Enterprise Library的Validation Application Block 。
另一方面,也許你只是在尋找一個好的Guard類或Code Contracts 。 這些用於與驗證不同的目的(參見合同設計 )。 你可以想象將屬性(我建議重用數據注釋 )與一些面向方面的編程相結合,以便以聲明方式為你完成保護(參見PostSharp )。 然而,這可能只是炫耀:)。
您可以創建一個將該字段作為ref
參數的方法:
public static void SetWithMaxLength(ref string field, string value, int maxLength)
{
if(value.Length > maxLength) throw new Exception("Max length is " + maxLength);
field = value;
}
然后你可以把你的二傳手寫成:
set
{
SetWithMaxLength(ref this._someStr, value, 200);
}
通常你不會用屬性做這樣的事情,但它是可能的,雖然不值得推薦。 使用風險自負:)(如果屬性沒有使用LengthAttribute
修飾,你會放松地獄:))
public interface AttributeValidator
{
void CheckOk(object value);
}
public class LenghtAttribute : Attribute, AttributeValidator
{
public int MaxLength { get; private set; }
public LenghtAttribute(int lenght)
{
this.MaxLength = lenght;
}
public void CheckOk(object value)
{
var str = value as string;
if (str != value)
throw new Exception("Not a string!");
if (str != null && str.Length > MaxLength)
throw new Exception("To long!");
}
}
public class DoesNotContain : Attribute, AttributeValidator
{
public string Chars { get; private set; }
public DoesNotContain(string chars)
{
this.Chars = chars;
}
public void CheckOk(object value)
{
var str = value as string;
if (str != value)
throw new Exception("Not a string!");
if (str != null && Chars.Any(c => str.Contains(c)))
throw new Exception("Contains forbidden character!");
}
}
public class SomeClass
{
private string _someString;
[Lenght(200)]
[DoesNotContain("$#2")]
public string SomeString
{
get { return _someString; }
set
{
Utils.Validate("SomeString", this, value);
_someString = value;
}
}
}
public static class Utils
{
public static void Validate(string property, object instance, string value)
{
var validators = instance.GetType().GetProperty(property)
.GetCustomAttributes(false).OfType<AttributeValidator>();
foreach (var validator in validators)
validator.CheckOk(value);
}
}
編輯我擴展了這個例子。 仍然是一個可怕的解決方案,但它的確有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.