Generics .Net使用反射然后强制转换加载泛型

Generics .Net使用反射然后强制转换加载泛型,generics,reflection,.net-4.0,unity-container,Generics,Reflection,.net 4.0,Unity Container,这是一项后续行动。只有当你对背景故事感兴趣的时候,才懒得去读它 简而言之,我使用反射从程序集加载一组泛型类型。程序集在运行时加载 我的当前项目和正在加载的程序集都引用了第二个程序集,该程序集包含以下接口: IJob IJob包装器(IJob的) 我正在加载的程序集(称之为Jobs.dll)包含一个JobWrapper(IJob的)——它实现了IJobWrapper接口 Jobs.dll还包含多个实现IJob 现在,我将适当的类型加载到一个容器(Unity)中,并在需要时将其取出。这是可行的(

这是一项后续行动。只有当你对背景故事感兴趣的时候,才懒得去读它

简而言之,我使用反射从程序集加载一组泛型类型。程序集在运行时加载

我的当前项目和正在加载的程序集都引用了第二个程序集,该程序集包含以下接口:

  • IJob
  • IJob包装器(IJob的)
我正在加载的程序集(称之为
Jobs.dll
)包含一个
JobWrapper(IJob的)
——它实现了
IJobWrapper
接口

Jobs.dll
还包含多个实现
IJob

现在,我将适当的类型加载到一个容器(Unity)中,并在需要时将其取出。这是可行的(也就是说,容器根据需要解析引用并实例化对象)

注意:下面的
JobType
JobWrapperType
通过反射检索

具体而言:

        Dim TypeArgs As Type() = {JobType}
        Dim WrappedJob = JobWrapperType.MakeGenericType(TypeArgs)
        Dim ContainerJob = Container.Resolve(WrappedJob)
        Dim JobInstance = DirectCast(ContainerJob, IJobWrapper(Of IJob))
这里抛出错误的是演员阵容的最后一行

第3行的
ContainerJob
在技术上是一个对象,因为我需要使用非泛型重载来进行解析(即类型参数而不是“(Of XXX)”

然而,根据调试器,它实际上是一个
MyProject.Jobs.JobWrapper(MyProject.Jobs.DailyStatusReport的)

MyProject.Jobs.JobWrapper
实现
IJobWrapper(IJob的)
MyProject.Jobs.DailyStatusReport
Implements
IJob

DirectCast引发此异常:

Unable to cast object of type 'MyProject.Jobs.JobWrapper`1[MyProject.Jobs.DailyStatusReport]' to type 'MyProject.JobService.Common.IJobWrapper`1[MyProject.JobService.Common.IJob]'.
有人能解释一下为什么它不能做演员/如何避开它吗?我想知道它是否在将引用程序集中定义的接口与从
Jobs.dll
中引用的接口进行匹配时遇到问题-但是如果是这样,我不确定如何协调这两个接口

非常感谢

编辑:

接口中的示例方法:

IJob:

IJobWrapper:

Function ShouldExectute() As Boolean
Sub Execute()
ReadOnly Property DatabaseId as Long
ReadOnly Property Name as String
ReadOnly Property IsDisabled As Boolean

作业包装器永远不会返回IJob类型的任何东西。它确实使用类型信息来查找附加到实现IJob和读取信息的类的各种属性

不可能执行此强制转换(带反射或不带反射),因为需要泛型类型参数精确匹配。因此,您可以将
AnyImplementationOfIJobWrapper(属于IJob)
强制转换为
IJobWrapper(属于IJob)
,但您不能将
AnyImplementationOfIJobWrapper(属于IJob)
强制转换为
IJobWrapper(属于IJob)

但是,如果您控制
IJobWrapper
的代码,则可以通过将其声明为
接口IJobWrapper(Out IJob)
将其转换为。这将允许您执行演员阵容。这与允许您将
IEnumerable(子类的)
分配给
IEnumerable(超类的)
的机制相同

(请随意更正我可能犯的任何语法错误;我已经有一段时间没有使用VB了。)


一个自然的问题是“为什么一开始就不允许使用此类型?”原因是它会导致危险情况:假设您有一辆
IList(Of Vehicle)vehicles
。似乎可以将
列表(汽车)
分配给
车辆
,因为汽车列表可以被视为车辆列表。但是如果我们允许
车辆
引用真正的
车辆列表
,我们可以尝试将
添加到
车辆
,这应该是允许的,因为
车辆
似乎是
车辆
的列表,而
车辆
。但是,实际列表仅限于包含
汽车
s,因此我们必须抛出一个异常(对于
车辆
的用户来说非常意外),或者将
插入
汽车
的列表(造成等待发生的灾难)。解决方案:禁止演员阵容
IEnumerable
(但不是
IList
)可以成为协变的,因为它只包含允许从集合中读取的方法。因此,可以将
IEnumerable(汽车)
分配给
IEnumerable(汽车)
,因为
IEnumerable
只允许您读取收藏的内容,而不允许在其中插入新对象。

好吧,这似乎正是我遇到的问题(我以前从未奇怪地遇到过)。我确实控制着
Jobs.dll
-你能给出一个实现这项功能所需的代码示例吗?如果有帮助,我会在我的问题中添加一个关于接口的方法摘要。我假设你对
IJobWrapper
的声明如下所示:
接口IJobWrapper(IJob的)
。在这种情况下,添加关键字
Out
即可使接口协变:
interface IJobWrapper(Of Out IJob)
。然而,协变和逆变是在.NET4.0中引入的,在早期版本中可能不起作用。谢谢,我将尝试一下。幸运的是,我使用的.Net 4工作得很好,谢谢-现在我只需要离开去了解它在做什么。。。
Function ShouldExectute() As Boolean
Sub Execute()
ReadOnly Property DatabaseId as Long
ReadOnly Property Name as String
ReadOnly Property IsDisabled As Boolean