¿Cómo puedo usar la reflexión para encontrar las propiedades que implementan una interfaz específica?

Considera este ejemplo:

public interface IAnimal { } public class Cat: IAnimal { } public class DoStuff { private Object catList = new List(); public void Go() { // I want to do this, but using reflection instead: if (catList is IEnumerable) 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"); } } } 

¿Puedes completar la instrucción if, reemplazando algo con el código correcto?

EDITAR:

Noté que debería haber usado una propiedad en lugar de un campo para que esto funcione, por lo que debería ser:

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

Puedes ver el PropertyType las PropertyType , luego usar IsAssignableFrom , que supongo que es lo que quieres:

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

Por supuesto, debe agregar una propiedad a su clase si desea que el código anterior funcione 😉

Tenga en cuenta que en su ejemplo, catList no se encontraría con GetType().GetProperties () . Deberías usar GetType().GetFields () lugar.

Si está intentando determinar si la propiedad está definida como IEnumerable, puede hacer esto:

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

Si desea saber si puede asignar el valor de la propiedad a un IEnumerable , haga lo siguiente:

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

Si el tipo de propiedad no es lo suficientemente específico (como el object Animal{get;set;} ) para obtener su respuesta, deberá obtener el valor para decidir. Puedes hacerlo:

 object value = property.GetValue(this, null); if (value is IEnumerable) { MessageBox.Show("animal list found"); } 

Otra forma de hacerlo es simplemente llamar a GetProperties() en la interfaz desde dentro del objeto, a diferencia del objeto en sí.

 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."); } 

Me gusta hacer que el parámetro InterfaceName un Type para evitar cualquier error tipográfico al buscar GetInterface() por nombre de cadena.

Uso:

 DisplayObjectInterface(Obj, typeof(InterFaceNameGoesHere)); 

EDITAR : Me acabo de dar cuenta de que su ejemplo era una colección, esto no funcionará en una colección pasada como un todo. Tendrías que pasar cada elemento individualmente. Estoy tentado de eliminar, pero esto probablemente ayudará a otros que busquen en Google esta misma pregunta en busca de una solución que no sea de colección.