2

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

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

4 回答 4

6

这是一个假设 DateMemberAttribute 和 IgnoreForAllAttribute 互斥的 LINQ 示例

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);
       }
}
于 2012-10-01T04:59:25.467 回答
3
var properties = new List<PropertyInfo>();

GetProps(typeof(MostDerived), properties);

GetProps 是一个递归函数,它获取声明类型的属性,然后为层次结构中的下一个类型调用自身。它在到达“基地”时停止

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 的属性。

于 2012-10-01T04:30:08.373 回答
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);
                }
            }
        }
    }
}
于 2012-10-01T04:17:25.097 回答
0

您必须使用以下内容:

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

于 2012-10-01T04:18:08.580 回答