C# 如何更改/设置从TLB(TLH)中的EventArgs继承的COM类的GUID 我通过COM互操作将C语言中的一些事件暴露给C++库。一切都很好,但我想在COM风格的版本库。 当我尝试这样做时,遇到了一个障碍-我无法更改(设置)从该库的TLB导入的TLH文件中的SampleEventArgs类的GUID。下面是一个简单的工作示例

C# 如何更改/设置从TLB(TLH)中的EventArgs继承的COM类的GUID 我通过COM互操作将C语言中的一些事件暴露给C++库。一切都很好,但我想在COM风格的版本库。 当我尝试这样做时,遇到了一个障碍-我无法更改(设置)从该库的TLB导入的TLH文件中的SampleEventArgs类的GUID。下面是一个简单的工作示例,c#,c++,com,com-interop,C#,C++,Com,Com Interop,在C#中实现所需的接口和类: 导入TLB文件到C++项目生成TLH文件: #import "C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb" #import "com_interop_dll.tlb" // // Forward references and typedefs // struct __declspec(uuid("23ece2ab-6e98-4301-8fff-eed74151d585")) /* LIBI

在C#中实现所需的接口和类:

导入TLB文件到C++项目生成TLH文件:

#import "C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb"
#import "com_interop_dll.tlb"
//
// Forward references and typedefs
//

struct __declspec(uuid("23ece2ab-6e98-4301-8fff-eed74151d585"))
/* LIBID */ __com_interop_dll;
struct /* coclass */ SampleEventArgs;
struct /* coclass */ SampleClass;
struct __declspec(uuid("599c264e-506e-3780-97b6-c1edff5f4a66"))
/* dual interface */ _SampleEventArgs;
struct __declspec(uuid("e82fc089-4301-3c69-bd80-4328a85b6314"))
/* dual interface */ _SampleClass;
生成的TLH文件的一部分:

#import "C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb"
#import "com_interop_dll.tlb"
//
// Forward references and typedefs
//

struct __declspec(uuid("23ece2ab-6e98-4301-8fff-eed74151d585"))
/* LIBID */ __com_interop_dll;
struct /* coclass */ SampleEventArgs;
struct /* coclass */ SampleClass;
struct __declspec(uuid("599c264e-506e-3780-97b6-c1edff5f4a66"))
/* dual interface */ _SampleEventArgs;
struct __declspec(uuid("e82fc089-4301-3c69-bd80-4328a85b6314"))
/* dual interface */ _SampleClass;

我的问题是如何在C代码中为
\u SampleEventArgs
设置GUID?我相信,此GUID(
“599c264e-506e-3780-97b6-c1edff5f4a66”
)是自动生成的,并且存在手动设置此值的可能性。

只有声明自己的接口,才能控制[GUID]。在COM中非常重要,客户端代码总是与接口一起工作,实现总是隐藏的。按照现在的方式,类型库导出器被迫从类声明创建合成接口

不可避免地,它还必须自动生成接口的IID。否则不是坏事,接口在COM中是不可变的,如果您做了任何更改,那么您还必须更改IID

还要注意,您暴露的内容太多,这是您必须导入mscorlib.tlb的原因。那不太好。这是必需的,因为自动生成的接口还包括从System.Object继承的成员。在你的情况下,还有事件参数。所有这些对客户端代码都没有用处。让它像这样:

[Guid("599c264e-506e-3780-97b6-c1edff5f4a66")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[ComVisible(true)]
public interface ISampleEventArgs {
    int Count { set; get; }
}
客户端必须实现此接口才能获取事件,无需公开您的实现:

[ComVisible(false)]
public class SampleEventArgs : EventArgs, ISampleEventArgs
{
   public int Count { set; get; }
}

更改ISampleInterface.SampleMethod以公开ISampleEventArgs。写一个简单的类,同样的配方。为SampleClass赋予[ClassInterface(ClassInterfaceType.None)]属性,您就不再依赖于mscorlib.tlb,只有在声明自己的接口时才能控制[Guid]。在COM中非常重要,客户端代码总是与接口一起工作,实现总是隐藏的。按照现在的方式,类型库导出器被迫从类声明创建合成接口

不可避免地,它还必须自动生成接口的IID。否则不是坏事,接口在COM中是不可变的,如果您做了任何更改,那么您还必须更改IID

还要注意,您暴露的内容太多,这是您必须导入mscorlib.tlb的原因。那不太好。这是必需的,因为自动生成的接口还包括从System.Object继承的成员。在你的情况下,还有事件参数。所有这些对客户端代码都没有用处。让它像这样:

[Guid("599c264e-506e-3780-97b6-c1edff5f4a66")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[ComVisible(true)]
public interface ISampleEventArgs {
    int Count { set; get; }
}
客户端必须实现此接口才能获取事件,无需公开您的实现:

[ComVisible(false)]
public class SampleEventArgs : EventArgs, ISampleEventArgs
{
   public int Count { set; get; }
}

更改ISampleInterface.SampleMethod以公开ISampleEventArgs。写一个简单的类,同样的配方。将[ClassInterface(ClassInterfaceType.None)]属性赋予SampleClass,就我所知,您不再依赖于mscorlib.tlb

。NET事件机制将额外数据作为从EventArgs派生的参数类传递,因此我不能改用ISampleEventArgs。否,客户端必须实现接口才能获取事件。想想看,我不应该发布SampleEventArgs。已删除。据我所知,传递附加数据的.NET事件机制需要作为从EventArgs派生的参数类,因此我不能改用ISampleEventArgs。不,必须由客户端实现接口才能获取事件。想想看,我不应该发布SampleEventArgs。删除。