Где Delphi атрибуты реальных примеров мира?
Я знаю TMS Aurelius что мы можем использовать функцию" новые " атрибуты 2010 для сериализации полей таблицы базы данных в свойства объекта во время выполнения, например, и я не эксперт по этой глубокой объектно-ориентированной схеме, поэтому я смотрю в исходный код TMS и не могу понять, как реализовать его сам, не для БД, не для XML.
поэтому я искал все результаты Google на Delphi Attributes
и все, что люди представляют декларации примеры, а затем останавливается перед даже показывая свои примеры в действии.
тогда где реальные примеры того, как мы можем проектировать, объявлять, кодировать и использовать эти сочные классы внутри формы/кода выполнения?
есть ли у кого-нибудь пример, чтобы поделиться здесь или знать хорошую статью, которая завершена?
Edit1:
ответ должен быть TForm
С TButton
где при нажатии выполнить некоторое использование созданных классов атрибутов, не отвечайте, показывая только атрибут и классы интерфейсы, потому что есть много из этих примеров объявления, как я сказал раньше
3 ответов
если вы хотите объявить свой собственный атрибут, вы можете сделать это следующим образом:
type
TDisplayLabelAttribute = class(TCustomAttribute)
private
FText: string;
public
constructor Create(const aText: string);
property Text: string read FText write FText;
end;
атрибут-это обычный класс, который имеет TCustomAttribute как его предок. Вы реализуете его как обычно:
implementation
constructor TDisplayLabelAttribute.Create(const aText: string);
begin
FText := aText;
end;
теперь атрибут объявлен и реализован, вы можете просто использовать это:
[DisplayLabel('My Class')]
TMyClass = class
end;
Итак, теперь у вас есть атрибут, объявленный и реализованный, и вы использовали его для добавления метки отображения в некоторый класс. Заключительный этап-использовать это атрибут, так как у вас есть класс оформлен С ним. Код, который использует атрибут, не находится ни в атрибуте, ни в украшенном классе, он реализован в слое сервиса, который будет использовать украшение.
предположим, у нас есть класс, который возвращает возможную метку отображения для класса:
type
TArtifactInspector = class
public
class function DisplayLabelFor(aClass: TClass): string;
end;
этот метод будет проверять класс и вернуть свою метку, учитывая, что он существует. В противном случае он возвращает пустую строку:
implementation
uses
Rtti;
class function TArtifactInspector.DisplayLabelFor(aClass: TClass): string;
var
rttiContext: TRttiContext;
rttiType: TRttiType;
attribute: TCustomAttribute;
begin
rttiContext := TRttiContext.Create;
try
rttiType := rttiContext.GetType(aClass);
for attribute in rttiType.GetAttributes do
if attribute is TDisplayLabelAttribute then
Exit(TDisplayLabelAttribute(attribute).Text);
Result := '';
finally
rttiContext.Free;
end; // try to recover and return the DisplayLabel
end;
Я должен сказать, что мне не очень ясно, какой пример вам нужен. ИМХО в http://docwiki.embarcadero.com/RADStudio/XE4/en/Overview_of_Attributes это все, что вам нужно, возможно, при условии, что у вас есть некоторые базовые знания аннотации и/или аспектного программирования.
пример зависит от способа/цели, для которой автор конкретного SW использовал атрибуты. Вы упомянули систему ORM: типичное использование здесь-аннотировать члена класса представление сущности БД с дополнительной информацией, необходимой для работы БД в бэкэнде такой структуры. Предположим, у вас есть объект DB, имеющий поле COMPANY CHAR (32) не NULL, и вы хотите представить его в классе Delphi:
TSomeDBEntity = class(...)
FCDS: TClientDataset;
...
constructor Create;
...
[TCharColumn('COMPANY', 32, false)]
property CompanyName: string read GetCompanyName write SetCompanyName;
end;
затем вы определите атрибут TCharColumn с помощью конструктора
constructor TCharColumn.Create(const AFieldName:string; ALength:integer; ANullable:boolean);
begin
inherited;
FName := AFieldName;
FLength := ALength;
FNullable := ANullable;
end;
и использование такой аннотации может выглядеть так:
FCDS := TClientDataset.Create(nil);
RttiContext := TRttiContext.Create;
try
RttiType := RttiContext.GetType(self.ClassType);
Props := RttiType.GetProperties;
for Prop in Props do
begin
Attrs := Prop.GetAttributes;
case Prop.PropertyType.TypeKind of
tkUString:
begin
for Attr in Attrs do
if Attr is TCharColumn then
begin
ColAttr := TCharColumn(Attr);
FCDS.FieldDefs.Add(ColAttr.FName, ftString, ColAttr.FLength, not ColAttr.FNullable);
end;
end;
else
//... ;
end;
end;
finally
RttiContext.Free;
end;
этот фрагмент программы демонстрирует, как определить поля в набор данных во время выполнения на основе аннотации в Delphi. Мы ограничены немного из-за отсутствие именованных параметров, поэтому работать с списке параметр не является гибким, как должно быть, например как в Java (сравните ТМС Аврелий аннотация набор http://www.tmssoftware.com/site/manuals/aurelius_manual.pdf и http://www.techferry.com/articles/hibernate-jpa-annotations.html
не уверен, что вопрос задает реальные примеры использования атрибутов или как сериализовать таблицы БД в объекты с использованием атрибутов. Приведенный ниже пример-надуманный простой (но тем не менее пример), показывающий, как использовать атрибуты для регистрации изменений свойств объекта.
определите свой пользовательский атрибут
//By convention attributes are *not* prefixed with a `T`
//and have the word `Attribute` in their name
LoggableAttribute = class(TCustomAttribute)
private
FDescription : String;
public
constructor Create(Description: String);
property Description: String read FDescription;
end;
"hello world" классов TProduct с помощью атрибута
TProduct = Class(TObject)
private
FPrice: Double;
FDescription: String;
..
public
[LoggableAttribute('Product Price')]
property Price : Double read FPrice write SetPrice;
[Loggable('Product Description')] {the `Attribute` part is optional}
property Description : String read FDescription write SetDescription;
property IsDirty : Boolean read FIsDirty;
End;
любой класс, который имеет "loggable атрибут" может быть передан этому методу, чтобы перебирать свойства и регистрировать их.
procedure LogChanges(LoggableClass: TObject);
var
c : TRttiContext;
t : TRttiType;
p : TRttiProperty;
a : TCustomAttribute;
Value : TValue;
begin
c := TRttiContext.Create;
try
t := c.GetType(LoggableClass.ClassType);
for p in t.getProperties do
for a in p.GetAttributes do
if a is TLoggableProperty then begin
Value := p.GetValue(LoggableClass);
// log to db..
AddLogEntry(p.Name, TLoggableProperty(a).Description, Value.ToString);
end;
finally
c.Free;
end;
конец;
пример использования:
var
P : TProduct;
begin
P := TProduct.Create;
P.LoadPropertiesFromDB;
...
... User edits price ...
...
P.Price := 499.99;
...
... Save product to DB
if P.IsDirty then // save and log
LogChanges(P);