在属性装饰的类中递归搜索Properties

时间:2018-12-14 10:41:23

标签: c# .net recursion reflection attributes

我想获得所有由属性AggregateAuthorizeIdentifier装饰的属性。这是核心功能,因此应尽可能快。

我可以通过所有属性进行递归搜索,但是我会检查所有System和3rd party库。但这不是最佳解决方案。

您遇到了这样的问题吗?

public class ReadOrderHistoryQuery
{
    public List<string> Ordering { get; set; }

    public Criteria Criteria { get; set; }

    public class Criteria
    {
        [AggregateAuthorizeIdentifier]
        public int UserId { get; set; }

        public string InvoiceId { get; set; }
    }
}

我的解决方案:

    static IEnumerable<PropertyWithAttribute> GetAuthorizeIdentifierAttribute(object command)
    {
        var attributedProperties = GetAuthorizeIdentifierAttribute(command.GetType());
        return attributedProperties;
    }
    static IEnumerable<PropertyWithAttribute> GetAuthorizeIdentifierAttribute(Type type)
    {
        //check current property
        var result = type.GetProperties()
            .Where(prop => Attribute.IsDefined(prop, typeof(AggregateAuthorizeIdentifierAttribute)))
            .Select(p => new PropertyWithAttribute()
            {
                Property = p,
                Attribute = p.GetCustomAttribute<AggregateAuthorizeIdentifierAttribute>(true)
            })
            .ToList();
        //deeper check all properties
        result.AddRange(type.GetProperties()
            .SelectMany(p => GetAuthorizeIdentifierAttribute(p.PropertyType)));
        return result;
    }

2 个答案:

答案 0 :(得分:1)

最后我用附加的类型选择器(按字符串)实现了它。

    const string PropertyTypeStartWithSelector = "Diabdis.";

    static IEnumerable<PropertyWithAttribute> GetAuthorizeIdentifierAttribute(Type type, string propertyPathPrefix)
    {
        var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        //check current property
        var result = properties
            .Where(prop => Attribute.IsDefined(prop, typeof(AggregateAuthorizeIdentifierAttribute)))
            .Select(p => new PropertyWithAttribute()
            {
                PropertyPath = propertyPathPrefix == null ? p.Name : $"{propertyPathPrefix}{PropertyPathSeparator}{p.Name}",
                Attribute = p.GetCustomAttribute<AggregateAuthorizeIdentifierAttribute>(true)
            })
            .ToList();

        //check deeper properties, BUT just selector classes
        result.AddRange(properties
            .Where(p => p.DeclaringType.FullName.StartsWith(PropertyTypeStartWithSelector))
            .SelectMany(p => GetAuthorizeIdentifierAttribute(p.PropertyType, propertyPathPrefix == null ? p.Name : $"{propertyPathPrefix}{PropertyPathSeparator}{p.Name}")));
        return result;
    }

答案 1 :(得分:0)

当我需要做这样的事情时,我总是这样:

object objectToSearch = ...

PropertyInfo[] properties = objectToSearch.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
if (properties != null && properties.Length > 0)
{
    properties.ToList().ForEach(p =>
    {
        if (p.GetCustomAttributes(typeof(AggregateAuthorizeIdentifierAttribute), false).Count() == 1)
        {
            // Do something with the property
        }
    });
}

因此,您可以创建扩展方法以返回具有特定属性的对象的所有属性