Рекурсивно получить свойства, помеченные атрибутом - PullRequest
0 голосов
/ 28 октября 2018

После многих попыток и исследований, хотел спросить.

class Customer
{
    [Foo]
    public string Name {get;set;}

    public Account Account {get;set;}
}

class Account
{
   [Foo]
   public string Info {get;set;}
}

Я пытаюсь получить все свойства, помеченные атрибутом [Foo].

Я выполнил некоторую рекурсию, но сдался.Вот что я попробовал:

public static IEnumerable<PropertyInfo> GetPropertiesRecursive(this Type type)
{
    var visitedProps= new HashSet<string>();

    IList<PropertyInfo> propertyInfos = new List<PropertyInfo>();

    var currentTypeInfo = type.GetTypeInfo();

    while (currentTypeInfo.AsType() != typeof(object))
    {
        var unvisitedProperties = currentTypeInfo.DeclaredProperties.Where(p => p.CanRead &&
                                                                             p.GetMethod.IsPublic &&
                                                                             !p.GetMethod.IsStatic &&
                                                                             !visitedProps.Contains(p.Name));

        foreach (var propertyInfo in unvisitedProperties)
        {
            visitedProps.Add(propertyInfo.Name);

            propertyInfos.Add(propertyInfo);
        }

        currentTypeInfo = currentTypeInfo.BaseType.GetTypeInfo();
    }

    return propertyInfos;
}

Ответы [ 2 ]

0 голосов
/ 28 октября 2018

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

List<PropertyInfo> _props = new List<PropertyInfo>();

.

namespace WpfApplication3
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    /// 

    class MyClass
    {
        [AttributeType]
        public string SomeString { get; set; }

        public MySecondClass MySecondClass { get; set; }
    }

    class MySecondClass
    {
        [AttributeType]
        public string SomeString { get; set; }
    }

    class AttributeType : Attribute
    {

    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            CollectProperties(typeof (MyClass));
            InitializeComponent();
        }

        List<PropertyInfo> _props = new List<PropertyInfo>();

        public void CollectProperties(Type myType)
        {
            IEnumerable<PropertyInfo> properties = myType.GetProperties().Where(
                property => Attribute.IsDefined(property, typeof(AttributeType)));


            foreach (var propertyInfo in properties)
            {
                if (!_props.Any((pr => pr.DeclaringType.FullName == propertyInfo.DeclaringType.FullName)))
                {
                    _props.Add(propertyInfo);
                }
            }


            var props = myType.GetProperties();

            foreach (var propertyInfo in props)
            {
                CollectProperties(propertyInfo.PropertyType);
            }
        }
    }
}
0 голосов
/ 28 октября 2018

Вы можете использовать это

Обновлено в отношении некоторых замечательных моментов в комментариях от @ pinkfloydx33

public static IEnumerable<(Type Class, PropertyInfo Property)> GetAttributeList<T>(Type type, HashSet<Type> visited = null)
   where T : Attribute
{

   // keep track of where we have been
   visited = visited ?? new HashSet<Type>();

   // been here before, then bail
   if (!visited.Add(type))
      yield break;

   foreach (var prop in type.GetProperties())
   {
      // attribute exists, then yield
      if (prop.GetCustomAttributes<T>(true).Any())
         yield return (type, prop);

      // lets recurse the property type as well
      foreach (var result in GetAttributeList<T>(prop.PropertyType, visited))
         yield return (result);
   }
}

Использование

foreach (var result in GetAttributeList<FooAttribute>(typeof(Customer)))
   Console.WriteLine($"{result.Class} {result.Property.Name}");

Выход

ConsoleApp.Customer Name
ConsoleApp.Account Info
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...