Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

"Управление версиями единиц с одинаковым интерфейсом в Delphi"

Delphi , Компоненты и Классы , Модули

В современном программировании часто возникает необходимость работать с разными версиями библиотек или единиц (units в терминологии Delphi), которые имеют одинаковые интерфейсы. Это может быть связано с использованием третьесторонних библиотек, которые периодически обновляются, или с необходимостью поддержки нескольких версий одного и того же продукта. В данной статье мы рассмотрим, как управлять версиями единиц с одинаковым интерфейсом в Delphi.

Проблема

Допустим, у вас есть две единицы, tissV01 и tissV02, которые импортируются из третьей стороны и имеют одинаковый интерфейс IXMLMensagemTISS. Вам нужно выбрать, какую из этих единиц использовать в вашем приложении в зависимости от некоторого условия.

unit tissV01;
interface
uses
type
  IXMLMensagemTISS = interface(IXMLNode)
    ['{11773827-F0A1-42E0-99E1-E221DFAF8542}']
    // Property Accessors
  end;
function GetmensagemTISS(Doc: IXMLDocument): IXMLMensagemTISS;
implementation
function GetmensagemTISS(Doc: IXMLDocument): IXMLMensagemTISS;
begin
  Result := XXXX as IXMLMensagemTISS;
end;
end.

unit tissV02;
interface
uses
type
  { IXMLMensagemTISS }
  IXMLMensagemTISS = interface(IXMLNode)
    ['{11773827-F0A1-42E0-99E1-E221DFAF8542}']
    // Property Accessors
    property Cabecalho: string read Get_Cabecalho;
  end;
function GetmensagemTISS(Doc: IXMLDocument): IXMLMensagemTISS;
implementation
function GetmensagemTISS(Doc: IXMLDocument): IXMLMensagemTISS;
begin
  Result := XXXX as IXMLMensagemTISS;
end;
end.

В вашем приложении вы хотите иметь выбор, какую единицу использовать:

unit test;
interface
uses
tissV01, tissV02, .........
type
  TMyform = class(TForm)
  public
    msg3:IXMLMensagemTISS;
  end;
implementation
procedure TMyform.ExecuteMessage:
var
  xmlTISS : TXmlDocument;
begin
  xmlTISS := TXmlDocument.Create(nil);
  if condition then
    msg3 := tissV01.GetmensagemTISS(xmlTISS)
  else msg3 := tissV02.GetmensagemTISS(xmlTISS);
  with msg3.Cabecalho do
    something;
end;
end.

Однако, это не работает, потому что IXMLMensagemTISS общий для обеих единиц.

Подтвержденный ответ

Если у вас есть два одинаковых идентификатора в разных единицах, вы можете использовать префикс имени единицы, чтобы различать их.

var
  a: tissV01.IXMLMensagemTISS;
  b: tissV02.IXMLMensagemTISS;

В вашем примере кода, однако, вам необходимо сделать явно выбор, какой интерфейс использовать.

uses
  tissV01, tissV02;  // последняя единица в uses получает приоритет.
type
  TMyform = class(TForm)
  public
    msg3: tissV01.IXMLMensagemTISS;   // разрешено
    msg2: tissV02.IXMLMensagemTISS;   // разрешено
    msgx: IXMLMensagemTISS; // неоднозначно, будет оцениваться как tissV02.IXMLMensagemTISS;
  end;

Последняя единица в списке uses получает приоритет. Этот факт часто используется для переопределения встроенных классов и интерфейсов собственными.

Если вы хотите отложить выбор на основе какого-либо условия, вы можете использовать условную компиляцию. Либо в списке uses (используя effet приоритета порядка списка uses), либо явно в объявлениях.

unit DoWork;
interface
uses
{$ifdef V01HasPriority}
  tissV02, tissV01;
{$else}
  tissV01, tissV02;
{$endif}

или явно в объявлениях

var
  a: {$ifdef useV01} tissV01.IInt {$else} tissV02.IInt {$endif}

Затем вы делаете выбор где-то еще, используя {$define V01HasPriority}, который компилируется перед {$ifdef ...}. Вы также можете объявить {$define ...} в IDE.

Проект > Параметры > Компилятор Delphi > Условные определения.

Вы можете выбрать интерфейс во время выполнения, только если интерфейсы совместимы. Это означает, что интерфейсы наследуются от общего предка. Каждый интерфейс имеет общий предок в IInterface, однако лучше выбрать интерфейс как можно ближе к обоим.

Затем объявите переменную как этот общий предок:

var
  a: ICommonInterface;
begin
  if x=1 then a:= tissV01.NewXMLInterface
  else a:= tissV02.NewXMLInterface;
  if Supports(a, tissV01.IXMLInt) then tissV01.IXMLInt(a).DoV01Things
  else tissV02.IXMLInt(a).DoV02Things;

Если оба интерфейса имеют одинаковую сигнатуру, то все становится намного проще (и намного здоровее).

var
  a: IXMLCommon;
begin
  if x=1 then a:= tissV01.NewXMLInterface
  else a:= tissV02.NewXMLInterface;
  a.DoCommonThings(param1, param2);

Централизация принятия решений Конечно, если у вас есть много решений, которые нужно принять, sometimes лучше централизовать их, чем раскидывать по всему вашему приложению.

Так почему бы не создать единицу, где все принятие решений будет происходить, как

Создано по материалам из источника по ссылке.

"В современном программировании на Delphi часто возникает проблема управления версиями единиц с одинаковым интерфейсом, что может затруднить выбор между ними в приложении."


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Модули ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 11:54:45/0.0058989524841309/1