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



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

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 }
下面是

一个 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);
       }
}
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 的属性。

您可以使用以下函数来获得所需的结果:在属性名称中,您将获得所需的属性。

用法:

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

您必须使用以下方法:

  • 类型::获取属性方法,用于检索所有属性。
  • MemberInfo::GetCustomAttributes 以检索每个属性的属性。
  • 类型::BaseType 属性,用于检索类型的基类型。

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

相关内容

最新更新