C# 如何重构这一系列空字符串或空字符串测试,使其更小、更干净?
目前,我手动验证了10个属性的这种方法。这里我只展示了3个属性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
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属性重载中指定消息