在C#中实现DISPID_VALUE并从C ++中调用它

时间:2012-12-15 15:58:05

标签: c# c++ com

我有一个接受IDispatch接口的C ++ COM模块,在某些条件下使用DISPID_VALUE调用它们。这种方法在C ++中运行良好。现在我在C#中有一个客户端,我想实现一个实现IDispatch的对象,并且有一个DISPID = 0(DISPID_VALUE)的方法。我已经尝试过了:

// This will generate invalid cast
[ComVisible(true)]
class Callback1
{
    [DispId(0)]
    void Execute(object arg) {...}
}

// This also generate invalid cast
[ComVisible(true)]
[Guid("163AC24E-90DB-47D4-8580-EBB21E981FBF"),
    InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
interface ICallback2
{
    [DispId(0)]
    void Execute(object arg) ;
}
[Guid("842A7754-7CE6-4991-9E12-3FAB2367591A"),
    ClassInterface(ClassInterfaceType.None),
    ComSourceInterfaces(typeof(ICallback2))]
class Callback2 : ICallback2
{
    public void Execute(object arg) {}
}

我也不记得怎么样,但是我也写了一个成功投射的代码,但什么都没有。现在我想知道如何编写一个实现IDispatch的类,并在DISPID = 0时调用特定的方法。

施放例外是:

System.InvalidCastException was unhandled
  Message=Specified cast is not valid.
  Source=mscorlib
  StackTrace:
   at System.StubHelpers.InterfaceMarshaler.ConvertToNative(Object objSrc, IntPtr itfMT, IntPtr classMT, Int32 flags)
   at nmclientLib.INMAsyncOperation.AddCallback(Object pCallback)
   at NMTools.RecorderRegistration.BeginConnection(OperationDoneHandler h) in D:\Programming\Version 0.9\A_Project\NMTools\RecorderRegistration.cs:line 166
   at NMTools.ConnectionManager.NoRequestRegisterConnection(RecorderRegistration r, Boolean bConnect) in D:\Programming\Version 0.9\A_Project\NMTools\ConnectionManager.cs:line 396
   at NMTools.ConnectionManager.<InitializeFromDatabase>b__0(Object s, EventArgs e) in D:\Programming\Version 0.9\A_Project\NMTools\ConnectionManager.cs:line 339
   at System.Windows.Forms.Timer.OnTick(EventArgs e)
   at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(Form mainForm)
   at TestApp1.Program.Main() in D:\Programming\Version 0.9\A_Project\TestApp1\Program.cs:line 18

InnerException:

1 个答案:

答案 0 :(得分:3)

好的,从评论中可以清楚地看出问题所在。您必须声明[ComVisible]接口和类 public 。 CLR尊重可访问性,当.NET程序不能这样做时,COM客户端不会使用内部类型。

更好的异常消息本来不错,但这与COM错误处理过程相同。其中没有任何类似于可访问性约束的内容,因此没有比E_NOINTERFACE更具体的错误代码。哪个被转换为InvalidCastException。

值得注意的是,这种情况非常罕见,在.NET应用程序中使用[ComVisible] .NET类没有多大意义。只需通过添加对程序集的引用直接使用该类。你将摆脱注册要求,令人讨厌的错误消息和方法调用中的一大块开销。模数某种你无法摆脱的COM层,就会发生这种情况。