Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.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#_String_Validation_If Statement_Refactoring - Fatal编程技术网

C# 如何重构这一系列空字符串或空字符串测试,使其更小、更干净?

C# 如何重构这一系列空字符串或空字符串测试,使其更小、更干净?,c#,string,validation,if-statement,refactoring,C#,String,Validation,If Statement,Refactoring,目前,我手动验证了10个属性的这种方法。这里我只展示了3个属性 if (string.IsNullOrEmpty(account.Name)) { return BadRequest("Name is required"); } if (string.IsNullOrEmpty(account.Nationality)) { return BadRequest("Nationality is required"); } if (str

目前,我手动验证了10个属性的这种方法。这里我只展示了3个属性

if (string.IsNullOrEmpty(account.Name))
{
    return BadRequest("Name is required");
}

if (string.IsNullOrEmpty(account.Nationality))
{
    return BadRequest("Nationality is required");
}


if (string.IsNullOrEmpty(account.Phone))
{
    return BadRequest("Phone is required");
}

我相信有更好的方法来重构代码,以减少API验证的代码行。

假设您有这样一个类,并且希望检查所有rw公共字符串属性:

using System.Linq;
using System.Reflection;

class Account
{
  public string Name { get; set; }
  public string Nationality { get; set; }
  public string Phone { get; set; }
  public int Value { get; set; }
}
我们可以使用反射和Linq进行重构,如下所示:

var account = new Account();
account.Name = "Name";

var type = account.GetType();

var flags = BindingFlags.Public 
          | BindingFlags.Instance 
          | BindingFlags.GetProperty 
          | BindingFlags.SetProperty;

var property = type.GetProperties(flags)
                   .Where(p => p.PropertyType == typeof(string))
                   .Where(p => string.IsNullOrEmpty((string)p.GetValue(account)))
                   .Select(p => p.Name)
                   .FirstOrDefault();

if ( property != null )
  return BadRequest($"{property} is required");
我们将该类型的所有属性都作为公共实例,而不是静态的,并且具有getter和setter,然后对所需的字符串类型进行筛选,并检查该值以选择第一个找到的字符串的名称,否则结果为null

要不检查所有字符串属性,我们可以使用自定义的
Ignore
属性:

class IgnoreAttribute : Attribute
{
}

class Account
{
  [Ignore]
  public string MyString { get; set; }
  public string Name { get; set; }
  public string Nationality { get; set; }
  public string Phone { get; set; }
  public int Value { get; set; }
}
Linq查询现在是:

var property = type.GetProperties(flags)
                   .Where(p => p.PropertyType == typeof(string))
                   .Where(p => p.GetCustomAttribute(typeof(IgnoreAttribute)) == null)
                   .Where(p => string.IsNullOrEmpty((string)p.GetValue(account)))
                   .Select(p => p.Name)
                   .FirstOrDefault();
正如@Charles提到的,
RequiredAttribute
也可以改为:

using System.ComponentModel.DataAnnotations;

class Account
{
  public string MyString { get; set; }
  [Required]
  public string Name { get; set; }
  [Required]
  public string Nationality { get; set; }
  [Required]
  public string Phone { get; set; }
  public int Value { get; set; }
}

var property = type.GetProperties(flags)
                   .Where(p => p.PropertyType == typeof(string))
                   .Where(p => p.GetCustomAttribute(typeof(RequiredAttribute)) != null)
                   .Where(p => string.IsNullOrEmpty((string)p.GetValue(account)))
                   .Select(p => p.Name)
                   .FirstOrDefault();
或者实际上这里的
NotNullOrEmpty
属性是合适的:

class NotNullOrEmptyAttribute : Attribute
{
}

class Account
{
  public string MyString { get; set; }
  [NotNullOrEmpty]
  public string Name { get; set; }
  [NotNullOrEmpty]
  public string Nationality { get; set; }
  [NotNullOrEmpty]
  public string Phone { get; set; }
  public int Value { get; set; }
}

var property = type.GetProperties(flags)
                   .Where(p => p.PropertyType == typeof(string))
                   .Where(p => p.GetCustomAttribute(typeof(NotNullOrEmptyAttribute)) != null)
                   .Where(p => string.IsNullOrEmpty((string)p.GetValue(account)))
                   .Select(p => p.Name)
                   .FirstOrDefault();


您可以使用System.ComponentModel.DataAnnotations命名空间中的必需属性装饰属性

然后验证您的模型状态

if (!ModelState.IsValid)
{
   return BadRequest(ModelState);
} 

编写一个单独的函数可以是一个解决方案。您对此有何想法?目前尚不清楚您要删除的复制内容到底是什么。你想避免到处写这些精确的3 if支票吗?如果是,请提取一个方法。你不喜欢一直写
字符串.IsNullOrEmpty
?如果是这样,请创建一个键值对列表,其中包含要检查的值和错误消息,并在其中循环,直到找到一个空/空值。@Steve我更新了我的答案,起初它是垃圾,并投票重新打开。没有答案是垃圾。我投你的票:)谢谢如果使用Required属性,这类问题会更好,错误响应将与手动验证不同。你可以在Required属性重载中指定消息