Reflection从所有其他派生类中排除基类的所有属性和特定属性

时间:2012-10-01 03:34:29

标签: c# .net system.reflection

我有以下基础,中间和派生类::

public class Base
{
    [DataMemberAttribute()]
    public int ValueBase { get; set; }

    [IgnoreForAllAttribute("Param1", "Param2")]
    public int IgnoreBase { get; set; }
}

public class Middle : Base
{
    [DataMemberAttribute()]
    public int ValueMiddle { get; set; }

    [IgnoreForAllAttribute("Param1", "Param2")]
    public int IgnoreMiddle { get; set; }
}

public class MostDerived : Middle
{
    [DataMemberAttribute()]
    public int ValueMostDerived { get; set; }

    [IgnoreForAllAttribute("Param1", "Param2")]
    public int IgnoreMostDerived { get; set; }
}

我需要一个给定类型的函数,我需要为层次结构中除基础之外的所有类返回DataMemberAttribute属性。

此外,应该忽略图中所有类的所有IgnoreForAllAttribute属性。

var derivedObject = new MostDerived();
var attributes = MyShinyAttributeFunction(derivedObject.GetType());
// returns [] { ValueMostDerived, ValueMiddle }

4 个答案:

答案 0 :(得分:6)

这是一个LINQ示例,它假定DateMemberAttribute和IgnoreForAllAttribute是互斥的

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

假设属性不相互排斥的样本

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

答案 1 :(得分:3)

var properties = new List<PropertyInfo>();

GetProps(typeof(MostDerived), properties);

GetProps是一个递归函数,它获取声明类型的属性,然后为层次结构中的下一个类型调用自身。它到达'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);

  }
}

属性列表将包含具有DataMemberAttribute但没有IgnoreForAllAttribute的属性。

答案 2 :(得分:1)

您可以使用以下功能获得所需的结果: 在propertyNames中,您将获得所需的属性。

用法:

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

功能:

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

答案 3 :(得分:0)

您必须使用以下内容:

当BaseType不存在时停止的递归函数应该可以解决问题。