【发布时间】:2012-12-15 15:58:05
【问题描述】:
我有一个接受 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
内部异常:
【问题讨论】:
-
代码看起来不错。您需要更好地解释您在何处以及如何看到“无效演员表”。 DISPID_INVOKE 没有其他任何意义,dispid 值 0 是 DISPID_VALUE 并且总是用于 COM 对象的默认属性。 Execute() 不是属性。
-
@HansPassant 好吧,我对代码很生气,写了
DISPID_INVOKE而不是DISPID_VALUE。 DISPID 0 也将用于默认属性和默认函数,例如在IE中,所有 JavaScript 函数都是具有执行它们的 DISPID = 0 方法的对象,这是我的类接受实现具有 DISPID 的函数的接口的主要原因= 0, 是支持 IE 中的 JavaScript! -
[ComVisible] 接口和类必须是公开的才能使用。这是另一个错字吗?
-
@HansPassant 非常感谢,我不知道,你想把它写成答案让我接受吗!
-
那条评论真的解决了问题吗?