[英]C# custom attribute validation in console environment
我的問題是關於在C#中使用自定義屬性進行驗證。
我不太明白驗證是如何工作的。 我已經聲明了一個帶有驗證規則的屬性,但是當應該拋出錯誤時它不是。
屬性:
[AttributeUsage(AttributeTargets.Property)]
public class NotNullAttribute : Attribute
{
public bool IsValid(object value)
{
if (value is string && (string)value != "")
{
return false;
}
return true;
}
}
在屬性內部,我檢查屬性是否為string類型,如果它的值是一個空字符串,因為這是我必須檢查的。
任務是檢查屬性是否為string
,如果是空字符串則無效,否則為無效。
我的Person
:
class Person
{
[NotNull]
public string Name { get; set; }
}
我在這里應用自定義屬性。
主要方法:
class Program
{
static void Main(string[] args)
{
Person p1 = new Person();
p1.Name = "";
Console.WriteLine("Validation done");
Console.ReadKey();
}
}
這是我實例化Person
類並為Name
屬性分配一個空字符串的地方。 這是我猜的錯誤應該拋出的地方。
所以我的問題是為什么不應用驗證? 我應該以某種方式從屬性中調用IsValid
方法嗎?
我會對此做一些解釋,謝謝你提前!
屬性本身只是屬性的“裝飾者”。 如果沒有人調用它,它將不會自動執行也不會被使用。
但是,在您的情況下,當您可以使用屬性本身時,我沒有看到使用屬性的重點:
private string _name = "";
public string Name
{
get
{
return _name;
}
set
{
if ( string.IsNullOrEmpty(value) )
{
//throw or fallback
}
else
{
_name = value;
}
}
}
進行基本值驗證正是作業屬性設置者非常適合的。 如果有人使用無效值,您可以拋出異常,或者設置回退值。
如果您仍然希望使用屬性,則仍需要一些代碼來執行驗證。 而且,除非執行驗證,否則任何人都可以為屬性分配任何有效值。
例如, ASP.NET MVC在模型綁定期間使用屬性驗證 - 它檢查綁定模型類上的驗證屬性,並在操作方法開始執行之前對其進行驗證。
這是一個如何使代碼與反射一起工作的簡單示例。
首先是驗證屬性的略微更新版本:
[AttributeUsage(AttributeTargets.Property)]
public class NotNullAttribute : Attribute
{
public bool IsValid(object value)
{
if (!string.IsNullOrEmpty(value as string))
{
return false;
}
return true;
}
}
你的代碼實際上只允許一個null
或""
值,我想這與你想要的相反。 僅當字符串不為null
且不為空時,此版本才有效。
現在在Program
類中創建一個Validate
方法:
private static bool Validate(object model)
{
foreach (var propertyInfo in model.GetType().GetProperties())
{
foreach (var attribute in propertyInfo.GetCustomAttributes(true))
{
var notNullAttribute = attribute as NotNullAttribute;
if (notNullAttribute != null)
{
if (!notNullAttribute.IsValid(propertyInfo.GetValue(model)))
{
return false;
}
}
}
}
return true;
}
這基本上收集傳入參數類型的所有屬性,檢查NotNullAttribute
的屬性的所有屬性,然后針對model
中的當前值執行屬性的IsValid
方法。
最后,您可以從Main
調用它:
static void Main(string[] args)
{
Person p1 = new Person();
p1.Name = "d";
if (Validate(p1))
{
Console.WriteLine("Valid");
}
else
{
Console.WriteLine("Invalid");
}
Console.WriteLine("Validation done");
Console.ReadKey();
}
現在,如果您計划添加更多驗證屬性,我將首先創建一個接口:
public interface IValidationAttribute
{
bool IsValid(object value);
}
然后從IValidationAttribute
派生所有驗證屬性,並在Validate
方法中使用IValidationAttribute
代替NotNullAttribute
。 通過這種方式,代碼變得更加面向未來,因為您可以隨時對接口進行編程並隨時添加新的驗證屬性。
public class BankAccount
{
public enum AccountType
{
Saving,
Current
}
[Required(ErrorMessage="First Name Required")]
[MaxLength(15,ErrorMessage="First Name should not more than 1`5 character")]
[MinLength(3,ErrorMessage="First Name should be more than 3 character")]
public string AccountHolderFirstName { get; set; }
[Required(ErrorMessage="Last Name Required")]
[MaxLength(15,ErrorMessage="Last Name should not more than 1`5 character")]
[MinLength(3,ErrorMessage="Last Name should be more than 3 character")]
public string AccountHolderLastName { get; set; }
[Required]
[RegularExpression("^[0-9]+$", ErrorMessage = "Only Number allowed in AccountNumber")]
public string AccountNumber { get; set; }
public AccountType AcType { get; set; }
[AccountBalaceCheckAttribute]
public double AccountBalance { get; set; }
}
如何驗證
public class GenericValidator
{
public static bool TryValidate(object obj, out ICollection<ValidationResult> results)
{
var context = new ValidationContext(obj, serviceProvider: null, items: null);
results = new List<ValidationResult>();
return Validator.TryValidateObject(
obj, context, results,
validateAllProperties: true
);
}
}
例
static void Main(string[] args)
{
var bankAccount = new BankAccount();
ICollection<ValidationResult> lstvalidationResult;
bool valid = GenericValidator.TryValidate(bankAccount, out lstvalidationResult);
if (!valid)
{
foreach (ValidationResult res in lstvalidationResult)
{
Console.WriteLine(res.MemberNames +":"+ res.ErrorMessage);
}
}
Console.ReadLine();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.