簡體   English   中英

控制台環境中的C#自定義屬性驗證

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM