2012-02-08 10 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

+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()プロパティを取得したかったでしょう。

List<T>と同じかどうかをチェックする代わりに、タイプがIEnumerable<T>を実装しているかどうかを確認することもできます。

+0

私はMyles McConnelsの推奨事項を試してみるところの完全なコードを今追加しました。 – SwissCoder

関連する問題