代码之家  ›  专栏  ›  技术社区  ›  Marc Bernier

接口继承和转换

  •  4
  • Marc Bernier  · 技术社区  · 15 年前

    我创建了一个从另一个(COM)接口继承的接口:

    public interface IDTSComponentMetaData : IDTSComponentMetaData90 { }
    

    就这样。

    问题是SSIS在一个关键点将一个对象传递给本机接口,我需要将其转换为包装器接口:

    #if SQL2005
    public void Initialize(IDTSComponentMetaData90 c,IServiceProvider s) {
    #elif SQL2008
    public void Initialize(IDTSComopnentMetaData100 c,IServiceProvider s) {
    #endif
      m_ComponentMetaData = (IDTSComponentMetaData) c;
      m_ServiceProvider = s;
    }
    

    这样编译没有问题,但在运行时,我得到一个“无法将System.\u ComObject类型的COM对象强制转换为接口类型“MyNameSpace.IDTSComponentMetaData”。此操作失败,因为对IID为{483E01E7-001C-35E4-Ac9f-4B0C1B81E409}的接口的COM组件的QueryInterface调用由于以下错误而失败:不支持此类接口(HRESULT的异常:0x80004002(E\u NOINTERFACE))。

    我做的是不是完全错了?

    4 回复  |  直到 15 年前
        1
  •  5
  •   dtb    15 年前

    有什么理由不根据SQL Server版本简单地为接口设置别名?

    #if SQL2005
    using IDTSComponentMetaData = IDTSComponentMetaData90;
    #elif SQL2008
    using IDTSComponentMetaData = IDTSComopnentMetaData100;
    #endif
    
        2
  •  1
  •   Lasse V. Karlsen    15 年前

    不幸的是,你想做的事行不通。

    问题是底层对象实际上并没有实现您的接口。它只实现特定的版本化接口,即您试图摆脱的接口。

    在C语言中,最好的方法是对接口进行别名处理,但不幸的是,这必须在需要使用此接口的每个.cs文件的顶部进行。

    有没有可能创建一个包装器对象来实现您的接口呢?然后您自己的对象将实现新接口,并将每个调用传递回基础对象上的相关方法/属性。在这个物体上你可以做各种各样的 #if 的和类似的方法来处理差异,但是对程序的其余部分隐藏差异。

    或者,您可以创建两个类,它们都实现了您的新接口,并使用IoC容器或类似的容器来请求“实现此接口的对象”,而不知道您实际上在和这两个类中的哪一个说话。

        3
  •  0
  •   Paul Keister    15 年前

    我想说,这里最好的选择是显式定义IDTSComponentMetaData,而不是从IDTSComponentMetaData90派生它。然后可以创建两个不同的类,通过将方法调用转发到适合SQL Server版本的COM接口来实现接口。

        4
  •  0
  •   dtb    15 年前

    我相信COM接口的名称其实并不重要,所以创建自己的COM接口也可能有用(尽管我无法测试它)。

    #if SQL2005
    
    [ComImport]
    [Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IDTSComponentMetaData
    {
        // all members of IDTSComponentMetaData90
    }
    
    #elif SQL2008
    
    [ComImport]
    [Guid("YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IDTSComponentMetaData
    {
        // all members of IDTSComponentMetaData100
    }
    
    #endif