Получить все свойства и подвойства из класса - PullRequest
0 голосов
/ 30 апреля 2018

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

Я столкнулся с проблемой рекурсии, когда элементы добавляются в неправильный список.

Мой код выглядит следующим образом:

private List<Member> GetMembers(object instance)
{
    var memberList = new List<Member>();
    var childMembers = new List<Member>();

    foreach (var propertyInfo in instance.GetType().GetProperties())
    {
        var member = new Member
        {
            Name = propertyInfo.PropertyType.IsList() ? propertyInfo.Name + "[]" : propertyInfo.Name,
            Type = SetPropertyType(propertyInfo.PropertyType),
        };

        if (propertyInfo.PropertyType.IsEnum)
        {
            member.Members = GetEnumValues(propertyInfo).ToArray();
        }

        if (propertyInfo.PropertyType.BaseType == typeof(ModelBase))
        {
            var childInstance = propertyInfo.GetValue(instance) ?? Activator.CreateInstance(propertyInfo.PropertyType);

            childMembers.AddRange(GetMembers(childInstance));

            member.Members = childMembers.ToArray();
        }

        if (propertyInfo.PropertyType.IsGenericType && (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(List<>) ||
            propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
        {
            var itemType = propertyInfo.PropertyType.GetGenericArguments()[0];

            var childInstance = Activator.CreateInstance(itemType);

            childMembers.AddRange(GetMembers(childInstance));

            member.Members = childMembers.Distinct().ToArray();
        }

        memberList.Add(member);
    }

    return memberList;
}

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018

Я не могу знать наверняка, поскольку у меня нет знаний о вашем коде для его отладки и тестирования; однако, я полагаю, что ваша проблема может быть связана с тем фактом, что вы повторно используете список childMembers. Дайте мне знать, если это не так.

private List<Member> GetMembers(object instance)
{
    var memberList = new List<Member>();

    foreach (var propertyInfo in instance.GetType().GetProperties())
    {
        var childMembers = new List<Member>(); // Moved to here, so it's not shared among all propertyInfo iterations.
        var member = new Member
        {
            Name = propertyInfo.PropertyType.IsList() ? propertyInfo.Name + "[]" : propertyInfo.Name,
            Type = SetPropertyType(propertyInfo.PropertyType),
        };

        if (propertyInfo.PropertyType.IsEnum)
        {
            member.Members = GetEnumValues(propertyInfo).ToArray();
        }

        if (propertyInfo.PropertyType.BaseType == typeof(ModelBase))
        {
            var childInstance = propertyInfo.GetValue(instance) ?? Activator.CreateInstance(propertyInfo.PropertyType);

            childMembers.AddRange(GetMembers(childInstance));

            member.Members = childMembers.ToArray();
        }

        if (propertyInfo.PropertyType.IsGenericType && (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(List<>) ||
            propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
        {
            var itemType = propertyInfo.PropertyType.GetGenericArguments()[0];

            var childInstance = Activator.CreateInstance(itemType);

            childMembers.AddRange(GetMembers(childInstance));

            member.Members = childMembers.Distinct().ToArray();
        }

        memberList.Add(member);
    }

    return memberList;
}
0 голосов
/ 30 апреля 2018

Разве не подойдет следующее?

public static IEnumerable<PropertyInfo> GetProperties(this Type type, int depth = 1)
{
    IEnumerable<PropertyInfo> getProperties(Type currentType, int currentDepth)
    {
        if (currentDepth >= depth)
            yield break;

        foreach (var property in currentType.GetProperties())
        {
            yield return property;

            foreach (var subProperty in getProperties(property.PropertyType,
                                                      currentDepth + 1))
            {
                yield return subProperty;
            }
        }
    }

    if (depth < 1)
        throw new ArgumentOutOfRangeException(nameof(depth));

    return getProperties(type, 0);    
}

Дан следующий тип:

class Foo
{
    public string S { get; }
    public int I { get; }
}

Выход

Console.WriteLine(string.Join(Environment.NewLine,
                  typeof(Foo).GetProperties(2)
                             .Select(p => $"{p.DeclaringType.Name}: {p.Name}")));

будет:

Foo: S
String: Chars
String: Length
Foo: I
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...