将泛型转换为接口类型 - 无法将类型为“System.RuntimeType”的对象强制转换为类型

9

我有一些类似这样的类:

public class Customer
{ }

public interface IRepository 
{ }

public class Repository<T> : IRepository
{ }

public class CustomerRepository<Customer>
{ }

接下来,根据这个问题的答案,我可以使用反射来获取每个*Repository引用的泛型类型列表:

我想最终得到一个Dictionary<Type, IRepository>

到目前为止,我有以下代码:

Dictionary<Type, IRepository> myRepositories = Assembly.GetAssembly(typeof(Repository<>))
.GetTypes()
.Where(typeof(IImporter).IsAssignableFrom)
.Where(x => x.BaseType != null && x.BaseType.GetGenericArguments().FirstOrDefault() != null)
.Select(
    x =>
    new { Key = x.BaseType != null ? x.BaseType.GetGenericArguments().FirstOrDefault() : null, Type = (IRepository)x })
.ToDictionary(x => x.Key, x => x.Type);

然而,它不喜欢我的类型转换(IRepository)x
我会得到以下错误:

无法将类型为“System.RuntimeType”的对象强制转换为类型“My.Namespace.IRepository”。


3
你只有一个“Type”,你如何期望获得实例? - Jon Skeet
2个回答

14

你不能将类型为 Type 的类强制转换为 (IRepository) type

你可以使用 Activator.CreateInstance 创建 CustomerRepository 对象,而且不需要使用 Select,直接使用 ToDictionary 即可。下面是代码示例:

var myRepositories = Assembly.GetAssembly(typeof(Repository<>))
       .GetTypes()
       .Where(x => x.BaseType != null && 
                   x.BaseType.GetGenericArguments().FirstOrDefault() != null)

       .ToDictionary(x => x.BaseType.GetGenericArguments().FirstOrDefault(), 
                            x => Activator.CreateInstance(x) as IRepository );

当激活对象的构造函数需要一些参数时,此解决方案无法正常工作。 - Lasoty

3
如果x是一个System.Type对象,例如如果xtypeof(Repository<>),那么你不能直接进行强制类型转换。 Type不是一个实例。
如果x没有“免费”类型参数,也就是说x是非泛型或者封闭的泛型,那么(IRepository)Activator.CreateInstance(x)可能会为你创建一个x类型的对象。但我不确定这是否符合你的需求。是否有无参实例构造函数?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接