using attributes and rtti to automate programming tasks
DESCRIPTION
Using attributes and RTTI to automate programming tasks. Primo ž Gabrijelčič thedelphigeek.com. Attributes. “ Attributes are a language feature in Delphi that allows annotating types and type members with special objects that carry additional information . - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/1.jpg)
Using attributes and RTTI to automate
programming tasks
Using attributes and RTTI to automate
programming tasks
Primož Gabrijelčič
thedelphigeek.com
Primož Gabrijelčič
thedelphigeek.com
![Page 2: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/2.jpg)
Attributes
“Attributes are a language feature in Delphi that allows annotating types and type members with special objects that carry additional information.
This information can be queried at run time. Attributes extend the normal Object-Oriented model with Aspect-Oriented elements.”
- Delphi documentation
![Page 3: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/3.jpg)
Attributes
• Code annotation• Programmer annotates the code
• Run time querying• Program reads those annotations and reacts
accordingly
![Page 4: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/4.jpg)
Example
type TMyClass = class [MyAttribute][MyAttribute] FField: string; end;
![Page 5: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/5.jpg)
Implementation
• Attribute = class• Descending from TCustomAttribute• Traditionally not starting with a T and ending in an
Attribute
type MyAttribute = class(TCustomAttribute) end;
![Page 6: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/6.jpg)
Simplification
• Attribute part of the name can be removed in the annotation
• Standard practice
type TMyClass = class [MyAttribute][MyAttribute] FField1: string; [My][My] FField2: integer; end;
![Page 7: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/7.jpg)
RTTI
ctx := TRttiContext.Create;try t := ctx.GetType(aClass); for f in t.GetFields do for a in f.GetAttributes do …finally ctx.Free; end;
•Attributes exist only when observed!
![Page 8: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/8.jpg)
Useful helpers
• RTTIUtils• Robert Love
• DSharp.Core.Reflection• Stefan Glienke• Presentation tomorrow!
![Page 9: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/9.jpg)
Parameters
• Attributes can accept parameters
type TMyClass = class [StoreAs('ExternalField')][StoreAs('ExternalField')] FField: string; end;
![Page 10: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/10.jpg)
Constructor
• Add a constructor accepting appropriate parameters
type StorageAsAttribute =
class(TCustomAttribute) public constructor Create(externalName:
string); end;
![Page 11: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/11.jpg)
Overloaded attributes
• Attribute can accept different parameter types or variable number of parameters
type
TMyClass = class
[StoreAs('ExternalField1')][StoreAs('ExternalField1')]
FField1: string;
[StoreAs('ExternalField2', true)][StoreAs('ExternalField2', true)]
FField2: string;
end;
![Page 12: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/12.jpg)
Overloaded constructors
type StoreAsAttribute = class(TCustomAttribute) public constructor Create( externalName: string); overload; constructor Create(externalName: string; storeAsAttribute: boolean); overload; end;
![Page 13: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/13.jpg)
Default values
type StoreAsAttribute = class(TCustomAttribute) public constructor Create(externalName: string; storeAsAttribute: boolean = false); end;
![Page 14: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/14.jpg)
Advanced attributes
• Multiple attributes on one element
[Serialize][Serialize] [RootNode('Options')][RootNode('Options')] TewOptions = class [Serialize] [RootNode('Optons')][Serialize] [RootNode('Optons')] TewOptions = class [Serialize, RootNode('Options')][Serialize, RootNode('Options')] TewOptions = class
![Page 15: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/15.jpg)
Attributable entities
• Attributes can be applied to• classes, records• fields, properties• methods, method parameters• non-local enumeration declaration, variable
declarations
• Even to entities that are not accessible with RTTI!
![Page 16: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/16.jpg)
Problems
• Not working on generic classes
• W1025 Unsupported language feature: 'custom attribute‘
• Meaning can be unclear [GpManaged(true)][GpManaged(true)] FList: TObjectList;
![Page 17: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/17.jpg)
Practical examplesPractical examples
![Page 18: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/18.jpg)
Automatically created fields
type TewOptions = class(TGpManaged) strict private FActiveLanguage: string; FRibbonState : string; [GpManaged][GpManaged] FEditor : TewOpt_Editor; [GpManaged][GpManaged] FHotkeys : TewOpt_Hotkeys; [GpManaged][GpManaged] FNewWindow : TewOpt_NewWindow; [GpManaged][GpManaged] FRecentFiles: TRibbonRecentItemsStorage; public property ActiveLanguage: string read FActiveLanguage write FActiveLanguage; property Editor: TewOpt_Editor read FEditor; property Hotkeys: TewOpt_Hotkeys read FHotkeys; property NewWindow: TewOpt_NewWindow read FNewWindow; property RecentFiles: TRibbonRecentItemsStorage; property RibbonState: string read FRibbonState write FRibbonState; end;
![Page 19: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/19.jpg)
Object serialization - XML
type [XmlRoot('Person')][XmlRoot('Person')] TPerson = class(TObject) private FLastName: String; FBirthday: TDateTime; FMiddleName: String; FFirstName: String; public [XmlAttribute('First_Name')][XmlAttribute('First_Name')] property FirstName: String read FFirstName write FFirstName; [XmlElement('LAST_NAME')][XmlElement('LAST_NAME')] property LastName: String read FLastName write FLastName; [XmlIgnore][XmlIgnore] property MiddleName: String read FMiddleName write FMiddleName; property Birthday: TDateTime read FBirthday write FBirthday; end;
![Page 20: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/20.jpg)
Object serialization - INI
type TConfigSettings = class(TObject) private FConnString: String; FLogLevel: Integer; FLogDir: String; FSettingsFile: String; public // Use the IniValue attribute on any property or field // you want to show up in the INI File. [IniValue('Database','ConnectString','')][IniValue('Database','ConnectString','')] property ConnectString: String read FConnString write FConnString; [IniValue('Logging','Level','0')][IniValue('Logging','Level','0')] property LogLevel: Integer read FLogLevel write FLogLevel; [IniValue('Logging','Directory','')][IniValue('Logging','Directory','')] property LogDirectory: String read FLogDir write FLogDir; end;
![Page 21: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/21.jpg)
Unit testing - DUnitX
type TMyExampleTests = class public [Test] [TestCase('Case 1','1,2')] [TestCase('Case 2','3,4')] [TestCase('Case 3','5,6')] procedure TestOne(param1 : integer; param2 : integer);
[TestCase('Case 3','Blah,1')] procedure AnotherTestMethod(const a : string; const b : integer); [Test] procedure TestTwo;
//Disabled test [Test(false)] procedure DontCallMe;
![Page 22: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/22.jpg)
ORM mapping
type [TAttrDBTable('NONE')] TReportItem = class(TObject) protected [TAttrDBField(PP_VEHICLE_FIELD)] FVeiculoId: integer; [TAttrDBField(PP_DRIVER_FIELD)] FMotoristaId: integer; [TAttrDBField(PP_TRIP_FIELD)] FViagemId: integer; [TAttrDBField(PP_DATE)] FDataRelatorio: TDate; end;
![Page 23: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/23.jpg)
Data validation
type TMyConfig = class public procedure Validate; published [MustNotEmptyString] [FolderMustExists] property WorkingDir: string read GetWorkingDir write SetWorkingDir;
[MaxValue(7)] [MinValue(1)] property DefaultDay: Integer read GetDefaultDay write SetDefaultDay;
[MustNotEmptyString] [LimitToTheseChars('xyz')] property DefaultCity: string read GetDefaultCity write SetDefaultCity; end;
![Page 24: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/24.jpg)
Command-line parsing
TMyCmdLine = class(TCmdLine) [ParamName(‘importdir’), [ParamName(‘importdir’), ShortName(‘import’)]ShortName(‘import’)] ImportFolder: string; [ParamName(‘logsoapdetails’)][ParamName(‘logsoapdetails’)] LogDetails: boolean; [ParamName(‘user’), Default(‘guest’)][ParamName(‘user’), Default(‘guest’)] Username: string;end; cmdLine := TMyCmdLine.Create;if cmdLine.LogDetails then …
![Page 25: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/25.jpg)
ConclusionConclusion
![Page 26: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/26.jpg)
Pros & Cons
+ Big code reduction
+ Self-describing code
-Meaning sometimes unclear
-RTTI can get complicated
![Page 27: Using attributes and RTTI to automate programming tasks](https://reader036.vdocument.in/reader036/viewer/2022062301/56814299550346895daec9f3/html5/thumbnails/27.jpg)
Links
Overview•http://docwiki.embarcadero.com/RADStudio/XE5/en/Overview_of_Attributes•http://www.tindex.net/Language/Attributes.html•http://www.thedelphigeek.com/2012/10/multiple-attributes-in-one-line.html•http://delphi.fosdal.com/2010/11/another-generics-rtti-bug-attributes.html•http://stackoverflow.com/q/6119986
GpAutoCreate•http://www.thedelphigeek.com/2012/10/automagically-creating-object-fields.html
Serialization•http://robstechcorner.blogspot.com/2009/10/xml-serialization-control-via.html•http://robstechcorner.blogspot.de/2009/10/ini-persistence-rtti-way.html
DUnitX•https://github.com/VSoftTechnologies/DUnitX•http://www.finalbuilder.com/Resources/Blogs/PostId/697/introducing-dunitx.aspx
ORM mapping•http://stackoverflow.com/a/14342203
Validation•http://forum.codecall.net/topic/76628-using-attributes-for-validations/