Как я могу использовать отражение, чтобы найти свойства, которые реализуют определенный интерфейс? - PullRequest
12 голосов
/ 20 июня 2011

Рассмотрим этот пример:

public interface IAnimal
{
}

public class Cat: IAnimal
{
}

public class DoStuff
{
    private Object catList = new List<Cat>();

    public void Go()
    {
        // I want to do this, but using reflection instead:
        if (catList is IEnumerable<IAnimal>)
            MessageBox.Show("animal list found");

        // now to try and do the above using reflection...
        PropertyInfo[] properties = this.GetType().GetProperties();
        foreach (PropertyInfo property in properties)
        {
            //... what do I do here?
            // if (*something*)
                MessageBox.Show("animal list found");
        }
    }
}

Можете ли вы выполнить оператор if, заменив что-то на правильный код?

РЕДАКТИРОВАТЬ:

Я заметил, что я должен был использовать свойство вместо поля, чтобы это работало, поэтому оно должно быть:

    public Object catList
    {
        get
        {
          return new List<Cat>();
        }
    }

Ответы [ 3 ]

15 голосов
/ 20 июня 2011

Вы можете посмотреть свойства 'PropertyType, а затем использовать IsAssignableFrom, что, я полагаю, то, что вы хотите:

PropertyInfo[] properties = this.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
    if (typeof(IEnumerable<IAnimal>).IsAssignableFrom(property.PropertyType))
    {
        // Found a property that is an IEnumerable<IAnimal>
    }                           
}

Конечно, вам нужно добавить свойство в ваш класс, если вы хотите, чтобы приведенный выше код работал; -)

1 голос
/ 11 мая 2017

Другой способ сделать это - просто вызвать GetProperties() на интерфейсе внутри объекта, а не на самом объекте.

public static void DisplayObjectInterface(object source, Type InterfaceName)
{
    // Get the interface we are interested in
    var Interface = source.GetType().GetInterface(InterfaceName.Name);
    if (Interface != null)
    {
        // Get the properties from the interface, instead of our source.
        var propertyList = Interface.GetProperties();
        foreach (var property in propertyList)
            Debug.Log(InterfaceName.Name + " : " + property.Name + "Value " + property.GetValue(source, null));
    }
    else
        Debug.Log("Warning: Interface does not belong to object.");

}

Мне нравится делать InterfaceName параметр Type, чтобы избежать опечаток при поиске GetInterface() по имени строки.

Использование:

DisplayObjectInterface(Obj, typeof(InterFaceNameGoesHere));

РЕДАКТИРОВАТЬ : Я только что заметил, что ваш пример был коллекцией, это не сработает для коллекции, переданной в целом. Вы должны будете передать каждый элемент в отдельности. У меня возникает соблазн удалить, но это, вероятно, поможет другим пользователям, которые задают этот же вопрос в поисках решения, не связанного с коллекцией.

1 голос
/ 20 июня 2011

Обратите внимание, что в вашем примере catList не будет найден с GetType().GetProperties (). Вы бы использовали GetType().GetFields () вместо.

Если вы пытаетесь определить, определено ли свойство как IEnumerable, вы можете сделать это:

if (typeof(IEnumerable<IAnimal>) == property.PropertyType)
{
   MessageBox.Show("animal list found");
}

Если вы хотите узнать, можете ли вы присвоить значение свойства в IEnumerable<IAnimal>, сделайте следующее:

if (typeof(IEnumerable<IAnimal>).IsAssignableFrom (property.PropertyType))
{
   MessageBox.Show("animal list found");
}

Если тип свойства недостаточно конкретен (например, object Animal{get;set;}), чтобы получить ответ, вам нужно будет получить значение, чтобы решить. Вы можете сделать это:

object value = property.GetValue(this, null);
if (value is IEnumerable<IAnimal>)
{
   MessageBox.Show("animal list found");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...