如何识别 List<T> 是不是是实现特定接口的 T 列表

Posted

技术标签:

【中文标题】如何识别 List<T> 是不是是实现特定接口的 T 列表【英文标题】:How to identify whether List<T> is a list of Ts that implement a specific interface如何识别 List<T> 是否是实现特定接口的 T 列表 【发布时间】:2014-10-31 20:02:24 【问题描述】:

好的,所以我有一个包含多个List 类型属性的类。

有些列表只是简单的类型,如stringint 等。 但有些是自定义类型的列表,例如 Feature、Trailer、Artwork 等。

public class Movie : IMedia

   public List<Feature> Features;
   public List<Artwork> Artwork;
   public List<string> Genres;

所有自定义类型(以及 Movie 类本身)都实现了接口 IMedia

使用反射我想遍历 Movie 属性并对 List&lt;IMedia&gt; 类型的属性做一些事情 - 但问题就在这里;因为显然我不能只使用is List&lt;IMedia&gt;,同时还想将属性指定为特定类型,例如List&lt;Feature&gt;

你们建议我如何识别这些类型?

扩展List&lt;T&gt; 本身还是完全不同的东西?

【问题讨论】:

你应该展示你的代码。没有您的代码,我们不可能知道出了什么问题。 您要识别列表的类型还是列表中元素的类型? 听起来像是扩展类的教科书用例,出于好奇,尽管 is List&lt;T&gt;.GetType() == TypeOf(List&lt;T&gt;) 应该可以工作,除非您明确重铸该类,并且如果这些类如此熟悉且仅在name 为什么区分它们的对象可以作为对象存储在类中? 这只是***.com/questions/557340/…***.com/questions/4963160/…的组合 我不建议您在简单的 BL 案例中使用反射。这似乎是一种过度概括。 IE。实现在某些条件下返回 IList 的公共方法。 【参考方案1】:

假设您实际上是在使用 properties(这是问题中提到的)而不是 private fields(这是您问题中的类正在使用的) ,你可以这样做:

var movie = new Movie()  ... ;

foreach (var prop in typeof(Movie).GetProperties())

    if (prop.PropertyType.IsGenericType && 
        prop.PropertyType.GetGenericTypeDefinition() == typeof (List<>))
    
        /* Get the generic type parameter of the List<> we're working with: */
        Type genericArg = prop.PropertyType.GetGenericArguments()[0];

        /* If this is a List of something derived from IMedia: */
        if (typeof(IMedia).IsAssignableFrom(genericArg))
        
            var enumerable = (IEnumerable)prop.GetValue(movie);

            List<IMedia> media = 
                enumerable != null ? 
                enumerable.Cast<IMedia>().ToList() : null;

            // where DoSomething takes a List<IMedia>
            DoSomething(media);
        
    

【讨论】:

这正是我想要实现的。谢谢@Andrew Whitaker @Marle1:没问题!很高兴能提供帮助。【参考方案2】:

获取第一个泛型参数的类型:

var lst = new List<MyClass>();
var t1 = lst.GetType().GenericTypeArguments[0];

检查是否可以将其转换为接口:

bool b = typeof(IInterface).IsAssignableFrom(t1);

另一种方法可能是:

var castedLst = lst.OfType<IInterface>().ToList();
bool b = castedLst.Count == lst.Count; // all items were casted successfully

【讨论】:

感谢@Yorye Nathan,您的回答对我帮助很大,非常接近我需要的,但我接受了安德鲁斯的回答,因为他提供了完整的上下文。【参考方案3】:

如果我理解正确,你必须这样做:

Type paramType = typeof(T);
if(paramType is IMedia)  /*do smt*/ 

【讨论】:

我认为你错了。 TS 想要获取 typeof(T) ,其中 T 是 List 的通用参数。 这不是“is”运算符的工作方式。 msdn.microsoft.com/en-us/library/scekt9xw.aspx

以上是关于如何识别 List<T> 是不是是实现特定接口的 T 列表的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 List<T> 元素是不是包含具有特定属性值的项目

asp.net 如何取出List<T>中每一项的值

C#可以编写一个方法对T表查询并返回List<T>吗

如何将 List<T> 初始化为给定大小(而不是容量)?

如何将通用 List<T> 转换为基于接口的 List<T>

java里的List<T>接口里的subList方法,API没看懂