【问题标题】:Using reflection in ToString method [closed]在 ToString 方法中使用反射 [关闭]
【发布时间】:2016-02-25 09:53:13
【问题描述】:

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

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 对象中获取字符串列表的内容?

【问题讨论】:

  • 这些是字段,而不是属性 - 类似于 this.GetType().GetFields().Select(f =&gt; f.GetValue(this))?
  • 只有六个系列吗?为什么要使用反射?
  • 改用 GetFields()
  • 有很多方法可以改进该代码……而反射最多应该是要尝试的事情列表中的最后一个。 IE。只需将所有数组放入集合中就足以简化代码而无需反射。
  • @AlexeiLevenkov 这可能是一个简化的例子。对 this.GetType() 的调用也允许检索在派生类型上定义的成员。当然不是一个好方法,但是 this.GetType() 会对派生类型产生影响,清除基类中的集合集合不会

标签: c#


【解决方案1】:
  1. 它们不是属性,它们是字段,所以你需要使用GetFields
  2. 你需要告诉GetFields方法你想得到private 成员使用BindingFlags,否则默认查找publicinstance成员。

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

【讨论】:

    【解决方案2】:

    好吧,如果你真的想要属性,第一件事就是你的代码中没有属性。你只有一些属性。如果是这种情况,请更改其属性,例如:

    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 的答案!

    【讨论】:

    • 那些也不是属性......它们是字段。
    • 是的,我知道,我只是建议将其更改为属性。在另一种情况下,我建议查看 Selman22 的答案!
    • "你只有一些属性。" Felipe Oriani,5 分钟前...
    • 这就是我要找的。更具体地说,as IEnumerable&lt;String&gt; 部分。对于最初的困惑,我深表歉意。
    【解决方案3】:

    使用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}")
    );
    

    【讨论】:

      【解决方案4】:

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

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

      然后,为了能够枚举字段中的集合,您需要将其转换为IEnumerable&lt;string&gt;

      下面是它的样子:

      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 连接字符串会影响性能。

      【讨论】:

        猜你喜欢
        • 2013-04-28
        • 1970-01-01
        • 2023-04-09
        • 2011-01-02
        • 2012-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多