如何更改/设置COM类的GUID继承自TLB(TLH)中的EventArgs

时间:2016-01-12 20:20:29

标签: c# c++ com com-interop

我已经通过COM-Interop将一些用C#编写的库中的事件暴露给C ++库。一切正常,但我想用COM风格版本的这个库。 当我试图这样做时,我遇到了麻烦 - 我无法在从该库的TLB导入的TLH文件中更改(设置)SampleEventArgs类的GUID。以下是一个最小的工作示例。

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

[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")是自动生成的,并且可以手动设置此值。

1 个答案:

答案 0 :(得分:2)

如果您声明自己的界面,则只能控制[Guid]。在COM中非常重要,客户端代码始终与接口一起使用,并始终隐藏实现。你现在的方式是,类库出口商被迫从类声明中创建一个合成接口。

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

另请注意,您曝光过多,必须导入mscorlib.tlb。那不是很好。这是必需的,因为自动生成的接口还包括从System.Object继承的成员。在你的情况下和EventArgs。这些对客户端代码都没有用。所以让它类似于:

[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