1. Есть проект "ActiveX Control", в его OCX'е живёт штук 20 разных контролов. В частности - поле ввода числовых значений dfDecimal, поле ввода строковых значений dfString, поле ввода даты dfDate, и т.д. Все они - надстройки над обычным текстбоксом.
2. Есть проект "ActiveX DLL", в котором живёт тип clsDialogBuilder. У этого типа, в частности, есть метод GetField(control_name), с return type Object. Этот метод возвращает контрол, заданный по имени, - из числа контролов, описанных выше - в п.1. Т.к. в зависимости от заданного имени, речь может идти о контролах разных типов (dfDecimal, dfString, dfDate, ...), то return type данного метода - именно Object!
3. Есть проект "ActiveX DLL", в одной из форм которого живёт вот такой код:
Private WithEvents cBuilder1 As clsDialogBuilder ' динамический построитель диалогов
' ...
' ...
' ...
Private Sub cBuilder1_ValidateForm(Cancel As Boolean)
Dim dfBaseAssetVolume As [B]dfDecimal[/B]
Set dfBaseAssetVolume = cBuilder1.GetField("dfBaseAssetVolume")
If dfBaseAssetVolume.Value < 0 Then
MsgBox "BaseAssetVolume can't be negative!", vbCritical, "Error"
dfBaseAssetVolume.SetFocus
Cancel = True
End If
Set dfBaseAssetVolume = Nothing
End Sub
Как уже говорилось выше, метод GetField объекта cBuilder имеет return type Object, и верхний Set обеспечивает преобразование из Object в dfDecimal, даруя нам счастье в виде типизированного контрола, а также интеллисенса в дальнейшем коде.
Всё работает, но... ПЕРИОДИЧЕСКИ падает на строке с первым Set'ом с ошибкой "Type Mismatch". Помогает пересборка (просто тупая пересборка, без каких-либо изменений) обеих DLL'ек (из п.2 и п.3).
Почему падает - не могу понять. Падает (иногда, но не всегда!) после пересборки DLL'ки из пункта 3 - т.е. DLL'ки, фрагмент кода приведён выше. А вот если пересобрать её вместе с DLL'кой из п.2 - всё исправляется. В общем, эти DLL'ки обречены теперь на "парную" сборку. Дуплетом. И объяснить я это не могу. Есс-с-сно, binary compatibility свято блюдётся и не нарушалась уже лет несколько.
Если же я пожертвую типизацией и интеллисенсом, и откажусь от преобразования типов, то всё заработает ОК:
Private WithEvents cBuilder1 As clsDialogBuilder ' динамический построитель диалогов
' ...
' ...
' ...
Private Sub cBuilder1_ValidateForm(Cancel As Boolean)
Dim dfBaseAssetVolume As [B]Object[/B]
Set dfBaseAssetVolume = cBuilder1.GetField("dfBaseAssetVolume")
' MsgBox TypeName(dfBaseAssetVolume)
If dfBaseAssetVolume.Value < 0 Then
MsgBox "BaseAssetVolume can't be negative!", vbCritical, "Error"
dfBaseAssetVolume.SetFocus
Cancel = True
End If
Set dfBaseAssetVolume = Nothing
End Sub
Кстати, MsgBox показывает "dfDecimal" :)
Нет ли у кого мыслей, от чего может происходить такая ерунда? почему ошибка "плавает"?
Ответить
|