【问题标题】:How can you loop over the properties of a class?你如何循环一个类的​​属性?
【发布时间】:2010-11-25 11:34:32
【问题描述】:

c# 中有没有办法循环遍历类的属性?

基本上我有一个包含大量属性的类(它基本上保存大型数据库查询的结果)。 我需要将这些结果输出为 CSV 文件,因此需要将每个值附加到字符串中。

手动将每个值附加到字符串的明显方法,但是有没有一种方法可以有效地循环遍历结果对象并依次为每个属性添加值?

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    当然;您可以通过多种方式做到这一点;从反射开始(注意,这很慢 - 不过对于中等数量的数据来说还可以):

    var props = objectType.GetProperties();
    foreach(object obj in data) {
        foreach(var prop in props) {
            object value = prop.GetValue(obj, null); // against prop.Name
        }
    }
    

    但是;对于大量数据,提高效率是值得的;例如,在这里我使用Expression API 来预编译一个看起来写入每个属性的委托 - 这里的优点是不会在每行基础上进行反射(对于大量数据,这应该会明显更快):

    static void Main()
    {        
        var data = new[] {
           new { Foo = 123, Bar = "abc" },
           new { Foo = 456, Bar = "def" },
           new { Foo = 789, Bar = "ghi" },
        };
        string s = Write(data);        
    }
    static Expression StringBuilderAppend(Expression instance, Expression arg)
    {
        var method = typeof(StringBuilder).GetMethod("Append", new Type[] { arg.Type });
        return Expression.Call(instance, method, arg);
    }
    static string Write<T>(IEnumerable<T> data)
    {
        var props = typeof(T).GetProperties();
        var sb = Expression.Parameter(typeof(StringBuilder));
        var obj = Expression.Parameter(typeof(T));
        Expression body = sb;
        foreach(var prop in props) {            
            body = StringBuilderAppend(body, Expression.Property(obj, prop));
            body = StringBuilderAppend(body, Expression.Constant("="));
            body = StringBuilderAppend(body, Expression.Constant(prop.Name));
            body = StringBuilderAppend(body, Expression.Constant("; "));
        }
        body = Expression.Call(body, "AppendLine", Type.EmptyTypes);
        var lambda = Expression.Lambda<Func<StringBuilder, T, StringBuilder>>(body, sb, obj);
        var func = lambda.Compile();
    
        var result = new StringBuilder();
        foreach (T row in data)
        {
            func(result, row);
        }
        return result.ToString();
    }
    

    【讨论】:

    • 感谢您的回答,但对访问另一个类的属性有疑问,例如:如果我有 List&lt;Booking&gt; 其中 Booking 是一个类,而 Cab 作为另一个类,我将其引用为预订类别中的财产。我如何通过foreach 解析来获取 Cab 类的属性...谢谢
    • 现在我可以获取Booking 类的每个属性,如foreach(var porp in obj2Insert) { //using prop.GetValue() to return the result and store it. } 但是,这会遍历Booking Entity 的整个属性,我不需要......!这就是我被打动的地方......!
    • 感谢您提供这个创造性的解决方案 :) 您能指定“中等数量的数据”吗?您能否粗略估计一下使非反射解决方案值得付出努力总共需要多少属性?
    • @buddybubble 它也被行倍增,而不仅仅是属性。对于“多少”-恐怕您必须进行简介
    • @Marc,感谢您为大量数据提供出色的 sn-p 代码。我对表达式不太熟悉,能否请您简要解释一下第二个代码是如何工作的?
    【解决方案2】:
    foreach (PropertyInfo prop in typeof(MyType).GetProperties())
    {
        Console.WriteLine(prop.Name);
    }
    

    【讨论】:

      【解决方案3】:

      我在此页面上尝试了各种建议,但我无法让其中任何一个发挥作用。我从最佳答案开始(您会注意到我的变量名称相似),然后我自己完成了它。这就是我要做的工作 - 希望它可以帮助其他人。

      var prop = emp.GetType().GetProperties();     //emp is my class
          foreach (var props in prop)
            {
              var variable = props.GetMethod;
      
              empHolder.Add(variable.Invoke(emp, null).ToString());  //empHolder = ArrayList
            }
      

      ***我应该提一下,这仅在您使用 get;set; 时才有效。 (公共)属性。

      【讨论】:

      • 这很棒。这会产生值:string value = variable.Invoke(emp, null).ToString();
      【解决方案4】:

      您可以列出对象的属性

        IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();
      

      然后使用 foreach 导航到列表中..

         foreach (var property in properties)
                  {
                    here's code...
                  }
      

      【讨论】:

        【解决方案5】:

        使用类似的东西

        StringBuilder csv = String.Empty;
        PropertyInfo[] ps this.GetType().GetProperties();
        foreach (PropertyInfo p in ps)
        {
            csv.Append(p.GetValue(this, null);
            csv.Append(",");
        }
        

        【讨论】:

          【解决方案6】:
          var csv = string.Join(",",myObj
              .GetType()
              .GetProperties(BindingFlags.Public | BindingFlags.Instance)
              .Select(p => p.GetValue(myObj, null).ToString())
              .ToArray());
          

          【讨论】:

            【解决方案7】:

            这是在 vb.net 中循环属性的方法,与 c# 中的概念相同,只是翻译语法:

             Dim properties() As PropertyInfo = Me.GetType.GetProperties(BindingFlags.Public Or BindingFlags.Instance)
                        If properties IsNot Nothing AndAlso properties.Length > 0 Then
                            properties = properties.Except(baseProperties)
                            For Each p As PropertyInfo In properties
                                If p.Name <> "" Then
                                    p.SetValue(Me, Date.Now, Nothing)  'user p.GetValue in your case
                                End If
                            Next
                        End If
            

            【讨论】:

              【解决方案8】:

              循环遍历属性

              Type t = typeof(MyClass);
              foreach (var property in t.GetProperties())
              {                
              }
              

              【讨论】:

                【解决方案9】:
                string target = "RECEIPT_FOOTER_MESSAGE_LINE" + index + "Column";
                PropertyInfo prop = xEdipV2Dataset.ReceiptDataInfo.GetType().GetProperty(target);
                Type t = xEdipV2Dataset.ReceiptDataInfo.RECEIPT_FOOTER_MESSAGE_LINE10Column.GetType();
                prop.SetValue(t, fline, null);
                

                注意:目标对象必须是可设置的

                【讨论】:

                • 请补充说明。
                • @OhBeWisei 已更改我的代码,现在无需解释
                【解决方案10】:
                string notes = "";
                
                Type typModelCls = trans.GetType(); //trans is the object name
                foreach (PropertyInfo prop in typModelCls.GetProperties())
                {
                    notes = notes + prop.Name + " : " + prop.GetValue(trans, null) + ",";
                }
                notes = notes.Substring(0, notes.Length - 1);
                

                然后我们可以将注释字符串作为列写入日志表或文件。您必须使用 System.Reflection 才能使用 PropertyInfo

                【讨论】:

                  【解决方案11】:

                  从简单的类对象中获取属性值......

                  class Person
                  {
                      public string Name { get; set; }
                      public string Surname { get; set; }
                      public int Age { get; set; }
                  }
                  
                  class Program
                  {
                      static void Main(string[] args)
                      {
                          var person1 = new Person
                          {
                              Name = "John",
                              Surname = "Doe",
                              Age = 47
                          };
                  
                          var props = typeof(Person).GetProperties();
                          int counter = 0;
                  
                          while (counter != props.Count())
                          {
                              Console.WriteLine(props.ElementAt(counter).GetValue(person1, null));
                              counter++;
                          }
                      }
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 2011-03-21
                    • 2012-04-28
                    • 2023-01-20
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-01-18
                    • 2012-07-05
                    • 2019-06-22
                    相关资源
                    最近更新 更多