2009-10-24 67 views
1

这只是关于如何为COM导入编写代码的问题。关于如何正确声明互操作接口的说明

我的正确实施的互操作界面的理解是,主要标准是:

  1. 所有方法签名必须以兼容的方式
  2. 方法必须准确显示在相同的顺序相匹配。 Net接口与非托管接口一样
  3. 当非托管接口继承自另一个非托管接口时,托管实现必须首先声明基本级接口成员,从最底层接口开始。

我的问题是;如果我正在导入的接口从另一个接口继承并覆盖/隐藏基接口中的一个或多个成员,我该如何处理成员出现的顺序?接口成员声明去了哪里?首先,基础接口在哪里声明?或者从原来的位置移除并放置在派生接口声明的位置?

[uuid(31d1c294-1dd2-11b2-be3a-c79230dca297)] 
interface BaseComInterface 
{ 
    void method1(); 
    void method2(); 
    void method3(); 
} 

[uuid(fab51c92-95c3-4468-b317-7de4d7588254)] 
interface DerivedComInterface : BaseComInterface 
{ 
    void method1(); 
    void method4(); 
    void method5(); 
} 

现在的C#代码:

[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IDerivedComInterface 
{ 
    void method1(); // do I remove this one? 
    void method2(); 
    void method3(); 
    void method1(); // or this one? 
    void method4(); 
    void method5(); 
} 

回答

1

你有没有一个真正在做这件事的人的例子?虽然在一个接口和另一个从它派生的接口中使用同一个方法的名称在COM中是完全合法的,但它在几乎所有的开发环境中使派生接口很难或不可能工作。这包括实现以及根据接口调用任何COM对象。

在COM接口中没有重写或隐藏的东西。 COM接口只是对象的二进制接口在内存中的布局的约定,接口定义中的方法名称除了工具之外没有任何意义。在你的情况下,BaseComInterface承诺一个带有六个方法的'vtable',前三个匹配IUnknown方法的签名,接下来的三个匹配你给出的三个方法的签名,所有这些都按正确的顺序排列。另一方面,DerivedComInterface承诺包含九个方法的“vtable”,前三个签名与IUnknown方法匹配,接下来的三个与BaseComInterface方法的签名匹配,最后三个匹配DerivedComInterface特有的三个方法。这些方法的名称是不重要的,除了您的IDE,工具和编译器需要名称来查找'vtable'指针。因此,基本上,在C#以及C,C++和其他一些语言中,为了实现DerivedComInterface,需要对其中一个方法名进行装饰以区分它的'vtable'插槽。

要回答你的问题 - 因为它们都需要在那里履行COM合同,你会删除既不方法:

[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IDerivedComInterface 
{ 
    void method1(); 
    void method2(); 
    void method3(); 
    void method1_2(); //Decorated to distinguish from base interface method. 
    void method4(); 
    void method5(); 
} 

这忽略,如果这些接口从IDispatch接口而不是IUnknown的派生会发生什么,一团糟,我不想进入。另外,请记住,如果您的idl确实将方法定义为返回void,则必须使用PreserveSig属性修饰您的C#方法。

+0

很好的答案,非常丰富,谢谢! – 2009-10-25 19:01:12

0

我建议你使用explicit interface member implementations避免冲突。

+0

我不认为你读了这个问题。我在这里谈论的是interop代码,而不是纯粹的托管继承。 – 2009-10-24 21:01:49

+0

那你为什么要在C#中实现接口呢?界面由其他人实现。你只需要将COM对象的RCW强制转换为你想要的接口。 .Net会为你调用QueryInterface。 – 2009-10-24 21:54:08