Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
控制台环境中的C#自定义属性验证_C#_Validation_Attributes - Fatal编程技术网

控制台环境中的C#自定义属性验证

控制台环境中的C#自定义属性验证,c#,validation,attributes,C#,Validation,Attributes,我的问题是关于在C#中使用自定义属性进行验证 我不太明白验证是如何工作的。我已经声明了一个属性,其中包含验证规则,但是当应该抛出错误时,它不会抛出 属性: [AttributeUsage(AttributeTargets.Property)] public class NotNullAttribute : Attribute { public bool IsValid(object value) { if (value is string && (

我的问题是关于在C#中使用自定义属性进行验证

我不太明白验证是如何工作的。我已经声明了一个属性,其中包含验证规则,但是当应该抛出错误时,它不会抛出

属性:

[AttributeUsage(AttributeTargets.Property)]
public class NotNullAttribute : Attribute
{
    public bool IsValid(object value)
    {
        if (value is string && (string)value != "")
        {
            return false;
        }
        return true;
    }

}
在属性内部,我检查属性是否为string类型,其值是否为空字符串,因为这是我必须检查的

任务是检查属性是否为
字符串
,如果为空字符串,则该属性无效,否则为空字符串

我的
班级:

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;
      }
   }
}
执行基本值验证正是作业属性设置器的优势所在。如果有人使用了无效值,您可以抛出异常,或者设置回退值

如果仍然希望使用属性,则仍然需要一些代码来执行验证本身。而且,任何人都可以为属性指定任何有效值,除非执行了验证

例如,在模型绑定期间使用属性验证—它检查绑定模型类上的验证属性,并在action方法开始执行之前进行验证

属性验证示例 下面是一个简单的示例,说明如何使代码与反射一起工作

首先,这里是验证属性的稍微更新版本:

[AttributeUsage(AttributeTargets.Property)]
public class NotNullAttribute : Attribute
{
    public bool IsValid(object value)
    {
        if (!string.IsNullOrEmpty(value as string))
        {
            return false;
        }
        return true;
    }
}
您的代码实际上只允许一个
null
值,我想这与您想要的正好相反。此版本仅在字符串不为空且不为空时有效

现在在
程序
类中创建一个
验证
方法:

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
属性的所有属性,然后根据
模型的当前值执行属性的
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; }  
   }  
但是,在您的情况下,当您可以使用属性本身时,我不认为使用属性有什么意义:

private string _name = "";

public string Name
{
   get
   {
      return _name;
   }
   set
   {
      if ( string.IsNullOrEmpty(value) )
      {
          //throw or fallback
      }
      else
      {
          _name = value;
      }
   }
}
执行基本值验证正是作业属性设置器的优势所在。如果有人使用了无效值,您可以抛出异常,或者设置回退值

如果仍然希望使用属性,则仍然需要一些代码来执行验证本身。而且,任何人都可以为属性指定任何有效值,除非执行了验证

例如,在模型绑定期间使用属性验证—它检查绑定模型类上的验证属性,并在action方法开始执行之前进行验证

属性验证示例 下面是一个简单的示例,说明如何使代码与反射一起工作

首先,这里是验证属性的稍微更新版本:

[AttributeUsage(AttributeTargets.Property)]
public class NotNullAttribute : Attribute
{
    public bool IsValid(object value)
    {
        if (!string.IsNullOrEmpty(value as string))
        {
            return false;
        }
        return true;
    }
}
您的代码实际上只允许一个
null
值,我想这与您想要的正好相反。此版本仅在字符串不为空且不为空时有效

现在在
程序
类中创建一个
验证
方法:

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
属性的所有属性,然后根据
模型的当前值执行属性的
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  
        );  
    }  
}
公共类GenericValidator
{  
公共静态bool TryValidate(对象对象对象,输出ICollection结果)
{  
var context=newvalidationcontext(obj,serviceProvider:null,items:null);
结果=新列表();
返回验证程序.TryValidateObject(
目标、背景、结果、,
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();  
}  
static void Main(字符串[]args)
{  
var bankAccount=新银行账户();
i收集LST验证结果;
bool valid=genericvalidate.TryValidate(bankAccount,out lstvalidationResult);
如果(!有效)
{  
对于