2012-02-08 94 views
0

我是新来的反射,递归迭代遍历对象的最佳方式是什么,它将泛型列表和普通数组作为包含其他对象的字段?递归迭代列表/数组

更多信息

其实我创建了下面的属性来标记将被导出翻译领域:

using System; 
[AttributeUsage(AttributeTargets.Field)] 
public class ExportForTranslationAttribute : System.Attribute 
{ 
    public ExportForTranslationAttribute() { } 
} 

然后我开始在某个对象,并从那里去更深。 (我现在复制了整个方法。)

private Int64 timesMaxDeepnessReached = 0;

private void searchForExportableStringsInObject(object obj, int deepness) 
{ 
    if (deepness > maxDeepness) 
    { 
     timesMaxDeepnessReached++; 
     return; 
    } 

    if (obj != null) 
    { 
     //only follow serializable objects! 
     var objAttributes = obj.GetType().GetCustomAttributes(true); 
     foreach (var oa in objAttributes) 
     { 
      if (oa.GetType() == typeof(SerializableAttribute)) 
      { 
       var fields = obj.GetType().GetFields(); 
       if (fields == null || !fields.Any()) 
       { return; } 

       foreach (var fieldInfo in fields) 
       { 
        //1. handle string fields that are directly on the component 
        #region directly on object 
        var attributes = fieldInfo.GetCustomAttributes(true); 

        bool hadExportAttribute = false; 

        foreach (var a in attributes) 
        { 
         if (a.GetType() == typeof(ExportForTranslationAttribute)) 
         { 
          Debug.Log("found something!"); 
          hadExportAttribute = true; 

          if (fieldInfo.FieldType == typeof(string)) 
          { 
           try 
           { 
            Debug.Log("info.GetValue= " + fieldInfo.GetValue(obj)); 
            addKeyWhenNotExisting((string)fieldInfo.GetValue(obj)); 
           } 
           catch (Exception ex) { Debug.Log("error while getting value to export: " + ex); } 
          } 
          else if (fieldInfo.FieldType == typeof(string[])) 
          { 
           Debug.Log("found string[]!"); 
           try 
           { 
            Debug.Log("info.GetValue= " + fieldInfo.GetValue(obj)); 
            foreach (var item in (string[])fieldInfo.GetValue(obj)) 
            { 
             addKeyWhenNotExisting(item); 
            } 
           } 
           catch (Exception ex) { Debug.Log("error while getting value to export: " + ex); } 
          } 
          else if (fieldInfo.FieldType == typeof(List<string>)) 
          { 
           Debug.Log("found List<string>!"); 
           try 
           { 
            Debug.Log("info.GetValue= " + fieldInfo.GetValue(obj)); 
            foreach (var item in (List<string>)fieldInfo.GetValue(obj)) 
            { 
             addKeyWhenNotExisting(item); 
            } 
           } 
           catch (Exception ex) { Debug.Log("error while getting value to export: " + ex); } 
          } 
          else 
          { 
           Debug.LogWarning("Can only add ExportForTranslation-Attribute to string values and collection of string values. Not on the type: " + fieldInfo.FieldType); 
          } 
         } 
        } 
        #endregion //directly on object 
       } 
      } 
      else if (oa.GetType() == typeof(List<>)) 
      { 
       try 
       { 
        foreach (var item in (IList)oa) 
        { 
         searchForExportableStringsInObject(item, ++deepness); 
        } 
       } 
       catch (Exception ex) { }//{ Debug.Log("error while getting value to export: " + ex); } 
      } 
      else if (oa.GetType() == typeof(Array)) 
      { 
       try 
       { 
        foreach (var item in (Array)oa) 
        { 
         searchForExportableStringsInObject(item, ++deepness); 
        } 
       } 
       catch (Exception ex) { }//{ Debug.Log("error while getting value to export: " + ex); } 
      } 
     } 
    } 
    else 
    { 
     return; 
    } 
} 
+0

首先,你为什么吞咽所有的例外? – CodesInChaos 2012-02-08 15:34:51

+0

我想一些更具体的背景信息,你真的想做什么可能是有益的。 – 2012-02-08 15:37:56

+1

+1我同意这个问题不是特别好写,也许它不是很清楚是必需的,但如果我已经正确解释它,我认为它确实有一些优点。 – 2012-02-08 15:45:30

回答

1

oa.GetType()让你的实例的类型,你需要oa.PropertyType的财产不是类型。

编辑

我可能已经在房前屋后把这个在一起,我敢打赌,有一个更好的,或者至少更简洁的方式,但也许这有点像你在找什么:

class Program 
    { 
     static void Main(string[] args) 
     { 
      var testType = new TestType {GenList = new List<string> {"test", "type"}}; 

      foreach(var prop in typeof (TestType).GetProperties()) 
      { 
       if (prop.PropertyType.IsGenericType) 
       { 
        var genericTypeArgs = prop.PropertyType.GetGenericArguments(); 

        if (genericTypeArgs.Length!=1 || !(genericTypeArgs[0] == typeof(string))) 
         continue; 

        var genEnum = typeof (IEnumerable<>).MakeGenericType(genericTypeArgs); 

        if (genEnum.IsAssignableFrom(prop.PropertyType)) 
        { 
         var propVal = (IList<string>)prop.GetValue(testType, BindingFlags.GetProperty, null, null, null); 

         foreach (var item in propVal) 
          Console.WriteLine(item); 
        } 
       } 
      } 

      Console.ReadLine(); 
     } 
    } 

    public class TestType 
    { 
     public IList<string> GenList { get; set; } 
    } 
+0

我标记你的问题作为答案。其实我很可能不会再看问题,因为我改变了我的工作环境;-) – SwissCoder 2012-04-06 01:43:35

1

属性永远不是List<>。所以oa.GetType() == typeof(List<>)将永远是错误的。

也许你想让GetFields()的字段或GetProperties()的属性代替自定义属性。

您可能还想检查类型是否实现了IEnumerable<T>而不是检查它是否与List<T>相同。

+0

我现在添加了完整的代码,在那里我会尝试Myles McConnels的建议。 – SwissCoder 2012-02-08 16:47:07