我有一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属性创建委托的答案所示。。演示在这里摆弄。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句