关于COM方法的marshal类参数怎么样?

时间:2014-04-28 15:07:15

标签: c# vbscript com pinvoke

我在VBSript中定义了一个类:

Class Foo
  Public i
End Class

我想将一个实例传递给用C#编写的COM对象:

Dim oCOMTEST : Set oCOMTEST = CreateObject("COMTests.Class1")

Dim oFoo : Set oFoo = new Foo
oFoo.i = 42
Call oCOMTEST.M(oFoo)

方法M定义为:

public void M(ref object foo)

目前该方法需要object,但我宁愿使用该方法 采用C#等价类型的Foo。其中我尝试过改变objectFoo

[StructLayout(LayoutKind.Sequential)]
public class Foo
{
  [MarshalAs(UnmanagedType.U4)]
  public int i;
}

但没有成功。因此我的问题是:

VBScript类型Foo的封送C#版本如何?

-

这是我的最小测试用例。

using System.Runtime.InteropServices;

namespace COMTests
{
  [ComVisible(true)]
  [Guid("4624071F-2D98-4ECC-8898-558F4D24EEC9")]
  [InterfaceType(ComInterfaceType.InterfaceIsDual)]
  public interface IClass1
  {
    void M(ref object foo);
  }

  [ComVisible(true)]
  [Guid("9F2B6958-742F-4E5D-A5F3-D6BDC6C841DB")]
  [ClassInterface(ClassInterfaceType.None)]
  [ProgId("COMTests.Class1")]
  public class Class1 : IClass1
  {
    public void M(ref object foo)
    {
      System.Diagnostics.Debugger.Launch();
    }
  }
}

以下VBScript:

Dim oCOMTEST : Set oCOMTEST = CreateObject("COMTests.Class1")

Dim oFoo : Set oFoo = new Foo
oFoo.i = 42
Call oCOMTEST.M(oFoo)

Class Foo
  Public i
End Class

1 个答案:

答案 0 :(得分:3)

VBScript类不是完整的COM对象,因为它没有与之关联的IID(接口ID)。所以,我可能错了,但我不认为你可以让它与.NET类或接口匹配(许多属性,如ComImport期望一个关联的Guid属性)。如果Foo是从“真正的”COM对象创建的,它可以工作。在后台,我相信VBScript的Foo对象只实现了IDispatch,所以它本质上非常动态。

但是,您仍然可以使用c#dynamic伪类型关键字轻松使用其属性和元数据,例如,以下代码应该可以正常工作:

[ComVisible(true)]
[Guid("9F2B6958-742F-4E5D-A5F3-D6BDC6C841DB")]
[ProgId("COMTests.Class1")]
public class Class1
{
    public void M(dynamic foo)
    {
        Console.WriteLine("foo:" + foo.i);
    }
}

PS:在此上下文中不需要接口或ref属性。使用上面的代码,这将由.NET自动创建(在IDL术语中,为了便于阅读,有点简化):

[
  uuid(E66DC08B-A63A-41A8-B63D-15ED6F4569AB),
  version(1.0),
]
library ClassLibrary1
{
    interface _Class1;

    [
      uuid(9F2B6958-742F-4E5D-A5F3-D6BDC6C841DB),
      version(1.0),
    ]
    coclass Class1 {
        [default] interface _Class1;
        interface _Object;
    };

    [
      odl,
      uuid(F56AF0FC-D93B-399E-8FBD-9B72CF50D7D9),
      hidden,
      dual,
      oleautomation,
    ]
    interface _Class1 : IDispatch {
    };
};