1

IDispatchインターフェイスを受け入れるC++COMモジュールがあり、特定の条件でを使用してそれらを呼び出しますDISPID_VALUE。このメソッドはC++で非常にうまく機能します。これで、C#にクライアントがあり、 = 0( )IDispatchのメソッドを実装して持つオブジェクトを実装したいと思います。私はすでにこれを試しました:DISPIDDISPID_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) {}
}

また、その方法は覚えていませんが、キャストは成功するが何も呼び出さないコードも記述しています。ここで、 =0IDispatchのときに特定のメソッドを実装して呼び出すクラスを作成する方法を知りたいと思います。DISPID

キャストの例外は次のとおりです。

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:

4

1 に答える 1

3

さて、コメントから問題が何であったかは明らかです。[ComVisible]インターフェイスとクラスをpublicとして宣言する必要があります。CLRはアクセシビリティを尊重し、.NETプログラムでも内部型を使用できない場合、COMクライアントは内部型を使用できません。

より良い例外メッセージがあればよかったのですが、それはCOMエラー処理のコースと同等です。それ以外の点ではアクセシビリティの制約に似たものがないため、E_NOINTERFACEよりも具体的なエラーコードはありません。これはInvalidCastExceptionに変換されます。

注目すべきは、これは非常にまれであり、.NETアプリケーションで[ComVisible].NETクラスを使用することはあまり意味がありません。アセンブリへの参照を追加して、クラスを直接使用するだけです。メソッド呼び出しで、登録要件、ダッキーなエラーメッセージ、およびオーバーヘッドのチャンクを取り除くことができます。Moduloは、取り除くことができないある種のCOMレイヤーです。

于 2012-12-15T16:48:42.887 に答える