接口inheritance和转换

我创建了一个接口,我从另一个(COM)接口inheritance:

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调用由于以下错误而失败:不支持此类接口(HRESULTexception:0x80004002(E_NOINTERFACE)) 。

我做的完全错了吗?

你不是简单地根据SQL Server版本对接口进行别名的原因吗?

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

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

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

因此,当您将对象转换为该接口时,它将失败。

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

你有可能创建一个实现你的界面的包装器对象吗? 然后您自己的对象将实现新接口,并将每个调用传递回基础对象上的相关方法/属性。 在该对象中,您可以执行各种#if和类似处理差异,但隐藏与程序其余部分的差异。

或者,你可以创建两个类,既实现你的新接口,又使用IoC容器或类似的东西来询问“实现这个接口的那个对象”,而不知道你实际在谈论哪两个。

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

我想说你最好选择明确定义IDTSComponentMetaData而不是从IDTSComponentMetaData90派生它。 然后,您可以通过对适用于SQL Server版本的COM接口的正向方法调用来创建2个实现该接口的不同类。

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