繁体   English   中英

基于类对象列表,如何创建有效属性名称列表?

[英]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.NamePropertyInfo.PropertyTypePropertyInfo.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();
    }
}

笔记:

演示小提琴在这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM