如何将IEnumerable <object>强制转换为IEnumerable <runtime type>

Mat*_*ero 2 .net c# linq generics casting

我正在努力完成以下任务.

假设我有这个数据模型:

public class Article
{
     public ICollection<string> Tags { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

从数据库中检索这些标记.我的数据库的API将它们作为一个返回给我List<object>.

因此,我需要转换为List<object>实现的东西ICollection<string>.

我知道LINQ Cast<T>()方法将其元素强制转换为给定类型并返回转换后的元素IEnumerable<T>.

但是,我不能使用Cast<string>(),因为总是会投我List<object>IEnumerable<string>,不给该车型有任何选项ICollection<double>属性(或任何其他类型).

我可以使用反射并获取泛型类型参数:

Type genericArg = collectionType.GetGenericArguments().First();
Run Code Online (Sandbox Code Playgroud)

但这会让我Type失去运行时间,我无法使用它Cast<genericArg>().

我怎样才能施放IEnumerable<object>一个IEnumerable动态的Type

我应该注意,我的模型上不允许复杂的类型,所以像:

public ICollection<Tag> Tags { get; set; }
Run Code Online (Sandbox Code Playgroud)

不会发生.我只处理原始类型.

Hei*_*nzi 7

你对铸造有一个基本的误解.

必须在编译时知道转换操作的结果类型.¹

请考虑以下示例:

string a = "abc";
object b = (object)a;
string c = (string)b;
Run Code Online (Sandbox Code Playgroud)

运行时类型a,b并且c是相同的.是的string.在编译时类型是不同的.转换仅与编译时类型相关.

因此,你的问题的答案

如何投射IEnumerable<object>IEnumerable<runtime type>

是:你没有.对于运行时类型,强制转换没有意义.


也就是说,让我为你的真正问题提供一个解决方案:假设你有一个IEnumerable<object> values,Type myTargetType并且想要创建一个List<typeof(myTargetType)>包含值的方法.

首先,使用反射创建列表:

var listType = typeof(List<>).MakeGenericType(myTargetType);
IList myList = (IList)Activator.CreateInstance(listType);
Run Code Online (Sandbox Code Playgroud)

然后你填写清单:

foreach (var item in values)
{
    myList.Add(item);
}
Run Code Online (Sandbox Code Playgroud)

显然,Add引发ArgumentException如果一个条目values不是运行时类型myTargetType.


¹结果类型可以是泛型类型,但也必须在编译时指定泛型类型参数.