Статьи Королевства Дельфи

       

Объекты и их заместители


В предыдущем разделе речь шла только о типах инспектируемых объектов. В этом разделе "фокус ввода" перемещается на инспектируемые объекты. Как было сказано, инспектор получает доступ к значениям свойств на основе RTTI. Это означает, что инспектируемые классы должны содержать объявление и реализацию published-свойств. Если мы инспектируем классы визуальных компонентов, порожденных от TComponent, то это условие выполняется автоматически и никаких других усилий нам прикладывать не нужно. Если мы проектируем классы, специально рассчитанные на инспекцию, то мы можем удовлетворить этому требованию, если при объявлении классов укажем директиву {$M+} или будем порождать классы данных от TPersistent. Все свойства, доступные для инспекции, нужно объявить в секции published. В этом случае от нас также не требуется дополнительных усилий. Ситуация осложняется, если нам требуется инспектировать объекты, которые не содержат RTTI или вообще не являются Delphi-объектами. Такое может произойти, например, если:

  • мы вводим инспектор объектов в уже существующий проект, в котором изначально не предполагалось наличие инспектора,
  • требуется инспекция объектов, разработанных сторонними разработчиками,
  • объекты реализуются на другом языке программирования или доступны только через их интерфейсы (например, COM-объекты),
  • объекты размещаются в адресном пространстве другого процесса или на другой машине в локальной сети.
Для того, чтобы иметь возможность инспекции объектов различной природы и происхождения, вводится понятие "объект-заместитель" (proxy). Те, кто знаком с книгой Эриха Гамма и др. "Приемы объектно-ориентированного проектирования. Паттерны проектирования" сразу поймут, в чем дело. При инспекции объекта, который не содержит RTTI, динамически создается его заместитель, который, с одной стороны, имеет RTTI и соответствующие published-свойства, а, с другой стороны, содержит ссылку на инспектируемый объект и перенаправляет запросы на получение и изменение свойств соответствующим методам, интерфейсным входам или полям данных реального инспектируемого объекта. После инспекции объекта его заместитель просто уничтожается. Таким образом, для инспектора создается иллюзия, что он работает с родным Delphi-объектом. Способ создания proxy-объекта тесно связан с тем, как реализован сам инспектируемый объект. Естественно, что в каждом конкретном случае потребуется конкретное решение. Для примера предположим, что инспектируемый объект - прямоугольник, то есть, экземпляр записи типа TRect. Тогда реализация объекта-заместителя может быть такой:


type {$M+} TRect_Proxy = class public constructor Create(ARect: PRect); private FRect: PRect; // указатель на экземпляр записи function GetLeft: Integer; function GetTop: Integer; function GetWidth: Integer; function GetHeight: Integer; procedure SetLeft(const Value: Integer); procedure SetTop(const Value: Integer); procedure SetWidth(const Value: Integer); procedure SetHeight(const Value: Integer); published property Left: Integer read GetLeft write SetLeft; property Top: Integer read GetTop write SetTop; property Width: Integer read GetWidth write SetWidth; property Height: Integer read GetHeight write SetHeight; end; {$M-} constructor TRect_Proxy.Create(ARect: PRect); begin Assert(Assigned(ARect)); FRect := ARect; end; function TRect_Proxy.GetLeft: Integer; begin Result := FRect^.Left; end; ... procedure TRect_Proxy.SetHeight(const Value: Integer); begin FRect^.Bottom := FRect^.Top + Value; end;
Для случая, когда инспектируемый объект находится, например, на другой машине локальной сети, реализация прокси-объекта будет сложнее и определится тем, как конкретно реализовано сетевое взаимодействие.


Содержание раздела