递归迭代List / Array

时间:2012-02-08 15:15:02

标签: c# list generics reflection

我是反思的新手,递归迭代对象的最佳方法是什么,将通用列表和普通数组作为包含其他对象的字段?

更多信息

实际上,我创建了以下属性来标记将要导出以进行翻译的字段:

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;
    }
}

2 个答案:

答案 0 :(得分: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; }
    }

答案 1 :(得分:1)

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

也许您希望获取包含GetFields()的字段或包含GetProperties()的属性,而不是获取自定义属性。

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