【问题标题】:Get properties and values from unknown object从未知对象获取属性和值
【发布时间】:2010-11-10 13:11:02
【问题描述】:

从 PHP 的世界开始,我决定尝试 C#。我已经进行了搜索,但似乎找不到如何做到这一点的答案。

$object = new Object();

$vars = get_class_vars(get_class($object));

foreach($vars as $var)
{
    doSomething($object->$var);
}

我基本上有一个对象列表。该对象可以是三种不同类型中的一种,并将具有一组公共属性。我希望能够获取对象的属性列表,遍历它们,然后将它们写到文件中。 我认为这与 c# 反射有关,但这对我来说是全新的。

任何帮助将不胜感激。

【问题讨论】:

  • 附带说明:在列表中包含不同类型的对象(没有公共基类或接口)不是一种好的编程风格,至少在 c# 中不是。

标签: c# reflection


【解决方案1】:

应该这样做:

Type myType = myObject.GetType();
IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties());

foreach (PropertyInfo prop in props)
{
    object propValue = prop.GetValue(myObject, null);

    // Do something with propValue
}

【讨论】:

  • @jonathan System.Reflection 命名空间
  • 实际上不需要从数组创建列表,只需PropertyInfo[] props = input.GetType().GetProperties();
  • 您想使用 Newtonsoft.Json.JsonConvert 更新 2017 年的答案吗?
  • @clone 这是一种完全不同的方式。如果您认为这是一种有效的方法,您应该发布答案
  • @Jonesopolis 如何从dynamic 获取属性,而不先将其转换为object,然后按照我的答案进行操作?
【解决方案2】:
void Test(){
    var obj = new{a="aaa", b="bbb"};

    var val_a = obj.GetValObjDy("a"); //="aaa"
    var val_b = obj.GetValObjDy("b"); //="bbb"
}
//create in a static class
static public object GetValObjDy(this object obj, string propertyName)
{            
     return obj.GetType().GetProperty(propertyName).GetValue(obj, null);
}

【讨论】:

    【解决方案3】:

    是的,反射将是要走的路。首先,您将获得Type,它表示列表中实例的类型(在运行时)。您可以通过拨打GetType method on Object 来完成此操作。因为它在Object 类上,它可以被.NET 中的每个 对象调用,因为所有类型都派生自Objectwell, technically, not everything,但这在这里并不重要)。

    拥有Type 实例后,您可以调用GetProperties method 来获取PropertyInfo 实例,这些实例代表关于Type 上的属性的运行时信息。

    注意,您可以使用 GetProperties 的重载来帮助分类您检索到的哪些属性。

    从那里,您只需将信息写入文件。

    您上面的代码,翻译后将是:

    // The instance, it can be of any type.
    object o = <some object>;
    
    // Get the type.
    Type type = o.GetType();
    
    // Get all public instance properties.
    // Use the override if you want to classify
    // which properties to return.
    foreach (PropertyInfo info in type.GetProperties())
    {
        // Do something with the property info.
        DoSomething(info);
    }
    

    请注意,如果您需要方法信息或字段信息,则必须分别调用 GetMethodsGetFields 方法的重载之一。

    另请注意,将成员列出到文件中是一回事,但您不应该使用此信息来驱动基于属性集的逻辑。

    假设您可以控制类型的实现,您应该从一个公共基类派生或实现一个公共接口并对它们进行调用(您可以使用asis 运算符来帮助确定哪个您在运行时使用的基类/接口)。

    但是,如果您不控制这些类型定义并且必须基于模式匹配来驱动逻辑,那也没关系。

    【讨论】:

      【解决方案4】:

      嗯,在 C# 中也是类似的。 这是最简单的示例之一(仅适用于公共属性):

      var someObject = new { .../*properties*/... };
      var propertyInfos = someObject.GetType().GetProperties();
      foreach (PropertyInfo pInfo in propertyInfos)
      {
          string propertyName = pInfo.Name; //gets the name of the property
          doSomething(pInfo.GetValue(someObject,null));
      }
      

      【讨论】:

        【解决方案5】:

        从属性名称中获取特定的属性值

        public class Bike{
        public string Name {get;set;}
        }
        
        Bike b = new Bike {Name = "MyBike"};
        

        从属性的字符串名称访问Name的属性值

        public object GetPropertyValue(string propertyName)
        {
        //returns value of property Name
        return this.GetType().GetProperty(propertyName).GetValue(this, null);
        } 
        

        【讨论】:

          【解决方案6】:

          使用 Linq 的单行解决方案...

          var obj = new {Property1 = 1, Property2 = 2};
          var property1 = obj.GetType().GetProperties().First(o => o.Name == "Property1").GetValue(obj , null);
          

          【讨论】:

            【解决方案7】:

            您可以使用GetType - GetProperties - Linq Foreach

            obj.GetType().GetProperties().ToList().ForEach(p =>{
                                                                    //p is each PropertyInfo
                                                                    DoSomething(p);
                                                                });
            

            【讨论】:

              【解决方案8】:

              这是我用来将IEnumerable&lt;T&gt; 转换为DataTable 的东西,其中包含代表T 属性的列,IEnumerable 中的每个项目都有一行:

              public static DataTable ToDataTable<T>(IEnumerable<T> items)
              {
                  var table = CreateDataTableForPropertiesOfType<T>();
                  PropertyInfo[] piT = typeof(T).GetProperties();
                  foreach (var item in items)
                  {
                      var dr = table.NewRow();
                      for (int property = 0; property < table.Columns.Count; property++)
                      {
                          if (piT[property].CanRead)
                          {
                              var value = piT[property].GetValue(item, null);
                              if (piT[property].PropertyType.IsGenericType)
                              {
                                  if (value == null)
                                  {
                                      dr[property] = DBNull.Value;
                                  }
                                  else
                                  {
                                      dr[property] = piT[property].GetValue(item, null);
                                  }
                              }
                              else
                              {
                                  dr[property] = piT[property].GetValue(item, null);
                              }
                          }
                      }
                      table.Rows.Add(dr);
                  }
                  return table;
              }
              
              public static DataTable CreateDataTableForPropertiesOfType<T>()
              {
                  DataTable dt = new DataTable();
                  PropertyInfo[] piT = typeof(T).GetProperties();
                  foreach (PropertyInfo pi in piT)
                  {
                      Type propertyType = null;
                      if (pi.PropertyType.IsGenericType)
                      {
                          propertyType = pi.PropertyType.GetGenericArguments()[0];
                      }
                      else
                      {
                          propertyType = pi.PropertyType;
                      }
                      DataColumn dc = new DataColumn(pi.Name, propertyType);
              
                      if (pi.CanRead)
                      {
                          dt.Columns.Add(dc);
                      }
                  }
                  return dt;
              }
              

              这“有点”过于复杂,但它实际上非常适合查看结果,因为您可以给它一个List&lt;T&gt;,例如:

              public class Car
              {
                  string Make { get; set; }
                  int YearOfManufacture {get; set; }
              }
              

              您将返回一个具有以下结构的 DataTable:

              制作(字符串)
              YearOfManufacture (int)

              List&lt;Car&gt; 中的每一项都包含一行

              【讨论】:

                【解决方案9】:

                此示例修剪对象的所有字符串属性。

                public static void TrimModelProperties(Type type, object obj)
                {
                    var propertyInfoArray = type.GetProperties(
                                                    BindingFlags.Public | 
                                                    BindingFlags.Instance);
                    foreach (var propertyInfo in propertyInfoArray)
                    {
                        var propValue = propertyInfo.GetValue(obj, null);
                        if (propValue == null) 
                            continue;
                        if (propValue.GetType().Name == "String")
                            propertyInfo.SetValue(
                                             obj, 
                                             ((string)propValue).Trim(), 
                                             null);
                    }
                }
                

                【讨论】:

                  【解决方案10】:

                  我还没有发现这个可以工作,比如应用程序对象。然而,我已经成功了

                  var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
                  
                  string rval = serializer.Serialize(myAppObj);
                  

                  【讨论】:

                  【解决方案11】:

                  你可以试试这个:

                  string[] arr = ((IEnumerable)obj).Cast<object>()
                                                   .Select(x => x.ToString())
                                                   .ToArray();
                  

                  一旦每个数组都实现了 IEnumerable 接口

                  【讨论】:

                    【解决方案12】:
                    public Dictionary<string, string> ToDictionary(object obj)
                    {
                        Dictionary<string, string> dictionary = new Dictionary<string, string>();
                    
                        Type objectType = obj.GetType();
                        IList<PropertyInfo> props = new List<PropertyInfo>(objectType.GetProperties());
                    
                        foreach (PropertyInfo prop in props)
                        {
                            object propValue = prop.GetValue(obj, null);
                            dictionary.Add(prop.Name, propValue.ToString());
                        }
                    
                        return dictionary;
                    }
                    

                    【讨论】:

                      【解决方案13】:
                          /// get set value field in object to object new (two object  field like ) 
                      
                          public static void SetValueObjectToObject (object sourceObj , object resultObj)
                          {
                              IList<PropertyInfo> props = new List<PropertyInfo>(sourceObj.GetType().GetProperties());
                              foreach (PropertyInfo prop in props)
                              {
                                  try
                                  {
                                      //get value in sourceObj
                                      object propValue = prop.GetValue(sourceObj, null);
                                      //set value in resultObj
                                      PropertyInfo propResult = resultObj.GetType().GetProperty(prop.Name, BindingFlags.Public | BindingFlags.Instance);
                                      if (propResult != null && propResult.CanWrite)
                                      {
                                          propResult.SetValue(resultObj, propValue, null);
                                      }
                                  }
                                  catch (Exception ex)
                                  {  
                                      // do something with Ex
                                  }
                              }
                          }
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2011-08-16
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多