Несоответствие при передаче объектов из VBA в .NET через COM - PullRequest
3 голосов
/ 29 марта 2010

У меня есть следующий интерфейс для определения класса .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, как и ожидалось. Однако в последней строке я получил сообщение об ошибке «Требуется объект».

Почему установка значения с помощью метода set работает, но установка через свойство не удалась? Что мне нужно изменить, чтобы имущество работало должным образом?

Редактировать: у меня было несколько полезных ответов, поэтому мой дополнительный вопрос «возникнет ли эта проблема с COM-клиентами, написанными на других языках, или это специфично для VBA?».

Ответы [ 4 ]

4 голосов
/ 29 марта 2010

Ваш интерфейс экспортируется в библиотеку типов следующим образом:

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, вызванной поддержкой свойства по умолчанию. Вот почему вы должны использовать ключевое слово Set в VBA. Проблема в том, что вы не передаете объект в коде VBA, даже если .NET ожидает его.

После небольшого исследования я не нашел готового решения этой проблемы. Существует небольшая вероятность того, что ключевое слово Let может работать в VBA, я не пробовал. Единственное исправление на полпути - принудительное позднее связывание, вместо ComInterfaceType.InterfaceIsDual используйте ComInterfaceType.InterfaceIsIDispatch Или не используйте «объект».

1 голос
/ 30 марта 2010

Похоже, это проблема с 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)
0 голосов
/ 29 марта 2010

вы пробовали что-то вроде (немного ржавый, вы поняли):

Dim newValue as Int
int= 555.555
cc.Value = newValue (or maybe set cc.Value=newValue)
0 голосов
/ 29 марта 2010

Вам необходимо использовать ключевое слово Set в последней строке:

Set cc.Value = 555.555
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...