В Delphi, часто возникает необходимость узнать имя текущего модуля (unit) во время выполнения программы. Например, для отладки, логирования или динамической настройки интерфейса. В этой статье мы рассмотрим несколько способов решения этой задачи, включая встроенные функции и альтернативные подходы.
Проблема:
Необходимо получить имя модуля, в котором выполняется код, чтобы, например, отобразить его в заголовке формы в режиме отладки.
Решение 1: Использование TObject.UnitName
TObject предоставляет классовую функцию UnitName, которая возвращает имя модуля, в котором определен класс. Это наиболее простой и рекомендуемый способ, если вы находитесь в контексте класса, унаследованного от TObject (например, в форме).
Необходимо вручную обновлять константу при переименовании модуля.
Не масштабируемое решение.
Решение 3: Использование RTTI (не идеально)
Можно использовать RTTI (Run-Time Type Information) для получения имени класса и извлечения из него имени модуля.
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Rtti;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
function GetUnitName(AClass: TClass): String;
var
RttiContext: TRttiContext;
RttiType: TRttiType;
begin
RttiType := RttiContext.GetType(AClass);
Result := RttiType.QualifiedName;
end;
begin
Caption := GetUnitName(TForm1); // Отображает "Unit1.TForm1"
end;
end.
Преимущества:
Работает динамически.
Недостатки:
Возвращает полное имя класса (например, "Unit1.TForm1"), а не только имя модуля.
Не подходит для утилитных модулей без классов.
Более сложный код.
Альтернативное решение (использование секции initialization)
Этот метод использует секцию initialization модуля и обработку исключений для получения имени файла модуля.
unit Unit1;
interface
uses
System.SysUtils, System.Classes;
var
UnitName: string;
implementation
{$R *.dfm}
initialization
try
{$ASSERTIONS ON }
Assert(False)
except
on E: EAssertionFailed do
begin
var MSG := E.Message;
var P := Pos('(', MSG);
Delete(MSG, 1, P);
P := Pos(')', MSG);
SetLength(MSG, Pred(P));
UnitName := ChangeFileExt(ExtractFileName(MSG), '');
end;
end;
end.
Преимущества:
Работает даже в утилитных модулях без классов.
Динамически получает имя модуля.
Недостатки:
Использует обработку исключений, что может быть не самым эффективным решением.
Зависит от включенных ASSERTIONS.
Вывод:
Наиболее простым и рекомендуемым способом получения имени текущего модуля в Delphi является использование классовой функции TObject.UnitName, если вы находитесь в контексте класса, унаследованного от TObject. Для утилитных модулей без классов, метод с использованием секции initialization может быть подходящим вариантом, хотя и имеет свои недостатки. Использование констант не рекомендуется из-за необходимости ручного обновления. RTTI может быть использован, но требует дополнительной обработки для извлечения только имени модуля.
Статья описывает способы получения имени текущего модуля в Delphi во время выполнения программы, предлагая несколько решений с использованием `TObject.UnitName`, констант, RTTI и секции `initialization`.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.