我们开发了一个名为 XXadapter 的 .NET 程序集。目标是让 XXadapter 充当非托管客户端的 COM 对象。XXadapter 类实现了一个 C++ COM IDL 定义的接口。添加 C++ COM 对象作为对 C# 项目的引用,从而通过 Interop 公开 COM API。因此,类接口 _XXadapter 接口由 COM Interop 生成,并由非托管客户端使用。
在我尝试将 XXadapter 项目从 VS2010 迁移到 VS2012 之前,一切都很好(请注意,没有源代码更改)。_XXadapter 的 uuid 和 _XXadapter 中的一些方法的 DispID已更改。
这是 XXadapter 类的属性:
[ComVisible(true)]
[ComSourceInterfaces( typeof( _IBaseEvents ) )]
[ClassInterface(ClassInterfaceType.AutoDual)]
[Guid("class ID")]
public partial class XXadapter : ICOMInterface
{
...
}
这是迁移前类型库中的_XXadapter定义(由 oleview.exe 查看):
[
odl,
uuid(E8******-****-****-****-************),
hidden,
dual,
nonextensible,
oleautomation,
custom(123456-1234-1234-1234-123456789012, CompanyName.XXadapter)
]
interface _XXadapter : IDispatch {
[id(00000000), propget,
custom(654321-4321-4321-4321-210987654321, 1)]
HRESULT ToString([out, retval] BSTR* pRetVal);
[id(0x60020001)]
HRESULT Equals(
[in] VARIANT obj,
[out, retval] VARIANT_BOOL* pRetVal);
[id(0x60020002)]
HRESULT GetHashCode([out, retval] long* pRetVal);
[id(0x60020003)]
HRESULT GetType([out, retval] _Type** pRetVal);
[id(0x60020004)]
HRESULT GetVersion([out, retval] BSTR* pRetVal);
[id(0x60020005)]
HRESULT Method_one(...);
[id(0x60020006)]
HRESULT Method_two(...);
...
[id(0x6002000e)]
HRESULT Method_three(...);
[id(0x6002000f)]
HRESULT Method_four();
[id(0x60020010)]
HRESULT Method_five(...);
...
};
迁移后,_XXadapter定义为
[
odl,
uuid(E6****-****-****-****-************),
hidden,
dual,
nonextensible,
oleautomation,
custom(123456-1234-1234-1234-123456789012, CompanyName.XXadapter)
]
interface _XXadapter : IDispatch {
[id(00000000), propget,
custom(654321-4321-4321-4321-210987654321, 1)]
HRESULT ToString([out, retval] BSTR* pRetVal);
[id(0x60020001)]
HRESULT Equals(
[in] VARIANT obj,
[out, retval] VARIANT_BOOL* pRetVal);
[id(0x60020002)]
HRESULT GetHashCode([out, retval] long* pRetVal);
[id(0x60020003)]
HRESULT GetType([out, retval] _Type** pRetVal);
[id(0x60020004)]
HRESULT GetVersion([out, retval] BSTR* pRetVal);
[id(0x60020005)]
HRESULT Method_three(...);
[id(0x60020006)]
HRESULT Method_four(...);
[id(0x60020007)]
HRESULT Method_five(...);
[id(0x60020008)]
HRESULT Method_one(...);
[id(0x60020009)]
HRESULT Method_two(...);
...
};
不仅_XXadapter的uuid变了,所有Methods_XXXX()的DispID也变了。
结果,_XXadapter 程序集失去了与其 COM 客户端的向后兼容性。
通过对此问题的调查和搜索,我发现类型库中 Method_three/four/five() 的重新排序可能是由于这三个方法部分声明在单独的文件中造成的。我尝试将所有 COM 可见方法的声明移动到同一个文件中,这个问题可以解决。但是,这会产生一个我们原本想要避免的巨大文件。是否有任何解决方案可以在不移动 COM 可见方法的情况下保持向后兼容性?有谁知道重新排序方法的根本原因?太感谢了。