如何 change/set COM class 的 GUID 从 TLB (TLH) 中的 EventArgs 继承
How to change/set GUID for COM class inherit from EventArgs in TLB (TLH)
我已经通过 COM-Interop 从用 C# 编写的库向 C++ 库公开了一些事件。一切正常,但我想以 COM 样式对该库进行版本控制。
当我尝试这样做时,我遇到了一个障碍 - 我无法在从该库的 TLB 导入的 TLH 文件中更改(设置)SampleEventArgs
class 的 GUID。下面是一个最小的工作示例。
在 C# 中实现所需的接口和 classes:
[Guid("37B8697D-BC5F-4CCB-8002-5F734B4765C8")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class SampleEventArgs : EventArgs
{
public int Count { set; get; }
}
[Guid("8F6E11DE-C892-4540-89C0-C59F628ABC20")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ISampleInterface
{
[DispId(1)]
void SampleMethod(object sender, SampleEventArgs e);
}
[Guid("945B64A6-B4E5-48E7-9DB0-89BF92DCFD0C")]
[ComSourceInterfaces(typeof(ISampleInterface))]
[ComVisible(true)]
public class SampleClass
{
public void SampleMethod()
{
SampleEventArgs args = new SampleEventArgs() { Count = 0 };
sampleEventHandler(this, args);
}
public event SampleEventHandler sampleEventHandler;
}
public delegate void SampleEventHandler(object sender, SampleEventArgs e);
导入TLB文件到C++工程生成TLH文件:
#import "C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb"
#import "com_interop_dll.tlb"
部分生成的TLH文件:
//
// 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# 代码中为 _SampleEventArgs
设置 GUID?我相信,此 GUID ("599c264e-506e-3780-97b6-c1edff5f4a66"
) 是自动生成的,并且可以手动设置此值。
只有声明了自己的接口才能控制[Guid]。在 COM 中非常重要,客户端代码总是与接口一起工作,并且实现总是隐藏的。你现在这样做的方式,类型库导出器被迫从 class 声明创建一个合成接口。
不可避免地,它还必须auto-generate接口的IID。否则不是坏事,接口在 COM 中是不可变的,如果您进行任何更改,那么您 必须 也更改 IID。
另请注意,您暴露的太多了,因此您必须导入 mscorlib.tlb。那不是很好。这是必需的,因为 auto-generated 接口还包括从 System.Object 继承的成员。在你的情况下是 EventArgs。 None 这个是有用的客户端代码。所以让它像这样:
[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。并编写 ISampleClass,方法相同。为 SampleClass 提供 [ClassInterface(ClassInterfaceType.None)] 属性,您将不再依赖于 mscorlib.tlb
我已经通过 COM-Interop 从用 C# 编写的库向 C++ 库公开了一些事件。一切正常,但我想以 COM 样式对该库进行版本控制。
当我尝试这样做时,我遇到了一个障碍 - 我无法在从该库的 TLB 导入的 TLH 文件中更改(设置)SampleEventArgs
class 的 GUID。下面是一个最小的工作示例。
在 C# 中实现所需的接口和 classes:
[Guid("37B8697D-BC5F-4CCB-8002-5F734B4765C8")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class SampleEventArgs : EventArgs
{
public int Count { set; get; }
}
[Guid("8F6E11DE-C892-4540-89C0-C59F628ABC20")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ISampleInterface
{
[DispId(1)]
void SampleMethod(object sender, SampleEventArgs e);
}
[Guid("945B64A6-B4E5-48E7-9DB0-89BF92DCFD0C")]
[ComSourceInterfaces(typeof(ISampleInterface))]
[ComVisible(true)]
public class SampleClass
{
public void SampleMethod()
{
SampleEventArgs args = new SampleEventArgs() { Count = 0 };
sampleEventHandler(this, args);
}
public event SampleEventHandler sampleEventHandler;
}
public delegate void SampleEventHandler(object sender, SampleEventArgs e);
导入TLB文件到C++工程生成TLH文件:
#import "C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb"
#import "com_interop_dll.tlb"
部分生成的TLH文件:
//
// 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# 代码中为 _SampleEventArgs
设置 GUID?我相信,此 GUID ("599c264e-506e-3780-97b6-c1edff5f4a66"
) 是自动生成的,并且可以手动设置此值。
只有声明了自己的接口才能控制[Guid]。在 COM 中非常重要,客户端代码总是与接口一起工作,并且实现总是隐藏的。你现在这样做的方式,类型库导出器被迫从 class 声明创建一个合成接口。
不可避免地,它还必须auto-generate接口的IID。否则不是坏事,接口在 COM 中是不可变的,如果您进行任何更改,那么您 必须 也更改 IID。
另请注意,您暴露的太多了,因此您必须导入 mscorlib.tlb。那不是很好。这是必需的,因为 auto-generated 接口还包括从 System.Object 继承的成员。在你的情况下是 EventArgs。 None 这个是有用的客户端代码。所以让它像这样:
[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。并编写 ISampleClass,方法相同。为 SampleClass 提供 [ClassInterface(ClassInterfaceType.None)] 属性,您将不再依赖于 mscorlib.tlb