在ToString方法中使用反射

时间:2016-02-24 22:46:37

标签: c#

我正在尝试使用反射来清理我的班级。

private List<String> centers = new List<String>();
private List<String> leftWingers = new List<String>();
private List<String> rightWingers = new List<String>();
private List<String> defencemen = new List<String>();
private List<String> goalies = new List<String>();
private List<String> bench = new List<String>();

public List<String> Centers { get { return centers; } set { centers = value; } }
public List<String> LeftWingers { get { return leftWingers; } set { leftWingers = value; } }
public List<String> RightWingers { get { return rightWingers; } set { rightWingers = value; } }
public List<String> Defencemen { get { return defencemen; } set { defencemen = value; } }
public List<String> Goalies { get { return goalies; } set { goalies = value; } }
public List<String> Bench { get { return bench; } set { bench = value; } }

public String ToString()
{
    String output = "";

    System.Reflection.PropertyInfo[] properties = this.GetType().GetProperties();

    foreach (System.Reflection.PropertyInfo property in properties)
    {
        int count = 0;
        foreach (String value in property)
        {
            count++;
            output += "C" + count + ": " + value + System.Environment.NewLine;
        }

    }
}

这不起作用。我似乎无法循环每个属性的项目,因为它们是集合。有没有办法从PropertyInfo对象中获取字符串列表的内容?

4 个答案:

答案 0 :(得分:3)

  1. 它们不是属性,而是字段,因此您需要使用GetFields
  2. 您需要告诉GetFields方法您想获得private 会员使用BindingFlags,否则默认会查找publicinstance成员。

    var fields = this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
    

答案 1 :(得分:1)

好吧,如果你真的想要属性,首先是你的代码没有属性。你只有一些属性。对于样本:

,如果是这种情况,请更改属性
private List<String> centers { get; set; }
private List<String> leftWingers { get; set; }
private List<String> rightWingers { get; set; }
private List<String> defencemen { get; set; }
private List<String> goalies { get; set; }
private List<String> bench { get; set; }

然后你可以将它们作为集合和读取值读取,样本:

public String ToString()
{
    StringBuilder output = new StringBuilder();

    System.Reflection.PropertyInfo[] properties = this.GetType().GetProperties();

    foreach (System.Reflection.PropertyInfo property in properties)
    {
        var values = property.GetValue(this, null) as IEnumerable<String>;

        if (values != null) 
        {
            int count = 0;
            foreach (String value in values)
            {
                count++;
                output.AppendLine(string.Format("C{0}: {1}", count, value));
            }
        }
    }

    return output.ToString();
}

另一种情况是读取字段并避免将其转换为属性。看看Selman22的回答!

答案 2 :(得分:1)

使用Enumerable.ConcatEnumerable.Selectstring.Join可以大大简化您的问题:

IEnumerable<string> allItems = centers.Concat(leftWingers)
                                      .Concat(rightWingers)
                                      .Concat(defencemen)
                                      .Concat(goalies)
                                      .Concat(bench);

return string.Join
(
    Environment.NewLine, 
    allItems.Select((item, index) => $"C {index + 1}: {item}")
);

答案 3 :(得分:0)

这些是字段,因此您需要使用GetFields来获取它们。请注意,反射返回的字段只是元数据,它们不包含您需要的数据。

要获取数据,您需要使用GetValue方法获取当前对象的字段值。

然后,为了能够在字段中枚举集合,您需要将其转换为IEnumerable<string>

以下是它的样子:

public String ToString()
{
    String output = "";

    var fields = this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);

    foreach (var field in fields)
    {
        int count = 0;
        foreach (String value in (IEnumerable<string>) field.GetValue(this))
        {
            count++;
            output += "C" + count + ": " + value + System.Environment.NewLine;
        }
    }
    return output;
}    

由于您只有6个集合,因此您可以拥有不涉及反射的解决方案。这是一个例子:

public String ToString()
{
    String output = "";

    var collections = new[] {centers, leftWingers, rightWingers, defencemen, goalies, bench};

    foreach (var field in collections)
    {
        int count = 0;
        foreach (String value in field)
        {
            count++;
            output += "C" + count + ": " + value + System.Environment.NewLine;
        }
    }
    return output;
}    

请考虑使用StringBuilder代替string。使用string连接字符串会损害性能。