代码之家  ›  专栏  ›  技术社区  ›  DarthVader

递归地获取用属性标记的属性

  •  2
  • DarthVader  · 技术社区  · 7 年前

    在做了很多尝试和研究之后,我想请你离开。

    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 回复  |  直到 7 年前
        1
  •  2
  •   TheGeneral    7 年前

    你可以用这个

    更新 @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
    
        2
  •  2
  •   Eibi    7 年前

    下面是递归收集所有属性的工作代码示例:

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