【问题标题】:Passing strongly typed arguments in .NET COM interop在 .NET COM 互操作中传递强类型参数
【发布时间】:2012-12-29 03:42:43
【问题描述】:

我有两个通过 COM 互操作公开的 .NET 类 - 比如说 Foo 和 Bar,我需要将 Foo 类型的参数传递给 Bar 中定义的方法。像这样的:

[ComVisible(true)]
public class Foo
{
    // whatever
}

[ComVisible(true)]
public class Bar
{
    public void Method(Foo fff)
    {
        // do something with fff
    }
}

当我运行以下 VBS(使用 cscript.exe)时:

set foo = CreateObject("TestCSProject.Foo")
set bar = CreateObject("TestCSProject.Bar")
call bar.Method(foo)

我得到一个错误:

D:\test.vbs(3, 1) Microsoft VBScript runtime error: Invalid procedure call or argument: 'bar.Method'

但是,如果我将方法声明更改为:

    public void Method(object o)
    {
        Foo fff = (Foo)o;
        // do something with fff
    }

一切正常。我尝试了一些关于接口、属性等的魔法,但到目前为止没有运气。

有什么见解吗?

非常感谢

【问题讨论】:

  • 它应该像发布的那样工作,VBScript 使用后期绑定。尝试改进您的 sn-p 以创建一个以同样方式失败的示例。
  • @Hans - 我添加了失败的 VBS sn-p。从真实代码中复制/粘贴的所有内容。谢谢

标签: c# .net com com-interop


【解决方案1】:

确保您定义了一个 GUID 属性,如果您创建一个 QueryInterface(VB 可能会这样做),这是必要的。您必须为每个可组合的类生成一个新的唯一 GUID。

[Guid("77777777-3333-40df-9C0D-2B580E7E1F3B")]
[ComVisible(true)]
public class Foo
{
}

然后我强烈建议为您的 COM 对象编写接口,并将 ClassInterface 设置为 None,因此不会显示任何内部结构。这样你的类型库会更干净。

[Guid("88888888-ABCD-458c-AB4C-B14AF7283A6B")]
[ComVisible(true)]
public interface IFoo
{
}

[ClassInterface(ClassInterfaceType.None)]
[Guid("77777777-3333-40df-9C0D-2B580E7E1F3B")]
[ComVisible(true)]
public class Foo : IFoo
{
}

【讨论】:

  • VB 不查询具体的接口。它使用IDispatch。无论如何,这里的问题在于 Foo 参数的编组方式。
  • @Ran 将其编组为 IUnknown 时,您所做的与 Elephantik 将参数声明为对象时所做的相同,这有效,但不是强类型。 IDispatch 直接继承自 IUnknown,因此 VB 在请求特定接口(或类)时可以使用 QueryInterface。
  • 其实我就是这么做的。创建接口,指导一切,但没有运气。我只是不想淹没源代码。
  • @Elephantik - 我们一直都是这样做的。是否为 CoClass 设置了 ClassInterfaceType.None 属性,所以只导出接口? “方法”的参数当然应该是 IFoo 类型(不是 Foo)。
  • 我尝试了 ClassInterfaceAttribute 并且它有效,然后我将其删除,它仍然有效。所以我重新创建了这个例子,出乎意料的是,一切正常。完全不知道出了什么问题。无论如何,谢谢你的帮助。
【解决方案2】:

在同一个问题苦苦挣扎一段时间后,我发现通过引用而不是按值传递参数存在问题。见这里:

http://msdn.microsoft.com/en-us/library/ee478101.aspx

所以我只是在VB Script中为传递的参数添加了圆括号,它似乎已经解决了这个问题。因此,在您的示例中,只需这样做:

Set foo = CreateObject("TestCSProject.Foo")
Set bar = CreateObject("TestCSProject.Bar")
Call bar.Method((foo))

应该按预期工作,无需设置 ClassInterface 属性,也无需使用接口。

【讨论】:

    猜你喜欢
    • 2019-02-12
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    • 2010-11-14
    • 2011-12-21
    • 1970-01-01
    • 2012-02-27
    • 2016-10-07
    相关资源
    最近更新 更多