gpt4 book ai didi

.net - 从 Visual Studio 2010 迁移到 2012 时,类接口(interface)的 uuid 和 DispID 发生了变化

转载 作者:行者123 更新时间:2023-12-01 11:41:46 26 4
gpt4 key购买 nike

我们开发了一个名为 XXadapter 的 .NET 程序集。目标是让 XXadapter 充当非托管客户端的 COM 对象。 XXadapter 类实现 C++ COM IDL 定义的接口(interface)。 C++ COM 对象被添加为对 C# 项目的引用,从而通过 Interop 公开 COM API。因此,类接口(interface) _XXadapter 接口(interface)由 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() 的重新排序可能是由于这三个方法在单独的文件中是 partially declared。我试图将所有 COM 可见方法的声明移动到同一个文件中,这个问题可以解决。然而,这会产生一个我们原本想避免的巨大文件。是否有任何解决方案可以在不移动 COM 可见方法的情况下保持向后兼容性?有谁知道重新排序方法的根本原因?太感谢了。

最佳答案

guids 必须改变,这是 COM 中坚如磐石的要求。您犯的潜在核心错误是公开类实现。从看到 System.Object 方法暴露在您的 coclass 中可见,例如 ToString、Equals 等。这使您面临编译器重新安排方法顺序的风险,这是一个未定义的实现细节。

正确的做法是始终让实现不可见。像这样:

[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("put the IID here")]
public interface IXXadapter {
string ToString();
bool Equals(object obj);
int GetHashCode();
Type GetType();
// etc...
}

[ClassInterface(ClassInterfaceType.None)]
[Guid("put the CLSID here")]
public class XXadapter : IXXadapter {
// etc..
}

注意 ClassInterfaceType.None,它隐藏了类的内部结构。 COM 客户端只看到接口(interface)声明,它们是固定的并且顺序是可预测的。我包含了您最初公开的 4 个 System.Object 方法,您不必编写它们的实现。这应该可以挽救您的二进制兼容性,只需确保更新 [Guid] 属性以匹配旧属性即可。

关于.net - 从 Visual Studio 2010 迁移到 2012 时,类接口(interface)的 uuid 和 DispID 发生了变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19733607/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com