【发布时间】:2010-06-09 15:05:52
【问题描述】:
我正在尝试向 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 引用调用它?由于这将是客户使用的公共接口,我不喜欢必须解释为什么创建的所有对象都需要在一对额外的括号中传回...
【问题讨论】:
-
我在这个 sn-p 中没有看到 [ProgId]。这与真实代码有多接近? CreateFoo() 是否真的返回不同的接口?
-
这是我用来从更大的项目中重现问题的真实代码。它没有明确的 ProgId,它是从命名空间和类名生成的。