使用反射在C#中检查属性是否为列表

4

我目前卡在输出对象值上。其中一些对象具有List<string>属性,使用ToString()方法会引起问题。以下是我在基类中使用的代码,用于将属性的名称和值组合成一个字符串。

public override string ToString()
    {
        string content = "";
        foreach (var prop in this.GetType().GetProperties())
        {
            if (prop.PropertyType is IList<string> && prop.GetType().IsGenericType && prop.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(List<>)))
                content += prop.Name + " = " + PrintList((List<string>)prop.GetValue(this));
            else
            content += prop.Name + " = " + prop.GetValue(this) + "\r\n";
        }
        content += "\r\n";
        return content;
    }

    private string PrintList(List<string> list)
    {
        string content = "[";
        int i = 0;
        foreach (string element in list)
        {
            content += element;
            if (i == list.Count)
                content += "]";
            else
                content += ", ";
        }
        return content;
    }

无论如何,检查属性是否为列表不起作用。这可能是一个愚蠢的问题或者使用反射的一种不好的方式,但我对此还很陌生,并且将感激任何帮助来弄清楚发生了什么。

尝试使用IEnumerable。 - Steve
5
这段代码的意思是:prop.PropertyType是否可以被视为IList<string>类型。 - Nkosi
2个回答

4
public override string ToString()
{
    StringBuilder content = new StringBuilder();
    foreach (var prop in this.GetType().GetProperties())
    {
        var propertyType = prop.PropertyType;
        var propertyValue = prop.GetValue(this);
        if (propertyValue != null)
        {
            if (propertyValue is IEnumerable<string>)
                content.AppendFormat("{0} = {1}", prop.Name, PrintList(propertyValue as IEnumerable<string>));
            else
                content.AppendFormat("{0} = {1}", prop.Name, propertyValue.ToString());
        }
        else
            content.AppendFormat("{0} = null", prop.Name);
        content.AppendLine();
    }

    return content.ToString();
}

private string PrintList(IEnumerable<string> list)
{
    var content = string.Join(",", list.Select(i => string.Format("[{0}]", i)));
    return content;
}

完美运行!谢谢。 - P. Edge

3
我会这样做:
var property = prop.GetValue(this);

// try to cast as IEnumerable<string> -- will set to null if it's not.
var propertyStrings = property as IEnumerable<string>;
if (propertyStrings != null) {
    foreach(var s in propertyStrings) {
        // do something here with your strings.    
    }   
}

此外,不要使用+操作符来连接字符串,可以考虑使用StringBuilder,它在内存和速度方面都更优秀。

我看到在string上使用+=的低效率,但为什么+会有问题? - cadaniluk
@Downvoter 和 += 一样。要执行 a = b + c,需要在内存中分配字符串 b + c,然后将其赋值给 a。例如,添加 1M 个字符串需要 1M 个字符串分配,每次分配时,随着结果变得越来越大,分配变得越来越昂贵。如果所有字符串的长度都为 s,则添加的时间复杂度为 O(s + 2s + 3s + 4s + 5s +6s... 1000000s),我认为这是 O(s.n^2)。StringBuilder 预先分配内存,在用完时加倍数组大小,因此添加一个字符串的时间复杂度为 O(s),对于所有字符串,时间复杂度为 O(s.n)。 - Steve Cooper
谢谢您提供 StringBuilder 的提示!@SteveCooper - P. Edge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接