关于c#:如何识别List< T>

How to identify whether List<T> is a list of Ts that implement a specific interface

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

有些列表只是简单的类型,如stringint等。但有些是自定义类型的列表,如功能、预告片、艺术品等。

1
2
3
4
5
6
public class Movie : IMedia
{
   public List<Feature> Features;
   public List<Artwork> Artwork;
   public List<string> Genres;
}

所有自定义类型(以及电影类本身)实现接口IMedia

使用反射,我想遍历电影属性,并对那些类型为List的属性做一些事情,但问题在于,显然,我不能只使用is List,当我还想指定属性为特定类型(如List)时。

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

扩展List本身还是完全不同的东西?


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

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

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

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

另一种方法可能是:

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


假设您实际使用的是属性(这是问题中提到的内容),而不是私有字段(这是问题中的类正在使用的内容),那么可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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);
        }
    }
}


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

1
2
Type paramType = typeof(T);
if(paramType is IMedia) { /*do smt*/ }