3

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

继承树

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

<DeviceInfoProvider Type="SbRioI2CProvider" Assembly="assembly.dll" >
</DeviceInfoProvider>
<DeviceInfoProvider Type="GenericProvider" Assembly="assembly.dll" >
</DeviceInfoProvider>

在运行时,我将 XML 字段映射到我的变量:

assembly.dll  ⇒ assemblyPath
Type          ⇒ typeName

在阅读 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是预期的派生类,但我无法成功地将其转换为它的基类型。

我错过了什么?

4

2 回答 2

2

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

要使此转换成功,您需要Assembly将 LoadFrom 上下文中加载的内容放入 Load 上下文中。有几种方法可以做到这一点。一种方法是将程序集放在 GAC 中。另一种是从应用程序库中删除assembly.dll,这样它就不会被探测发现。然后使用 AppDomain.AssemblyResolve 事件加载Assembly您通过 LoadFrom 获得的内容。

于 2012-04-05T06:20:53.103 回答
0

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

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

这条线看起来应该是:

if (type != null) {
    instance = Activator.CreateInstance(type)
}

这将导致instancetype object,但现在您可以将其转换为您想要的任何内容。

请参阅:http: //msdn.microsoft.com/en-us/library/wccyzw83.aspx

于 2012-04-05T02:22:45.840 回答