2012-02-08 3 views
0

Я новичок в отражении, что было бы лучшим способом рекурсивно перебирать объекты, которые имеют общие списки и обычные массивы как поля, содержащие другие объекты?Рекурсивно перебирать список/массив

Дополнительная информация

На самом деле я создал следующий атрибут для обозначения полей, которые будут экспортированы для перевода:

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

Тогда я начинаю на определенном объекте и углубиться оттуда. (теперь я скопировал весь метод.)

частный 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

+0

Я думаю, что более конкретная справочная информация, которую вы действительно пытаетесь сделать, может быть полезна. –

+1

+1 Я согласен, что вопрос не особенно хорошо написан, и, возможно, это не совсем понятно, требуется, но если я правильно его интерпретирую, я думаю, что у него есть какая-то заслуга. –

ответ

1

oa.GetType() получает вас тип экземпляра, а не тип собственности, для которого требуется oa.PropertyType.

EDIT

я, возможно, пошли по домам, чтобы положить это вместе, и я держал пари, что это лучше, или, по крайней мере, более лаконичным способом, но, возможно, это что-то вроде того, что вы ищете:

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

1

Атрибут никогда не является List<>. Таким образом, oa.GetType() == typeof(List<>) всегда будет ложным.

Возможно, вы хотели получить поля с GetFields() или свойствами с GetProperties() вместо получения пользовательских атрибутов.

Возможно, вы также захотите проверить, не соответствует ли тип IEnumerable<T>, если он идентичен List<T>.

+0

Теперь я добавил полный код, где я попробую рекомендации Майлса Макконнеля. – SwissCoder

Смежные вопросы