[英]Based on a list of class objects, how to create a list of valid property names?
我有一个如下所示的Data
类。
public class Data
{
public string Dt1 { get; set; }
public string Dt2 { get; set; }
public string Dt3 { get; set; }
public string Dt4 { get; set; }
public string Dt5 { get; set; }
}
以及它的类对象列表,具有以下示例数据。
var list = new List<Data>
{
new Data() { Dt1 = "DtA", Dt2 = string.Empty, Dt3 = "-", Dt5 = "DtC" },
new Data() { Dt1 = "DtB", Dt2 = string.Empty, Dt3 = string.Empty, Dt5 = "-" },
new Data() { Dt1 = "DtC", Dt2 = "-", Dt5 = "-" },
new Data() { Dt1 = "DtD", Dt2 = string.Empty, Dt3 = "DtX", Dt5 = string.Empty },
new Data() { Dt1 = "DtE", Dt3 = "-" }
};
我有一个“无效”字符串列表,如下所示。
var invalid = new List<string>() { string.Empty, "-", null };
现在,我想从上面的列表中找出至少包含一个有效字符串的属性名称,然后使用这些属性名称创建一个List<string>
。 如果我们考虑上面的样本数据,你可以看到,
Dt1
值都有效。Dt2
值都无效。Dt3
至少有一个有效值。Dt4
从未被赋值,因此,所有值都是无效的。Dt5
至少有一个有效值。所以,我的结果列表应该是
Dt1、Dt3、Dt5
我的方法是编写一个函数来识别字符串中是否至少有一个有效值,然后使用它检查列表的每个属性。
public static bool IsDataValid(List<string> data, List<string> invalid)
{
foreach (var item in data)
{
if (!invalid.Contains(item))
{
return true;
}
}
return false;
}
然后,
var invalid = new List<string>() { string.Empty, "-", null };
var result = new List<string>();
if (IsDataValid(list.Select(x => x.Dt1).ToList(), invalid))
{
result.Add("Dt1");
}
if (IsDataValid(list.Select(x => x.Dt2).ToList(), invalid))
{
result.Add("Dt2");
}
if (IsDataValid(list.Select(x => x.Dt3).ToList(), invalid))
{
result.Add("Dt3");
}
if (IsDataValid(list.Select(x => x.Dt4).ToList(), invalid))
{
result.Add("Dt4");
}
if (IsDataValid(list.Select(x => x.Dt5).ToList(), invalid))
{
result.Add("Dt5");
}
这当然有效,但对我的口味来说有点“难看”。 此外,我的实际Data
类有 20 多个属性,所以我必须使用 20 个if
语句,这又是一种糟糕的设计。
我想知道是否有另一种方法,特别是我不必对 if 语句进行“硬编码”的方法。 类似于以下内容,我可以在其中迭代类的属性并找出列表中的哪些是有效的。
foreach (var prop in typeof(Data).GetProperties())
{
// How do I do a `.Select()` here?
}
您可以使用Type.GetProperties()
获取您的类型的所有属性,然后使用PropertyInfo.Name
、 PropertyInfo.PropertyType
和PropertyInfo.GetValue()
获取集合中每个Data
项的所有字符串属性的名称和值。 有了它,您可以收集具有至少一个有效值的所有属性的名称,如下所示:
public static class ValidationExtensions
{
public static ICollection<string> ValidProperties<TObject, TValue>(this IEnumerable<TObject> items, Predicate<TValue> isValid)
{
var properties = typeof(TObject).GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => typeof(TValue).IsAssignableFrom(p.PropertyType))
.Where(p => p.CanRead && p.GetIndexParameters().Length == 0 && p.GetGetMethod() != null)
.ToList();
var set = new HashSet<string>();
foreach (var i in items) // Only iterate through the items once.
foreach (var p in properties)
{
if (set.Contains(p.Name)) // Do not call GetValue() if not necessary, it's expensive.
continue;
if (isValid((TValue)p.GetValue(i)))
set.Add(p.Name);
}
// Return properties in order
return properties.Select(p => p.Name).Where(n => set.Contains(n)).ToList();
}
}
笔记:
Delegate.CreateDelegate
访问给定类型的属性值,例如,如如何为 .NET 属性创建委托的答案中所示? .演示小提琴在这里。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.