我正在寻找一种解决方案来访问类的'flatten'(最低)属性值,并通过属性名称反射得到它。
即从 ClassB 或 ClassC 类型访问 Property1 或 Property2 :
public class ClassA
{
public virtual object Property1 { get; set; }
public object Property2 { get; set; }
}
public class ClassB : ClassA
{
public override object Property1 { get; set; }
}
public class ClassC : ClassB
{
}
使用简单反射会有效,直到您拥有被过度的虚拟属性(即 Property1 来自 ClassB )。然后你得到一个 AmbiguousMatchException ,因为搜索者不知道你是想要主类的属性还是派生的。
使用BindingFlags.DeclaredOnly避免AmbiguousMatchException,但是未覆盖的虚拟属性或派生类属性被省略(即 Property2 来自 ClassB )。
是否有替代这种糟糕的解决方法:
// Get the main class property with the specified propertyName
PropertyInfo propertyInfo = _type.GetProperty(propertyName, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
// If not found, get the property wherever it is
if (propertyInfo == null)
propertyInfo = _type.GetProperty(propertyName);
此外,此解决方法无法解决第二级属性的反映:从 ClassC 获取 Property1 并且 AmbiguousMatchException 返回。
我的想法:除了循环我别无选择...... Erk ...... ??
我对Emit开放,Lambda(Expression.Call可以处理这个吗?)甚至是DLR解决方案。
谢谢!
答案 0 :(得分:4)
执行此操作的唯一方法是枚举所有属性并过滤掉重复项。
我建议使用像Fasterflect这样的库来执行此操作。它解决了难题,并为您提供了许多优于标准反射功能的功能。
// find properties and remove duplicates higher up the hierarchy
var properties = type.Properties( Flags.ExcludeBackingMembers );
答案 1 :(得分:0)
使用Fasterflect解决方案:
foreach (PropertyInfo propertyInfo in objType.Properties(Flags.ExcludeBackingMembers | Flags.Public | Flags.Static | Flags.Instance))
{
FasterflectPropertyValue(propertyInfo.Name, obj);
}
private static object FasterflectPropertyValue(string propertyName, object obj)
{
return obj.GetPropertyValue(propertyName);
}
Reflection from Class1 - 1 loops :3602674ticks
Reflection from Class2 - 1 loops :2940541ticks
Reflection from Class3 - 1 loops :1035300ticks
Reflection from Class1 - 100 loops :2ms
Reflection from Class2 - 100 loops :2ms
Reflection from Class3 - 100 loops :3ms
Reflection from Class1 - 10000 loops :274ms
Reflection from Class2 - 10000 loops :284ms
Reflection from Class3 - 10000 loops :295ms
Fasterflect from Class1 - 1 loops :44ms
Fasterflect from Class2 - 1 loops :2508656ticks
Fasterflect from Class3 - 1 loops :2314142ticks
Fasterflect from Class1 - 100 loops :3223064ticks
Fasterflect from Class2 - 100 loops :5056514ticks
Fasterflect from Class3 - 100 loops :5166725ticks
Fasterflect from Class1 - 10000 loops :96ms
Fasterflect from Class2 - 10000 loops :138ms
Fasterflect from Class3 - 10000 loops :162ms