通过COM将对象从VBA传递到.NET不一致

时间:2010-03-29 15:54:14

标签: .net vba com

我定义了以下接口以将.NET类暴露给COM:

[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("6A983BCC-5C83-4b30-8400-690763939659")]
[ComVisible(true)]
public interface IComClass
{
    object Value { get; set; }

    object GetValue();

    void SetValue(object value);
}

这个界面的实现很简单:

[ClassInterface(ClassInterfaceType.None)]
[Guid("66D0490F-718A-4722-8425-606A6C999B82")]
[ComVisible(true)]
public class ComClass : IComClass
{
    private object _value = 123.456;

    public object Value
    {
        get
        {
            return this._value;
        }

        set
        {
            this._value = value;
        }
    }

    public object GetValue()
    {
        return this._value;
    }

    public void SetValue(object value)
    {
        this._value = value;
    }
}

然后我使用RegAsm注册了这个,并尝试通过以下代码从Excel中调用它:

Public Sub ComInterop()

    Dim cc As ComClass
    Set cc = New ComClass

    cc.SetValue (555.555)

    valueByGetter = cc.GetValue 
    valueByProperty = cc.Value 

    cc.Value = 555.555 

End Sub

当我逐步执行此代码时,valueByGetter = 555.5555和valueByProperty = 555.555正如预期的那样。但是,我在最后一行得到了“需要对象”的运行时错误。

为什么通过setter方法设置值有效但通过属性设置失败?为了让房产按预期工作,我需要做些什么改变?

编辑:我有一些有用的回复,所以我的另外一个问题是“这个问题会出现在用其他语言编写的COM客户端,还是特定于VBA?”。

4 个答案:

答案 0 :(得分:4)

您的界面将导出到类型库,如下所示:

dispinterface IComClass {
    properties:
    methods:
        [id(00000000), propget]
        VARIANT Value();
        [id(00000000), propputref]             // <=== problem here
        void Value([in] VARIANT rhs);
        [id(0x60020002)]
        VARIANT GetValue();
        [id(0x60020003)]
        void SetValue([in] VARIANT Value);
};

问题是Value属性设置器,它被声明为propputref而不是propput。完全不同的是COM中令人讨厌的一致性问题,它由支持默认属性引起。这就是你必须在VBA中使用Set关键字的原因。问题是:你没有在VBA代码中传递一个对象,即使.NET需要一个。

在研究了一下后,我发现没有现成的解决方案来解决这个问题。 Let关键字在VBA中可能起作用的可能性很小,我没有尝试过。唯一的中途修正是强制后期绑定,而不是ComInterfaceType.InterfaceIsDual使用ComInterfaceType.InterfaceIsIDispatch。或者避免使用“对象”。

答案 1 :(得分:1)

这似乎是tlbexp和使用后期绑定调用的MS建议的问题:

Dim cc As Object ' this one changed from ComClass
Set cc = New ComClass
...
cc.Value = 555.555

您可以将其保留在早期并尝试更简单的修复:

Set cc.Value = CVar(555.555)

答案 2 :(得分:0)

您需要在最后一行使用Set关键字:

Set cc.Value = 555.555

答案 3 :(得分:0)

你尝试过类似的东西(vb有点生疏,你明白了):

Dim newValue as Int
int= 555.555
cc.Value = newValue (or maybe set cc.Value=newValue)