Как получить все свойства Guid и их значения с именем «Id» из класса?

#c# #reflection #properties #ienumerable

Вопрос:

У меня есть класс, в котором есть вложенные объекты. Я хочу получить все свойства Guid и их значения с именем «Id». Это простая версия моих занятий:

 public class Main
{
    public Guid Id { get; set; }

    public ICollection<Child> Children { get; set; }
}

public class Child
{
    public Guid Id { get; set; }
    public ICollection<GrandChild> GrandChildren { get; set; }
}

public class GrandChild
{
    public Guid Id { get; set; }
}
 

У меня будет объект основного класса, и я хочу получить все свойства Guid с их значениями для всех вложенных и т. Д. для дальнейшей логики.Мне нужно использовать отражение. Основной класс является примером. У меня могут быть универсальные типы во время выполнения.
Есть какие-нибудь предложения?

Комментарии:

1. Как вы ожидаете получить возвращаемое значение? Предоставьте/покажите подпись метода.

Ответ №1:

Используйте рекурсивную функцию для обхода иерархии. Что-то вроде этого:

 using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp34
{
    public class Main
    {
        public Guid Id { get; set; }

        public ICollection<Child> Children { get; set; }
    }

    public class Child
    {
        public Guid Id { get; set; }
        public ICollection<GrandChild> GrandChildren { get; set; }
    }

    public class GrandChild
    {
        public Guid Id { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var main = new Main()
            {
                Children = new List<Child>()
                 {
                    new Child()
                    {
                        Id = Guid.NewGuid(),
                        GrandChildren = new List<GrandChild>()
                        {
                             new GrandChild() {Id=Guid.NewGuid() } ,
                             new GrandChild() {Id=Guid.NewGuid() } ,
                             new GrandChild() {Id=Guid.NewGuid() } ,
                             new GrandChild() {Id=Guid.NewGuid() }
                         }

                    },
                    new Child()
                    {
                        Id = Guid.NewGuid(),
                        GrandChildren = new List<GrandChild>()
                        {
                             new GrandChild() {Id=Guid.NewGuid() } ,
                             new GrandChild() {Id=Guid.NewGuid() } ,
                             new GrandChild() {Id=Guid.NewGuid() } ,
                             new GrandChild() {Id=Guid.NewGuid() }
                         }

                    }
                 }
            };

            foreach (var val in GetIds(main))
            {
                Console.WriteLine($"{val.Item1.GetType().Name} Id {val.Item2}");
            }
        }
        internal static IEnumerable<(object,Guid)> GetIds(Object o)
        {
            var t = o.GetType();
            foreach (var pId in t.GetProperties().Where( p => p.Name == "Id" amp;amp; p.PropertyType == typeof(Guid)))
            {
                yield return (o, (Guid)pId.GetValue(o));
            }
            foreach (var pChild in t.GetProperties().Where(p => p.PropertyType.IsGenericType amp;amp; p.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>)))
            {
                var children = (IEnumerable)pChild.GetValue(o);
                foreach (var child in children)
                {
                   foreach (var val in  GetIds(child))
                    {
                        yield return val;
                    }
                }
            }
                    

            
        }
    }
}
 

выходы

 Main Id 00000000-0000-0000-0000-000000000000
Child Id 971310cb-b1f6-4d27-91de-f1f4edcb1a3b
GrandChild Id 160ce573-e8bc-4cd6-9569-86d82e50d531
GrandChild Id 3524d68e-cbba-453f-a62c-b7530923f937
GrandChild Id 205ef5ac-c97c-45fc-b07a-aead02bd047e
GrandChild Id f79aff79-d3ef-46e0-a637-089bb4b8d9ec
Child Id dd789259-b1cb-4d12-b109-6318afbbc33f
GrandChild Id e909ef22-abf7-4aa7-bf07-8e82ea941203
GrandChild Id 16243269-1994-4d6e-b18e-1661c7e08867
GrandChild Id fba632c9-0450-4d42-86e6-b2b64479bc52
GrandChild Id 2ccb1f39-f046-41fe-b9db-68492c0d9010
 

Комментарии:

1. Я обновил вопрос. Пожалуйста, взгляните на часть отражения.

2. Да, это использует отражение.

Ответ №2:

В этом случае я использовал Словарь, чтобы определить, как найти потомков. Но это может быть сделано непосредственно путем поиска универсального типа. И в результате этот не использует анонимный тип. Тем не менее, результат тот же, вам придется рекурсивно пересекать иерархию.

         private static Dictionary<Type, Func<Type>> childTypeAccessor = new Dictionary<Type, Func<Type>>()
        {
            { typeof(Main), () => typeof(Child) },
            { typeof(Child), () => typeof(GrandChild) }
        };

        public class TypeDef
        {
            public Type Type {get; set;}
            public string PropertyName { get; set; }
        }

        private IEnumerable<TypeDef> SearchTypeProperties(Type type, Type searchType)
        {
            var properties = type.GetProperties().Where(p => p.PropertyType == searchType).Select(p =>
                new TypeDef { Type = type, PropertyName = p.Name }
            );

            if (childTypeAccessor.ContainsKey(type))
            {
                var subproperties = SearchTypeProperties(childTypeAccessor[type](), searchType);
                return properties.Concat(subproperties).ToList();
            }

            return properties.ToList();
        }
 

Комментарии:

1. Я обновил вопрос. Пожалуйста, взгляните на часть отражения?