我在下面有以下基本类、中间类和派生类:
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 不存在时停止的递归函数应该可以解决问题。