[英]How to determine if a property is required?
给定一个 class 这样的东西:
public class MyClass : ValidationValues
{
public string Foo { get; set; }
[Required(ErrorMessage = "Bar is required.")]
public string Bar { get; set; }
// and many more
}
public class ValidationValues
{
public bool IsValid { get; set; } = true;
public string InvalidReason { get; set; }
}
我需要确定是否需要属性,同时将其作为通用列表循环。 通过查看 Watch,我找到了一种方法,但感觉很笨拙,我认为它应该更简单。
对于某些上下文,此逻辑在 Azure Function 内部。因此没有视图,没有 MVC 等。function 是一个 Blob 存储触发器,它使用 | 拾取 a.CSV 文件。 被反序列化为List<MyClass>
的定界列表。 我们不想在反序列化时强制执行Required
属性,因为我们想要更精细的控制。
所以给出这样的文件:
value1 | |
value2 | something
最终返回给用户的是这样的:
[
{
"foo": "value1",
"bar": "",
"isValid": false,
"InvalidReason" : "Bar is required"
},
{
"foo": "value2",
"bar": "something",
"isValid": true,
"InvalidReason" : ""
}
]
这是我现在拥有的:
foreach (T item in itemList) // where 'itemList' is a List<T> and in this case T is MyClass
{
foreach (PropertyInfo property in item.GetType().GetProperties())
{
if (property.CustomAttributes.ToList()[0].AttributeType.Name == "RequiredAttribute")
{
// validate, log, populate ValidationValues
}
}
}
这是我不喜欢的部分:
property.CustomAttributes.ToList()[0].AttributeType.Name == "RequiredAttribute"
有时当我想出一个编码挑战时,我告诉自己,“就是这样”。 但在这种情况下,我很确定这不是方法。
反射很慢——或者至少,相对较慢。 所以; 这里最重要的是:不要对每个实例都这样做; 您可以按Type
缓存它(来自GetType()
,或者您可以只使用T
而从不检查每个实例的.GetType()
,具体取决于您的意图。这包括缓存给定类型存在的属性,以及哪些是required. 然而,真正的奖励点是使用元编程来发出 - 无论是在运行时,还是在构建时通过“生成器” - 一种完全按照你想要的方式执行的方法,没有任何循环,测试等;即在这种情况下,它可能会发出一个方法,它相当于
void ValidateMyClass(MyClass obj)
{
if (string.IsNullOrWhitespace(obj.Bar))
{
DoSomething("Bar is required.");
}
}
这可以通过多种方式完成,包括Expression
API、发出 API ( ILGenerator
)、发出 C# 并使用CSharpCodeProvider
或“生成器”API。
您可以使用GetCustomAttibute
重写该行:
using System.Reflection;
foreach (T item in itemList) // where 'itemList' is a List<T> and in this case T is MyClass
{
foreach (PropertyInfo property in item.GetType().GetProperties())
{
var attribute = property.GetCustomAttibute<RequiredAttribute>();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.