如何使用反射来查找实现特定接口的属性?

时间:2011-06-20 17:07:27

标签: c# .net reflection interface

考虑这个例子:

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 个答案:

答案 0 :(得分:15)

您可以查看属性“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 :(得分:1)

请注意,在您的示例中,GetType().GetProperties ()找不到catList。您可以使用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");
}

答案 2 :(得分:1)

另一种方法是在对象内部调用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));

编辑:我刚注意到您的示例是一个集合,这对整个传递的集合无效。您必须单独传递每个项目。我很想删除,但这可能会帮助其他人在谷歌这个同样的问题上寻找非收集解决方案。