Reflection exclude all attributes from base class and specific attribute from all other derived classes

馋奶兔 提交于 2019-12-06 21:42:50

Here's a LINQ sample that assumes DateMemberAttribute and IgnoreForAllAttribute are mutually exclusive

IEnumerable<PropertyInfo> MyProperties(object o)
{
   o.GetType().GetProperties()
    .Where(p => !(p.DeclaringType is Base))
    .Where(p => p.GetCustomAttributes(false).Any(a => a is DataMemberAttribute)
}

And a sample assuming the attributes are NOT mutually exclusive

IEnumerable<PropertyInfo> MyProperties(object o)
{
   o.GetType().GetProperties()
    .Where(p => !(p.DeclaringType is Base))
    .Where(p => 
       { 
          var attributes = p.GetCustomAttributes(false);
          return attributes.Any(a => a is DataMemberAttribute)
             && !attributes.Any(a => a is IgnoreForAllAttribute);
       }
}
var properties = new List<PropertyInfo>();

GetProps(typeof(MostDerived), properties);

GetProps is a recursive function that gets the properties for the declaring type and then calls itself for the next type in the hierarchy. It stops when it gets to 'Base'

private static void GetProps(Type T, List<PropertyInfo> Properties)
{
  if (T != typeof(Base))
  {
    var pis = T.GetProperties();

    foreach (var pi in pis)
    {
      if (pi.DeclaringType == T &&
        pi.GetCustomAttribute<DataMemberAttribute>() != null &&
        pi.GetCustomAttribute<IgnoreForAllAttribute>() == null)
      {
        Properties.Add(pi);
      }
    }

    GetProps(T.BaseType, Properties);

  }
}

The properties list will contain properties which have the DataMemberAttribute and don't have the IgnoreForAllAttribute.

You can use the following function to get desired results: In propertyNames, you will get the properties you need.

Usage:

List<string> propertyNames = new List<string>();
List<string> basePropertyNames = new List<string>();
MyShinyAttributeFunction(derivedObject.GetType(), ref propertyNames, ref basePropertyNames);

Function:

void MyShinyAttributeFunction(Type type, ref List<string> propertyNames, ref List<string> basePropertyNames)
{
    if (type == null)
        return;

    MyShinyAttributeFunction(type.BaseType, ref propertyNames, ref basePropertyNames);

    foreach (var property in type.GetProperties())
    {
        foreach (object customAttr in property.GetCustomAttributes(false))
        {
            if (customAttr is DataMemberAttribute)
            {
                if (type.BaseType.Name.Equals("Object"))
                {
                    DataMemberAttribute attribute = (DataMemberAttribute)customAttr;
                    if (!basePropertyNames.Contains(property.Name))
                        basePropertyNames.Add(property.Name);
                }
                else
                {
                    DataMemberAttribute attribute = (DataMemberAttribute)customAttr;
                    if (!propertyNames.Contains(property.Name) && !basePropertyNames.Contains(property.Name))
                        propertyNames.Add(property.Name);
                }
            }
        }
    }
}

You must make use of the following:

A recursive function that stops when BaseType does not exist should do the trick.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!