C# 强制转换到基类将抛出InvalidCastException

C# 强制转换到基类将抛出InvalidCastException,c#,casting,xml-deserialization,C#,Casting,Xml Deserialization,我的一个程序集包含以下“提供程序”类型: 我还有一个XML文件,它使用DeviceInfoProvider基类保存提供者信息。简化版本如下所示: <DeviceInfoProvider Type="SbRioI2CProvider" Assembly="assembly.dll" > </DeviceInfoProvider> <DeviceInfoProvider Type="GenericProvider" Assembly="assembly.dll" &g

我的一个程序集包含以下“提供程序”类型:

我还有一个XML文件,它使用
DeviceInfoProvider
基类保存提供者信息。简化版本如下所示:

<DeviceInfoProvider Type="SbRioI2CProvider" Assembly="assembly.dll" >
</DeviceInfoProvider>
<DeviceInfoProvider Type="GenericProvider" Assembly="assembly.dll" >
</DeviceInfoProvider>
阅读XML后,使用以下代码实例化我的类型:

var assembly = Assembly.LoadFrom(assemblyPath);

var type = (from t in assembly.GetTypes()
            where t.IsPublic && t.Name == typeName
            select t).FirstOrDefault();

if (type != null)
{
    instance = type.GetConstructor(Type.EmptyTypes).Invoke(null);
}
正如预期的那样,这会适当地生成我的对象

当我尝试将实例强制转换为基类对象时,问题出现了:

using (var provider = instance as DeviceInfoProvider)
{
    // provider is null!
}
instance
的运行时类型是预期的派生类,但我无法将其成功转换为其基类型


我缺少什么?

调用反射类型的构造函数不会创建它的实例

要创建反射类型的实例,请调用
Activator.CreateInstance

看起来这行应该是:

if (type != null) {
    instance = Activator.CreateInstance(type)
}
这将导致
实例
的类型为
对象
,但现在您可以将其强制转换为您想要的任何类型


请参阅:

您的问题可能是您正在LoadFrom上下文中从assembly.dll中的类型创建实例(GenericProvider、SBRIO2CProvider)。然后,您尝试按名称强制转换该程序集中的类型(DeviceInfo Provider)。这隐式地使用了加载上下文。运行时将来自同一程序集但在不同上下文中加载的类型视为不同的类型,因此强制转换失败,您将得到null。本文对程序集绑定上下文提供了一些额外的解释


要使此强制转换成功,需要将加载在LoadFrom上下文中的
程序集
加载到加载上下文中。有几种方法可以做到这一点。一种方法是将组件放入GAC中。另一种方法是从applicationbase中删除assembly.dll,以便通过探测不会找到它。然后使用AppDomain.AssemblyResolve事件加载通过LoadFrom获得的
程序集

那么,
Invoke
方法的返回值是多少?我知道了<代码>与构造函数关联的类的实例。我以前从未见过以这种方式创建的反射类型的实例。如果您进一步筛选Linq表达式以排序不是从
DeviceInfo提供程序派生的类型
,您是否仍然得到了您所寻找的相同类型?有关
ConstructorInfo.Invoke
的文档指出,
Activator.CreateInstance
应用于“创建没有实例构造函数的值类型的实例”。尽管如此,我还是尝试了它,但没有任何区别变量
typeName
的值是多少?从XML或常量字符串值“DeviceInfo Provider”读取?所有这些类型都在同一程序集中吗?@mikez:从XML加载的类型不必都在同一程序集中assembly@llj098:是的,它是从XML读取的。我已经更新了问题。谢谢你的解释和链接。给程序集一个强名称就成功了!
if (type != null) {
    instance = Activator.CreateInstance(type)
}