问题 使用包含另一个对象数组的对象的反射读取属性


如何使用c#中的反射读取包含数组类型元素的对象的属性。如果我有一个名为GetMyProperties的方法,并且我确定该对象是自定义类型,那么我该如何读取数组的属性及其中的值。 IsCustomType是确定类型是否为自定义类型的方法。

public void GetMyProperties(object obj) 
{ 
    foreach (PropertyInfo pinfo in obj.GetType().GetProperties()) 
    { 
        if (!Helper.IsCustomType(pinfo.PropertyType)) 
        { 
            string s = pinfo.GetValue(obj, null).ToString(); 
            propArray.Add(s); 
        } 
        else 
        { 
            object o = pinfo.GetValue(obj, null); 
            GetMyProperties(o); 
        } 
    } 
}

场景是,我有一个ArrayClass和ArrayClass的对象有两个属性:

-string Id
-DeptArray[] depts

DeptArray是另一个具有2个属性的类:

-string code 
-string value

因此,此方法获取ArrayClass的对象。我想在字典/列表项中读取所有属性从上到下并存储名称/值对。我能够为价值,定制,枚举类型做到这一点。我被一堆物体困住了。不知道怎么做。


10526
2018-02-02 19:58


起源

嗨,我从你的代码中看不出你想要实现的目标。代码不会编译,因为pInfo.GetValue返回一个对象,而不是一个字符串。 - Adam
对不起。我编辑了代码以将ToString()添加到pInfo.GetValue()。我不得不把这个方法搞定。最初该方法有一些复杂的逻辑。为简化起见,我需要阅读所有属性,属性的属性及其值。 - Sri Reddy


答案:


试试这段代码:

public static void GetMyProperties(object obj)
{
  foreach (PropertyInfo pinfo in obj.GetType().GetProperties())
  {
    var getMethod = pinfo.GetGetMethod();
    if (getMethod.ReturnType.IsArray)
    {
      var arrayObject = getMethod.Invoke(obj, null);
      foreach (object element in (Array) arrayObject)
      {
        foreach (PropertyInfo arrayObjPinfo in element.GetType().GetProperties())
        {
          Console.WriteLine(arrayObjPinfo.Name + ":" + arrayObjPinfo.GetGetMethod().Invoke(element, null).ToString());
        }
      }
    }
  }
}

我已经测试了这段代码,它通过正确的反射解析了数组。


16
2018-02-02 21:18



@evgk,我无法明确地向DeptArray施展。我在运行时确定类型。方法参数“obj”可以包含任何类对象。我需要一个通用方法来检查数组并迭代它的元素。 - Sri Reddy
或者,没有问题,我已经修改了答案。现在它将获取传递对象中的所有数组,并将迭代遍历每个数组元素及其属性,而不会明确地进行转换。如果您愿意,也可以使此方法递归。 - EvgK
@Evgk,太棒了!这是完美的 - 谢谢,我将测试具有不同对象属性的逻辑,看看它是否在某处失败。当你说递归时,是否检查数组的属性是否包含数组? - Sri Reddy
@EvgK,两个后续问题:1。如果obj是string []或int []或任何值类型数组,如何获取值? obj.GetType()。GetProperties()永远不会返回任何内容。 2.你能告诉我如何更改上面接受类型为“ParameterInfo.ParameterType”而不是obj的参数的方法吗?那么我应该在getMethod.Invoke()中传递什么? - Sri Reddy
1.这不是因为值类型,而是因为int类型,例如,根本没有任何属性。所以你应该只使用对象本身,而不必枚举它的属性(如Console.WriteLine(element); - EvgK


您需要检索属性值对象,然后在其上调用GetType()。然后你可以做这样的事情:

var type = pinfo.GetGetMethod().Invoke(obj, new object[0]).GetType();
if (type.IsArray)
{
    Array a = (Array)obj;
    foreach (object arrayVal in a)
    {
        // reflect on arrayVal now
        var elementType = arrayVal.GetType();
    }
}

仅供参考 - 我从递归对象格式化方法中提取此代码(我现在将使用JSON序列化)。


0
2018-02-02 20:11



不,我的意思是GetGetMethod。你为什么要打电话给GetSetMethod?你是不是想读取属性,如果它是一个DeptArray数组迭代元素并读取它们? - JohnOpincar
我试图回答这个问题“如何在c#中使用反射来读取包含数组类型元素的对象的属性。”如果这不是问题,那么你应该编辑它。 - JohnOpincar
John,你是绝对正确的,我需要读取属性并迭代DeptArray。当我运行这段代码。我在Array a =(Array)obj处得到了转换错误。它说ARrayClass canot被铸造成Array。你觉得我错过了什么吗? - Sri Reddy