IsAssignableFrom与COM

时间:2014-05-27 08:53:55

标签: c# reflection com casting com-interop

我正在使用COM-API,Autodesk Inventor。

此测试通过:

[Test]
public void CastTest()
{
    Inventor.Document document = _application.ActiveDocument;
    var assemblyDocument = (Inventor.AssemblyDocument)document;
    Assert.NotNull(assemblyDocument);
}

此测试失败:

[Test]
public void IsAssignableFromTest()
{
    Assert.IsTrue(typeof(Inventor.Document).IsAssignableFrom(typeof(Inventor.AssemblyDocument)));
}

我对COM一点都不太了解,有没有办法检查一个COM类型是否“继承”另一个使用反射或一些COM巫毒?

1 个答案:

答案 0 :(得分:3)

COM类型系统与.NET不兼容。相反,你正在编写包装器(所谓的RCW)。为了测试是否可以将一个COM对象转换为另一个COM对象,COM将QueryInterface - 方法作为IUnknown的成员提供,每个COM对象都必须实现该方法。但是,.NET会为您隐藏这些详细信息,以便您可以编写“感觉”像.NET代码的COM代码。

如果您查看Inventors互操作库的反汇编,您会发现DocumentAssemblyDocument之间没有直接关系。两者都是仅实现其各自coclass的默认接口的接口,并且归属于CoClassAttribute。但是在他们的继承树中,它们并不直接相关。它们可能都实现了相同的接口(我想类似IDocument),但你也不能将WinForms按钮转换为图片框,即使它们都是Control - 接口。

这就是反射和IsAssignableFrom正在测试的内容:每个CLR类型提供的元数据。 COM在这里工作不同。如果可以从另一个接口调用COM对象,则每个COM对象都可以自行“决定”它。因此它实现了QueryInterface。因此,在执行测试之前,您必须创建源类型的实例(COM不知道静态成员)。

传统演员会调用QueryInterface,因此您的测试可能看起来像:

[Test]
public void IsAssignableFromTest()
{
    Assert.IsNotNull(_application.ActiveDocument as Inventor.AssemblyDocument);
}

否则,您可以通过Marshal - 类直接致电QueryInterface

但是,无法通过COM对象反射来测试类型元数据。