Often when you add an indexer / array property you need to insert additional members that implement the indexer.
For example a field to store the values, make sure there’s a constructor and add some initialization code.
The ModelMaker Code Explorer Add Indexer Wizard is used to centralize this process. The wizard is highly customizable using Indexer implementation templates.
Pascal Example: adding an Indexer / Array property
Assume you have a class TStore that stores TThings.
To expose the Things we define a read-only indexer property Things[Index] like this:
1 2 3 4 5 6 7 |
type TStore = class(TObject) private function GetThings(Index: Integer): TThing; public property Things[Index: Integer]: TThing read GetThings; default; end; |
Apart from the property declaration there are usually other members required to fully implement this indexer property.
For example: you’ll need a field of type TList or TObjectList to actually store the things. This field must be initialized in the constructor and Freed in the destructor. You additionally might want to expose a Count property to allow iteration.
The TStore class interface would then look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
type TStore = class(TObject) private FThings: TList; // stores TThings function GetCount: Integer; // return FThings.Count function GetThings(Index: Integer): TThing; // return FThings[Index] public constructor Create; // create FThings destructor Destroy; override; // destroy FThings property Count: Integer read GetCount; // Number of Things // the actual indexer property property Things[Index: Integer]: TThing read GetThings; default; end; |
The above scenario is very common and ModelMaker Code Explorer comes with a highly specialized and flexible “Add Indexer” wizard that automates (most of) the entire process.
Just click OK in this dialog and the above mentioned class interface is inserted including the corresponding implementation code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
constructor TStore.Create; begin inherited Create; FThings := TList.Create; end; destructor TStore.Destroy; begin FreeAndNil(FThings); inherited Destroy; end; function TStore.GetCount: Integer; begin Result := FThings.Count; end; function TStore.GetThings(Index: Integer): TThing; begin Result := TThing(FThings[Index]); end; |
Customizing the wizard
The indexer implementation templates are customizable and new ones can be added.
Referring to the above example: More advanced implementations could include methods FindThing(..), AddThing(..), DeleteThing(..) etc.
Indexer Templates are stored in directory [install-root]\Shared\Indexers. Typically “C:\Program Files\ModelMakerTools\Shared\Indexers”.
The template that defines the implementation for the above mentioned TStore / Things example looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//MM#:type=indexer-implementation //MM#:description=Simple TList implementation with Count //MM#:getter=begin\N Result := <!PropertyType!>(F<!PropertyName!>[<!PropIndexCallParams!>]);\Nend; //MM#:ctor=F<!PropertyName!> := TList.Create; //MM#:dtor=FreeAndNil(F<!PropertyName!>); unit IndexerTemplate1;interface type TCodeTemplate = class private F<!PropertyName!>: TList; function GetCount: Integer; public property Count: Integer read GetCount; end; implementation function TCodeTemplate.GetCount: Integer; begin Result := F<!PropertyName!>.Count; end; end. |