我正在尝试向COM公开一个相当简单的C#类,它应该可以从VBScript(以及其他)中使用。 某些对象需要通过COM调用创建,稍后将用于进一步调用。暴露的类和接口的定义如下所示:
namespace Test
{
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IComInterface
{
IFoo CreateFoo();
void UseFoo(int x, IFoo f);
}
[ClassInterface(ClassInterfaceType.None)]
public sealed class CComInterface : IComInterface
{
public CComInterface() {}
public IFoo CreateFoo() { return new Foo(); }
public void UseFoo(int x, IFoo f) { f.Bar(); }
}
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IFoo
{
void Bar();
}
[ClassInterface(ClassInterfaceType.None)]
public class Foo : IFoo
{
internal Foo() {}
public void Bar() {}
}
}
VBScript中最简单的可思考COM客户端就是这样做的:
Dim ci
Set ci = WScript.CreateObject("Test.CComInterface")
Dim foo
Set foo = ci.CreateFoo
foo.Bar
ci.UseFoo 0, foo
当对Bar的调用成功时,调用UseFoo失败并显示“错误5:无效的过程调用或无效的参数”
生成的IDL对我来说似乎没问题:
dispinterface IComInterface {
properties:
methods:
[id(0x60020003)]
IFoo* CreateFoo();
[id(0x60020004)]
void UseFoo(
[in] long x,
[in] IFoo* f);
};
当我将第二个参数包装在括号中时,vbs调用成功,如下所示:
ci.UseFoo 0, (foo)
据我所知(但我不是VBScript专家),这会强制对foo的引用按值传递,即引用的副本。
如何更改界面以便可以直接使用foo参考调用它?由于这将是客户使用的公共界面,我不喜欢必须解释为什么所有创建的对象需要在一对额外的括号中传回的想法......
答案 0 :(得分:2)
public void UseFoo(int x, [MarshalAs(UnmanagedType.IDispatch)] IFoo f) { f.Bar(); }
答案 1 :(得分:1)
尝试更改C#界面以获取ref
参数。