BindingFlags.DeclaredOnly替代方法,以避免派生类的不明确属性(AmbiguousMatchException)

时间:2010-04-27 10:59:52

标签: c# .net reflection

我正在寻找一种解决方案来访问类的'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解决方案。

谢谢!

2 个答案:

答案 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