#delphi #function #constants
#delphi #функция #константы
Вопрос:
Рассмотрим следующий (не компилируемый) код:
program AttributesTestProgram;
{$APPTYPE CONSOLE}
uses
SysUtils,
Classes,
RTTI;
type
TDisplayTextAttribute = class(TCustomAttribute)
private
FDisplayText: string;
public
constructor Create(aDisplayText: string);
property DisplayText: string read FDisplayText write FDisplayText;
end;
constructor TDisplayTextAttribute.Create(aDisplayText: string);
begin
FDisplayText := aDisplayText;
end;
function GetFirstName: string;
begin
Result := 'First Name';
end;
type
TCustomer = Class(TObject)
private
FFirstName: string;
FLastName: string;
FStreetAddress: string;
FZIP: string;
FState: string;
FCity: string;
FPhone: string;
published
[TDisplayTextAttribute(GetFirstName)]
property FirstName: string read FFirstName write FFirstName;
end;
begin
// Code that does the work removed for clarity....
Readln;
end.
Естественно, мне интересно, почему это не удается скомпилировать с ошибкой:
[DCC Error] AttributesTestProgram.dpr(40): E2026 Constant expression expected
Я предполагаю, что это как-то связано с идеей, что атрибуты должны быть привязаны во время компиляции, или что-то в этом роде.
Следовательно, мои вопросы таковы:
Есть ли какой-либо способ «обойти систему» здесь и получить значение времени выполнения в этом месте атрибута?
Ответ №1:
Да, вам нужны константы, потому что параметры вычисляются до констант во время компиляции и хранятся в таблицах RTTI. Кроме того, атрибуты принадлежат классу, а не экземплярам объекта, поэтому, если у вас более одного TCustomer, ваша идея становится бессмысленной.
Вы можете обойти систему, предоставив атрибуту конструктор без параметров (или вообще без конструктора) и изменив свойство DisplayText на его метод, который принимает либо строку, либо объект, из которого вы можете извлечь строку.
Комментарии:
1. Спасибо, Мейсон. Я поиграю с этим.
2. И как мне вызвать этот новый метод при объявлении атрибута?
3. @Nick: … таким же образом, как вы бы вызывали метод для любого другого объекта? (Не уверен, что понимаю ваш вопрос.)
4. Далее, правильный ответ: «Вы не можете превзойти систему, и вам не следует этого хотеть» — что в значительной степени соответствует словам Мейсона. Я нашел другой, правильный способ инициализации параметров конструктора с помощью внедрения зависимостей, передав анонимный метод методу DelegateTo в Delphi Spring — не нужно пытаться настроить атрибут [Injection()].