2010-08-05 101 views
4

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

public interface IDTSComponentMetaData : IDTSComponentMetaData90 { } 

这就是它所做的一切。

这背后的原因是,根据我使用的SQL Server版本,基础可能是IDTSComponentMetaData90(2005)或IDTSComponentMetaData100(2008)。而不是有条件地编译代码中每个对IDTSComponentMetaData90/IDTSComponentMetaData100的引用,我想使用版本中立的接口,它将简单地包装适当的真实接口。

的问题是,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 .__ ComObject'的COM对象转换为'MyNameSpace.IDTSComponentMetaData'类型的接口。此操作失败,因为IID为“{483E01E7-001C-35E4-Ac9f-4B0C1B81E409}”的接口的COM组件上的QueryInterface调用由于以下错误而失败:没有支持此接口(异常来自HRESULT:0x80004002(E_NOINTERFACE)) 。

我在做什么完全错误?

回答

5

任何原因,你不只是取决于SQL Server版本的别名接口?

#if SQL2005 
using IDTSComponentMetaData = IDTSComponentMetaData90; 
#elif SQL2008 
using IDTSComponentMetaData = IDTSComopnentMetaData100; 
#endif 
+0

因为我真的是一个C++程序员,从来不知道可以用那种方式使用。我现在要试一下,如果它有效,你会为我节省很多痛苦! – 2010-08-05 21:10:30

+0

这将很好地工作,除了你不能集中指定,你必须在每个你想使用你的接口别名的文件的顶部指定它。 – 2010-08-05 21:22:50

+0

这看起来像在工作!太糟糕了C#没有#include指令,因为Lasse对重复是正确的,并且有大约14个.cs文件需要20个左右的替换。 但是,这仍然比替代方案的负载更好,这是为了保持2套源代码,2005年的另一个2008版本。 我想CRTL + C将成为我未来几个小时的新朋友。 – 2010-08-06 13:36:29

0

COM接口名称映射到接口ID(IID);此错误告诉您,您使用的对象不支持IDTSComponentMetaData90。

我会说你最好的选择是显式定义IDTSComponentMetaData,而不是从IDTSComponentMetaData90派生它。然后,您可以创建2个不同的类,通过对适用于SQL Server版本的COM接口进行转发方法调用来实现接口。

1

不幸的是,你试图做的事情是行不通的。

问题是底层对象实际上并未实现您的接口。它只实现特定的版本化界面,这是你试图摆脱的界面。

所以当你将对象转换到该接口时,它将失败。

在C#中可以做的最好的方法是通过别名界面,但不幸的是,这必须在需要使用此界面的每个.cs文件的顶部完成。

你有可能创建一个实现了你的接口的包装对象吗?然后,您自己的对象将实现新的接口,并将每个回调传递给底层对象上的相关方法/属性。在这个对象中,你可以做各种各样的#if和类似的东西来处理差异,但是隐藏与程序其余部分的差异。或者,你可以创建两个类,实现你的新接口,并使用IoC容器或类似的方法来请求“实现此接口的对象”,而不知道你实际正在与哪两个对话。

+0

我实际上正在走这条路,但@ dtb的解决方案实际上会更容易实现,因为我必须编写大约14个包装类。 – 2010-08-06 14:00:05

+0

他的方式工作?如果确实如此,它会为我节省一堆类似的问题,请告诉我们? – 2010-08-06 16:26:55

+0

是的,很好。我不得不在一堆.cs文件的顶部添加30个左右的“使用”行,但是我编译并运行了两个版本,没有出现问题。 – 2010-08-06 17:17:27

0

我相信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