【问题标题】:BindingFlags.DeclaredOnly alternative to avoid ambiguous properties of derived classes (AmbiguousMatchException)BindingFlags.DeclaredOnly 替代方案以避免派生类的不明确属性 (AmbiguousMatchException)
【发布时间】:2011-02-12 19:33:02
【问题描述】:

我正在寻找一种解决方案来访问一个类的“扁平化”(最低)属性值及其通过属性名称的反射派生的。

即从 ClassBClassC 类型访问 Property1Property2

   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
    {
    }

使用简单的反射一直有效,直到您拥有被覆盖的虚拟属性(即 ClassB 中的 Property1)。然后你会得到一个 AmbiguousMatchException 因为搜索者不知道你是想要主类的属性还是派生类的属性。

使用 BindingFlags.DeclaredOnly 可以避免 AmbiguousMatchException,但会省略未覆盖的虚拟属性或派生类属性(即 ClassB 中的 Property2)。

这种糟糕的解决方法是否有替代方法:

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

此外,此解决方法不能解决第二级属性的反射:从 ClassCAmbiguousMatchException 获取 Property1 又回来了。

我的想法:除了循环我别无选择... Erk... ??

我对 Emit、Lambda(Expression.Call 可以处理这个问题吗?)甚至 DLR 解决方案持开放态度。

谢谢!

【问题讨论】:

    标签: c# .net reflection


    【解决方案1】:

    这样做的唯一方法是枚举所有属性并过滤掉重复项。

    我建议使用像 Fasterflect 这样的库来执行此操作。它解决了难题,并为您提供了许多比标准反射所能做的更好的功能。

    // find properties and remove duplicates higher up the hierarchy
    var properties = type.Properties( Flags.ExcludeBackingMembers );
    

    【讨论】:

    • +1 for Fasterflect 但我想它的效率会低于发射 / 表达式树 / DLR 代码?
    • 它在幕后使用了 emit,虽然不是用于查找(因为这不是一个选项)。
    【解决方案2】:

    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
    @ 987654338@
    Fasterflect from Class3 - 10000 loops :162ms

    【讨论】:

      猜你喜欢
      • 2013-04-19
      • 2011-08-31
      • 2017-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-24
      相关资源
      最近更新 更多