Альтернатива BindingFlags.DeclaredOnly, чтобы избежать неоднозначных свойств производных классов (AmbiguousMatchException) - PullRequest
3 голосов
/ 27 апреля 2010

Я ищу решение для доступа к «сплющенным» (наименьшим) значениям свойств класса и его производным путем отражения именами свойств.

т.е. доступ к Property1 или Property2 из ClassB или ClassC типа:

   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.Declared. Только избегайте 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);

Кроме того, этот обходной путь не разрешает отражение свойств 2-го уровня: получение Property1 из ClassC и AmbiguousMatchException возвращается.

Мои мысли: у меня нет выбора, кроме петли ... Эрк ... ??

Я открыт для Emit, Lambda (Expression.Call может справиться с этим?), Даже решение DLR.

Спасибо!

Ответы [ 2 ]

4 голосов
/ 27 апреля 2010

Единственный способ сделать это - перечислить все свойства и отфильтровать дубликаты.

Я бы порекомендовал использовать такую ​​библиотеку, как Fasterflect . Он решает сложные проблемы и предоставляет массу полезных функций по сравнению с тем, что вы можете делать со стандартным отражением.

// find properties and remove duplicates higher up the hierarchy
var properties = type.Properties( Flags.ExcludeBackingMembers );
0 голосов
/ 05 августа 2013

Решение с 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 1024 *
*

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...