Я написал набор компонентов, которые связывают друг с другом через опубликованные свойства интерфейса. Они регистрируются и устанавливаются в пакет дизайна.Опубликованные свойства интерфейса ошибки и обходные пути
Использование опубликованных свойств интерфейса не так распространено в Delphi, и, следовательно, неудивительно, похоже, что это не так хорошо работает.
Он отлично работает, когда компоненты находятся в одной и той же форме, однако свойства интерфейса между компонентами в разных формах вызывают проблемы.
В отличие от объектных ссылок на компоненты в другой форме, интерфейсные ссылки, похоже, не распознаются IDE. То, что я имею в виду, лучше всего описывается примером, когда у вас есть две формы, открытые в среде IDE, и у них есть ссылки между компонентами на них, а затем попытка переключиться на представление формы в виде текста (Alt + F12) приведет к тому, что IDE будет правильно жаловаться на то, что:
Module 'UnitXXX.pas' has open descendents or linked modules. Cannot close.
Но если свойство представляет собой интерфейс, то этого не произойдет, то, что происходит, а не в том, что связь разорвана (и это в лучшем случае, когда вы используете механизм уведомлений, чтобы удалить ссылки, в противном случае вы слева с недопустимым указателем)
Другая проблема, вероятно, как следствие такой же ошибки заключается в том, что при открытии проекта в среде IDE порядок, в котором формы будут повторно открыты d не определено, поэтому среда IDE может попытаться открыть форму, содержащую компоненты, которые имеют интерфейсы интерфейса к компонентам в другой форме, но эта другая форма еще не воссоздана. Таким образом, это эффективно приводит либо к AV, либо к разрытым ссылкам.
Еще в 90-х годах, когда я использовал Datasets
и Datasources
Я помню похожие проблемы со связями между исчезающими формами, поэтому это несколько похоже.
В качестве временного обходного пути я добавил повторяющиеся опубликованные свойства, для каждого свойства интерфейса я добавил другое, которое объявлено как TComponent
. Это означает, что Delphi знает, что существует связь между формами, но, по меньшей мере, является уродливым обходным решением.
Так что я задаюсь вопросом, есть ли что-то, что я могу сделать, чтобы исправить эту проблему? Это ошибка IDE и, вероятно, не исправляется напрямую, но, возможно, я могу переопределить что-то или иначе подключиться к механизму потоковой передачи, чтобы более эффективно обходить эту ошибку.
Я никогда не заходил так глубоко в потоковый механизм, но я подозреваю, что механизм Fixup должен иметь дело с этим. Существует csFixups
TComponentState
, поэтому я надеюсь, что обходной путь возможен.
Редактировать: Использование D2007.
Update:
Новых обновленного воспроизводимый пример загружен в http://www.filedropper.com/fixupbugproject2
Добавлен property ComponentReference: TComponent
так, что легко сравнить и проследить интерфейс против компонента потокового видео.
Я сузил проблему до уровня ассемблера, который немного отличается от моей глубины.
В процедуре GlobalFixupReferences
в classes
блоке он называет:
(GetOrdProp(FInstance, FPropInfo) <> 0)
, который в конечном счете выполняет:
function TInterfacedComponent.GetInterfaceReference: IInterface;
begin
// uncomment the code bellow to avoid exception
{ if (csLoading in ComponentState) and (FInterfaceReference = nil) then
// leave result unassigned to avoid exception
else
}
result := FInterfaceReference; // <----- Exception happens here
end;
Как вы можете видеть из комментария, единственный способ, которым я нашел, чтобы избежать исключения заключается в том, чтобы оставить результат неназначенным, но это нарушает функциональность, так как сравнение выше в GlobalFixupReferences
сбой из-за GetOrdProp <> 0
, что сокращает связь ,
трассировку глубже более точное местоположение исключения в
procedure _IntfCopy(var Dest: IInterface; const Source: IInterface);
в system
блок
Эта линия, в частности, поднимает read of address 0x80000000
{ Now we're into the less common cases. }
@@NilSource:
MOV ECX, [EAX] // get current value
Итак, почему MOV
терпит неудачу, и что случилось с ECX
или EAX
Я понятия не имею.
Это интересный вопрос. Это немного отличается от моего личного опыта. Я подозреваю, что у вас есть демонстрационный проект, который поможет любому начинающему исследователю. –
@DavidHeffernan Это довольно легко воспроизвести, все, что вам нужно, это потомок TComponent с опубликованным свойством типа IInterface. Зарегистрируйте его, установите пакет и поместите его на каждую из двух бланков. Сказав это, я мог бы сделать это сам и позволить вам, ребята, поиграть с ним ... –
Я думаю, что это поможет, если вы это сделаете. Опустите барьеры для нас. –