Резюме вопроса

Когда я использую VBA {{X0 }}, передав ей экземпляр класса Object, доступного в ссылка на библиотеку mscorlib.dll (.NET ссылка на библиотеку), возвращаемое значение: 8.

Согласно документации VBA здесь, это означает, что объект является строкой. Это кажется смешным.

У меня вопрос: почему { Функция {X0}}, возвращающая значение строкового типа для экземпляров этого класса Object из ссылки VBA для библиотеки .NET? Это ошибка?

Исходная информация

Я подозреваю, что тот факт, что функция VarType в VBA говорит, что определенный COM-объект является строкой, может быть причиной того, что у меня возникают проблемы с использованием DispCallFunc в некоторых методах определенных объектов COM. COM-объекты - это COM-версии объектов .NET, доступные через .NET Framework.

Я использую ссылку VBA mscorlib.dll, чтобы получить функциональность раннего связывания для этих объектов. Ссылка относится к версии 4.0.30319 .NET Framework. На моем компьютере библиотека типов для ссылки хранится по адресу:

C : \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ mscorlib.tlb .

Это похоже на то, когда метод объекта указывает, что аргумент или возвращаемое значение должны иметь тип System.Object, DispCallFunc не работает для меня. В любом случае, это отдельная проблема, которая является косвенной по отношению к проблеме, которой посвящен этот вопрос.



Когда я использую функцию VarType с экземплярами других классов из библиотеки mscorlib.dll, я иногда получаю возвращаемые значения 9 & 13 (VbVarType.vbObject & {{X4} } константы), что кажется правильным.

Я проверил в Интернете, чтобы узнать, сталкивался ли кто-то еще с этой проблемой, но ничего не смог найти.

Код, который можно использовать для воспроизведения проблемы

Dim o As mscorlib.Object
Set o = New mscorlib.Object
Debug.Print "TypeName(o) = " & TypeName(o) ' TypeName function seems to work correctly.
Debug.Print "o.Equals(o) = " & o.Equals(o) ' System.Object.Equals method is working.

Debug.Print "VarType(CVar(o)) = " & VarType(CVar(o)) ' IMPORTANT LINE
' VBA VarType function says o is string (type 8) but it isn't?!

Debug.Print "VbVarType.vbString = " & VbVarType.vbString

Я ожидал, что VarType(CVar(o)) вернет 9, 13 или другое подходящее целое число. Вместо этого он возвратил 8, который не кажется подходящим (8 представляет строки.)

5
Mark Fernandes 12 Апр 2019 в 23:32

2 ответа

Лучший ответ

Если вы откроете typeLib C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb с помощью OleView например, и перейдите к интерфейсу _Object (не первый _Object, dispinterface, а второй), вы увидите это:

enter image description here

Итак, метод .NET Object.ToString() объявлен клиентам COM / Automation как

[id(00000000), propget, custom(54FC8F55-38DE-4703-9C4E-250351302B1C, 1)]
HRESULT ToString([out, retval] BSTR* pRetVal);

Это означает, что он виден COM-клиентам, которые понимают этот «синтаксический сахар» (VB / VBA / VBScript / JScript / .NET и т. Д.) Как свойство (propget + out + retval) с именем {{X0 }}, который возвращает String (BSTR).

Теперь id(0) означает, что это свойство по умолчанию , потому что 0 представляет DISPID_VALUE, специальный известный идентификатор.

И, наконец, VB / VBA VarType's Документация гласит:

Если объект имеет свойство по умолчанию, VarType (объект) возвращает тип свойства объекта по умолчанию.

(что я всегда находил довольно странным дизайнерским решением ...)

8
Simon Mourier 13 Апр 2019 в 07:51

Глядя на справочный источник для object.cs, я Я не вижу никаких [DispId] атрибутов, но при условии, что первый член будет маршализован с [DispId(0)], это сделает метод ToString типом COM по умолчанию .

Это единственное объяснение, которое я имею для вывода Debug.Print o System.Object, вместо того, чтобы сгореть с ошибкой 438, как это обычно бывает без члена по умолчанию.

Таким образом, проблема не столько в взаимодействии .NET / COM, сколько в том, чтобы получить метаданные из объекта, который имеет элемент по умолчанию: у вас будет точно такая же проблема с любым объектом COM, который имеет {{X0} } член по умолчанию:

?VarType(Application), VarType(Application.Name)
 8             8 

Я не могу придумать способ заставить VarType работать с ними. С другой стороны, проверка TypeOf...Is работает нормально:

?TypeOf Application Is Object
True

Отсюда:

Debug.Print TypeOf o Is Object ' True
1
Mathieu Guindon 12 Апр 2019 в 21:16