Подтвердить что ты не робот

Результаты отражения GetProperty приводят к "Неоднозначному совпадению найденного" на новом объекте

Как я могу получить свою собственность? В настоящее время происходит ошибка Ambiguous match found, см. Строку комментария в коде.

public class MyBaseEntity
{
    public MyBaseEntity MyEntity { get; set; }
}

public class MyDerivedEntity : MyBaseEntity
{
    public new MyDerivedEntity MyEntity { get; set; }
}

private static void Main(string[] args)
{
    MyDerivedEntity myDE = new MyDerivedEntity();

    PropertyInfo propInfoSrcObj = myDE.GetType().GetProperty("MyEntity");
    //-- ERROR: Ambiguous match found
}
4b9b3361

Ответ 1

Type.GetProperty

Ситуации, в которых происходит событие AmbiguousMatchException...

... производный тип объявляет свойство, которое скрывает унаследованное свойство с тем же именем, используя новый модификатор

Если вы запустите следующий

var properties = myDE.GetType().GetProperties().Where(p => p.Name == "MyEntity");

вы увидите, что возвращаются два объекта PropertyInfo. Один для MyBaseEntity и один для MyDerivedEntity. Вот почему вы получаете обнаруженную неоднозначную ошибку.

Вы можете получить PropertyInfo для MyDerivedEntity следующим образом:

PropertyInfo propInfoSrcObj = myDE.GetType().GetProperties().Single(p => 
    p.Name == "MyEntity" && p.PropertyType == typeof(MyDerivedEntity));

Ответ 2

Для свойства:

MemberInfo property = myDE.GetProperty(
    "MyEntity",
    BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);

Для метода:

MemberInfo method = typeof(String).GetMethod(
    "ToString",
    BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly,
    null,
    new Type[] { },// Method ToString() without parameters
    null);

BindingFlags.DeclaredOnly - указывает, что должны учитываться только члены, объявленные на уровне поставляемой иерархии типов. Унаследованные члены не учитываются.

Ответ 3

Неопределенность возникает из-за объявления new в MyDerivedEntity. Чтобы преодолеть это, вы можете использовать LINQ:

var type = myObject.GetType();
var colName = "MyEntity";
var all = type.GetProperties().Where(x => x.Name == colName);
var info = all.FirstOrDefault(x => x.DeclaringType == type) ?? all.First();

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

Ответ 4

Кевин уже указал на проблему, но вам не нужны сложные операторы или LINQ для этого:

PropertyInfo propInfoSrcObj = myDE.GetType().
    GetProperty("MyEntity", typeof(MyDerivedEntity));

Ответ 5

У меня возникла проблема с сериализацией MsgPack моего объекта LocationKey. Закончились те операторы, которые я определил в своем классе LocationKey. Если оба этих оператора определили, то вызвали DefaultContext.GetSerializer(obj.GetType());, чтобы бросить неоднозначное совпадение, найденное при попытке сериализации. Удаление одного набора операторов заставило проблему уйти.

public static bool operator ==(int key1, LocationKey key2)
{
    return key1 == key2.Value;
}

public static bool operator !=(int key1, LocationKey key2)
{
    return key1 != key2.Value;
}

public static bool operator ==(LocationKey key1, int key2)
{
    return key1.Value == key2;
}

public static bool operator !=(LocationKey key1, int key2)
{
    return key1.Value != key2;
}