How can I use reflection to find the properties which implement a specific interface?
Consider this example:
public interface IAnimal
{
}
public cl开发者_运维技巧ass 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");
}
}
}
Can you complete the if statement, replacing something with the correct code?
EDIT:
I noticed that I should have used a property instead of a field for this to work, so it should be:
public Object catList
{
get
{
return new List<Cat>();
}
}
You can look at the properties' PropertyType
, then use IsAssignableFrom
, which I assume is what you want:
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>
}
}
Of course, you need to add a property to your class if you want the above code to work ;-)
Please note that in your example, catList would not be found with GetType().GetProperties ()
. You would use GetType().GetFields ()
instead.
If you are trying to determine whether the property is defined as IEnumerable you can do this:
if (typeof(IEnumerable<IAnimal>) == property.PropertyType)
{
MessageBox.Show("animal list found");
}
If you want to know if you can assign the value of the property into a IEnumerable<IAnimal>
, do this:
if (typeof(IEnumerable<IAnimal>).IsAssignableFrom (property.PropertyType))
{
MessageBox.Show("animal list found");
}
If the property type is not specific enough (like object Animal{get;set;}
) to get your answer, you will need to get the value to decide. You can do this:
object value = property.GetValue(this, null);
if (value is IEnumerable<IAnimal>)
{
MessageBox.Show("animal list found");
}
Another way to do it is just call GetProperties()
on the interface from within the object, opposed to on the object itself.
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.");
}
I like to make InterfaceName
parameter a Type
to avoid any typo errors when looking up GetInterface()
by string name.
Usage:
DisplayObjectInterface(Obj, typeof(InterFaceNameGoesHere));
EDIT: I just noticed that your example was a collection, this will not work on a collection passed as a whole. You would have to pass each item individually. I'm tempted to delete but this will probably help others that google this same question looking for a non-collection solution.
精彩评论