Delphi Invalid Class Typecast - delphi

I'm trying to build an Delphi class for Invoice, and invoice Lines Array,to export it to JSON , I went to JSONTODelphi.com and I extract the class and add it to my project, but i each time i want to assign a value to (Partner_Shipping_Id) in the class I got "Invalid Class typecast" here my code :
unit Quotation;
interface
uses Pkg.Json.DTO, System.Generics.Collections, REST.Json.Types;
{$M+}
type
TQuotationLines = class
private
FDiscount: Integer;
FPrice: Double;
FProduct_Id: Integer;
FQuantity: Integer;
FTax_Id: Integer;
published
property Discount: Integer read FDiscount write FDiscount;
property Price: Double read FPrice write FPrice;
property Product_Id: Integer read FProduct_Id write FProduct_Id;
property Quantity: Integer read FQuantity write FQuantity;
property Tax_Id: Integer read FTax_Id write FTax_Id;
end;
TQuotationInvoice = class(TJsonDTO)
private
FCash_Van_Id: Integer;
FData: TDate;
FPartner_Id: Integer;
FPartner_Invoice_Id: Integer;
FPartner_Shipping_Id: Integer;
FPricelist_Id: Integer;
[GenericListReflect]
FLines: TObjectList<TQuotationLines>;
[JSONName('lines')]
FLinesArray: TArray<TQuotationLines>;
function GetLines: TObjectList<TQuotationLines>;
published
property Cash_Van_Id: Integer read FCash_Van_Id write FCash_Van_Id;
property Data: TDate read FData write FData;
property Partner_Id: Integer read FPartner_Id write FPartner_Id;
property Partner_Invoice_Id:Integer read FPartner_Invoice_Id write FPartner_Invoice_Id;
property Partner_Shipping_Id:Integer read FPartner_Shipping_Id write FPartner_Shipping_Id;
property Pricelist_Id: Integer read FPricelist_Id write FPricelist_Id;
property Lines: TObjectList<TQuotationLines> read GetLines;
destructor Destroy; override;
end;
implementation
{ TQuotationInvoice }
destructor TQuotationInvoice.Destroy;
begin
GetLines.Free;
inherited;
end;
function TQuotationInvoice.GetLines: TObjectList<TQuotationLines>;
begin
if not Assigned(FLines) then
begin
FLines := TObjectList<TQuotationLines>.Create;
FLines.AddRange(FLinesArray);
end;
Result := FLines;
end;
end.
in my from i add in the uses the class name and "Q" is TQuotationInvoice created in Public session , I create this procedure (Below), if i give the (Q.Partner_Shipping_Id) const number like (Q.Partner_Shipping_Id:=1) it work fine but when i pass a variable like (Q.Partner_Shipping_Id:=AshippingID) show error "Invalid Class Typecast"
procedure AddQuotation(ApartnerID,AshippingID,APriceListID:Integer);
begin
Q.Cash_Van_Id:=POSID.ToInteger;
Q.Data:=Date;
Q.Partner_Id:=ApartnerID;
Q.Partner_Shipping_Id:=AshippingID; // <---------------------- Here the Error
Q.Pricelist_Id:=APriceListID;
end;
any Ideas ?

Related

JSONMarshalled not working in Delphi XE10 (again)

I have a class I want to pass to a datasnap server, but the class contains this field Picture which should be a TPicture but for now I use an integer to avoid getting the marshall error "tkPointer currently not supported" :(
I have tried omitting a field/property "Picture" from getting marshalled by adding [JSONMarshalled(False)] but with no luck.
I have added the units as suggested in the thread here
JSONMarshalled not working in Delphi
unit TestObjU;
interface
uses
Classes, System.Generics.Collections, System.SyncObjs, System.SysUtils,
JSON, DBXJsonReflect, REST.JSON,
Data.FireDACJSONReflect, FireDAC.Comp.Client, vcl.ExtCtrls,
pngimage, graphics, variants,
GlobalFunctionsU, GlobalTypesU;
{$M+}
{$RTTI EXPLICIT FIELDS([vcPrivate])}
type
EPerson = class(Exception);
EPersonsList = class(Exception);
TGender = (Female, Male);
TPerson = class(TObject)
private
FFirstName: string;
FLastName: string;
FId: Integer;
FGender: TGender;
FModified : Boolean;
[JSONMarshalled(False)]
FPicture: Integer;
// [JSONMarshalled(False)] FPicture : TPicture;
function GetName: string;
procedure SetFirstName(const Value: string);
procedure SetLastName(const Value: string);
function GetId: Integer;
procedure SetGender(const Value: TGender);
procedure SetModified(const Value: Boolean);
public
property Id : Integer read GetId;
property Name : string read GetName;
property FirstName : string read FFirstName write SetFirstName;
property LastName : string read FLastName write SetLastName;
property Gender : TGender read FGender write SetGender;
property Modified : Boolean read FModified write SetModified;
// property Picture : TPicture read FPicture write FPicture;
[JSONMarshalled(False)]
property Picture : Integer read FPicture write FPicture;
function Update : Boolean;
function Delete : Boolean;
constructor Create(AId : Integer; AFirstName, ALastName : string; AGender : TGender); overload;
constructor Create(AFirstName, ALastName : string; AGender : TGender); overload;
destructor destroy; override;
function ToJsonString: string;
end;
But clearly it has no effect on the marshalling, Picture is still there - what am I missing?
function TPerson.ToJsonString: string;
begin
result := TJson.ObjectToJsonString(self);
end;
08-03-2016 10:26:24 [NORMAL] AddPerson serialized {"firstName":"Donald","lastName":"Duck","id":24,"gender":"Female","modified":false,"picture":92415648}
You are using TJson.ObjectToJsonString from REST.Json unit and that one needs different attribute to skip fields named JSONMarshalledAttribute
You should change your code to [JSONMarshalledAttribute(False)]
Delphi has a bit of mix up between older Data.DBXJsonReflect and newer REST.Json units and you should not mix them together in same code. Pick only one of them.
REST.Json.TJson.ObjectToJsonString
REST.Json.Types.JSONMarshalledAttribute
Data.DBXJSONReflect.JSONMarshalled
Yes - I found the solution, when using DBX (and not REST) you'll need add this unit "Data.DBXJSON" rather than the "REST.JSON" and change the two "from/to" methods for un/marshaling the object something like this.
NOTE. ToJSONString leaks for some reason, I'll have to investigate that more.
function TPerson.ToJsonString: string;
var
JSONMarshal: TJSONMarshal;
begin
result := '';
JSONMarshal := TJSONMarshal.Create(TJSONConverter.Create);
try
Result := JSONMarshal.Marshal(self).ToString;
finally
JSONMarshal.Free;
end;
end;
class function TPerson.FromJsonString(AJSONString: string): TPerson;
var
JSONUnMarshal: TJSONUnMarshal;
begin
JSONUnMarshal := TJSONUnMarshal.Create;
try
Result := JSONUnMarshal.Unmarshal(TJSONObject.ParseJSONValue(AJSONString)) as TPerson;
finally
JSONUnMarshal.Free;
end;
end;

Spring4d: How to "force" the container to believe a class implements an interface

I am using RemObjects DataAbstract along with Spring4d. RemObjects generates a SchemaServer_Intf.pas file that contains interfaces for every kind of table that exists in it's schema. It allows for "Strongly typed" datasets, allowing one to access a field using
(aDataSet as IMyDataSet).MyField := aValue
Here is a snapshot of one of the interfaces generated by DataAbstract
IEntiteType = interface(IDAStronglyTypedDataTable)
['{96B82FF7-D087-403C-821A-0323034B4B99}']
{ Property getters and setters }
function GetEntiteIdValue: String;
procedure SetEntiteIdValue(const aValue: String);
function GetEntiteIdIsNull: Boolean;
procedure SetEntiteIdIsNull(const aValue: Boolean);
function GetNameValue: WideString;
procedure SetNameValue(const aValue: WideString);
function GetNameIsNull: Boolean;
procedure SetNameIsNull(const aValue: Boolean);
function GetIsSystemValue: SmallInt;
procedure SetIsSystemValue(const aValue: SmallInt);
function GetIsSystemIsNull: Boolean;
procedure SetIsSystemIsNull(const aValue: Boolean);
{ Properties }
property EntiteId: String read GetEntiteIdValue write SetEntiteIdValue;
property EntiteIdIsNull: Boolean read GetEntiteIdIsNull write SetEntiteIdIsNull;
property Name: WideString read GetNameValue write SetNameValue;
property NameIsNull: Boolean read GetNameIsNull write SetNameIsNull;
property IsSystem: SmallInt read GetIsSystemValue write SetIsSystemValue;
property IsSystemIsNull: Boolean read GetIsSystemIsNull write SetIsSystemIsNull;
end;
Though, there is one problem. If you cast a dataTable like so:
aDataTable := IEntiteType(TDAMemDataTable.Create(nil));
You'll have an "Interface not supported error"
But, as soon as you do:
aDataTable.LogicalName := 'EntiteType';
aDataTable.BusinessRulesId := MyBusinessRuleID;
You can safely write
aDataTable := IEntiteType(TDAMemDataTable.Create(nil));
And you don't get any error.
So, with Spring4d, I thought of writing this in my registration unit:
aContainer.RegisterType<TDAMemDataTable>.Implements<IEntiteType>.DelegateTo(
function : TDAMemDataTable
var aDataTable : TDAMemDataTable;
begin
Result:= TDAMemDataTable.Create(nil);
Result.LogicalName := 'EntiteType';
Result.BusinessRulesId := MyBusinessRuleId;
end
)
But then, Spring4d throws (with reason) error :
Exception 'first chance' à $762D5B68. Classe d'exception ERegistrationException avec un message 'Component type "uDAMemDataTable.TDAMemDataTable" incompatible with service type "SchemaClient_Intf.IEntiteType".'. Processus EntiteREM2.exe (3088)
Is there a way to override this check?
Ok I've found a way to do that. Super simple actually :
aContainer.RegisterType<IAddress>.DelegateTo(
function : IAddress
var aTable : TDAMemDataTable;
begin
aTable := TDAMemDataTable.Create(nil);
aTable.LogicalName := nme_Address;
aTable.BusinessRulesID := RID_Address;
Result := aTable as IAddress;
end
);
Also, for people interested in registering many tables in an elegant fashion :
aContainer.RegisterType<IAddress>.DelegateTo(TableConfigurator.GetTableDelegate<IAddress>(nme_Address, RID_Address));
// Registering other tables here...
Just create some "Helper" class with this method :
class function TableConfigurator.GetTableDelegate<T>(aLogicalName, aBusinessRulesId: string): TActivatorDelegate<T>;
begin
Result := (function: T
var
aTable: TDAMemDataTable;
begin
aTable := TDAMemDataTable.Create(nil);
aTable.LogicalName := aLogicalName;
aTable.BusinessRulesID := aBusinessRulesId;
Result := T(TValue.From(aTable).AsInterface);
end);
end;

How can I avoid EInvalidPointer error when using TObjectDictionary in Delphi?

The program receives product information datas through window message.
Incoming datas processed in TProductInstance.PutProductData procedure.
Product information contains date, name, price.
I want to store datas as TObjectDictionary. The key is same date of the product and value is product information data list as TObjectList.
Also I want to maintain datas only in latest 7 days.
By the way, when I remove the item from TObjectDictionary for maintaining, error occurs like below.
First chance exception at $75214598.Exception class EInvalidPointer with message 'Invalid pointer operation'. Process product.exe (3848).
This is caused by FProductDictionary.Remove(StringKey);.
How can I avoid EInvalidPointer error with maintain latest 7 days datas?
type
TProductItem = class(TObject)
private
FDate: String;
FName: String;
FPrice: Integer;
procedure SetDate(const value: String);
procedure SetName(const value: String);
procedure SetPrice(const value: Integer);
public
property Date: String read FDate write SetDate;
property Name: String read FName write SetName;
property Price: Integer read FPrice write SetPrice;
constructor Create(const date, name: String; const price: Integer);
end;
TProductItemList = class(TObjectList<TProductItem>);
type
TProductInstance = class(TObject)
private
public
FLatestDate: String;
FProductList: TProductItemList;
FProductDictionary: TObjectDictionary<String, TProductItemList>;
constructor Create;
destructor Destroy; override;
procedure PutProductData(var Data: LP_Data);
end;
implementation
constructor TProductInstance.Create;
begin
FLatestDate := '';
FProductList := TProductItemList.Create;
FProductDictionary := TObjectDictionary<String, TProductItemList>.Create([doOwnsValues]);
end;
procedure TProductInstance.PutProductData(var Data: LP_Data);
var
StringKey: String;
begin
if (Trim(LP_Data^.date) <> FLatestDate) then
begin
FProductDictionary.AddOrSetValue(Trim(LP_Data^.date), FProductList);
for StringKey in FProductDictionary.Keys do
begin
if (GetDateToInt(Trim(LP_Data^.date)) - GetDateToInt(FLatestDate) > 7) then
FProductDictionary.Remove(StringKey);
end;
FProductList.Free;
end;
FProductList.Add(TProductItem.Create(Trim(LP_Data^.date), Trim(LP_Data^.name), Trim(LP_Data^.price)));
FLatestDate := Trim(LP_Data^.date);
end;
UPDATED
type
TProductItem = class(TObject)
private
FDate: String;
FName: String;
FPrice: Integer;
procedure SetDate(const value: String);
procedure SetName(const value: String);
procedure SetPrice(const value: Integer);
public
property Date: String read FDate write SetDate;
property Name: String read FName write SetName;
property Price: Integer read FPrice write SetPrice;
constructor Create(const date, name: String; const price: Integer);
end;
type
TProductInstance = class(TObject)
private
public
FLatestDate: String;
FProductList: TObjectList<TProductItem>;
FProductDictionary: TObjectDictionary<String, TObjectList<TProductItem>>;
constructor Create;
destructor Destroy; override;
procedure PutProductData(var Data: LP_Data);
end;
implementation
constructor TProductInstance.Create;
var
LProductItem: TProductItem;
LProductItemList: TObjectList<TProductItem>;
LStringList: TStringList;
begin
FLatestDate := '';
FProductList := TObjectList<TProductItem>.Create;
FProductDictionary := TObjectDictionary<String, TObjectList<TProductItem>>.Create([doOwnsValues]);
end;
procedure TProductInstance.PutProductData(var Data: LP_Data);
var
StringKey: String;
begin
FProductList.Add(TProductItem.Create(Trim(LP_Data^.date), Trim(LP_Data^.name), Trim(LP_Data^.price)));
if (Trim(LP_Data^.date) <> FLatestDate) then
begin
LProductItemList := TObjectList<ProductItem>.Create;
for LProductItem in FProductList do
begin
LProductItemList.Add(LProductItem);
end;
FProductDictionary.AddOrSetValue(Trim(LP_Data^.date), LProductItemList);
FProductList.Clear;
LStringList := TStringList.Create;
for StringKey in FProductDictionary.Keys do
begin
if (GetDateToInt(Trim(LP_Data^.date)) - GetDateToInt(FLatestDate) > 7) then
begin
LStringList.Add(StringKey);
end;
end;
for StringKey in LStringList do
begin
FProductDictionary.Remove(StringKey);
end;
FreeAndNil(LStringList);
end;
end;
Updated code occurs EInvalidPointer error on FProductDictionary.Remove(StringKey); What did I wrong?
The code you present is incomplete. You did not show the destructor for TProductInstance. For a question such as this you should always supply a simple MCVE. This is quite easy to achieve in a single console .dpr file.
Looking at what we can see, it is clear that the lifetime management in the code is broken. Let us critique this method.
procedure TProductInstance.PutProductData(var Data: LP_Data);
var
StringKey: String;
begin
if (Trim(LP_Data^.date) <> FLatestDate) then
begin
FProductDictionary.AddOrSetValue(Trim(LP_Data^.date), FProductList);
for StringKey in FProductDictionary.Keys do
begin
if (GetDateToInt(Trim(LP_Data^.date)) - GetDateToInt(FLatestDate) > 7) then
FProductDictionary.Remove(StringKey);
end;
FProductList.Free;
end;
FProductList.Add(TProductItem.Create(Trim(LP_Data^.date), Trim(LP_Data^.name),
Trim(LP_Data^.price)));
FLatestDate := Trim(LP_Data^.date);
end;
Because FProductDictionary owns its values, when you do
FProductDictionary.AddOrSetValue(Trim(LP_Data^.date), FProductList);
then FProductDictionary becomes the owner of FProductList. That means that you should not destroy FProductList ever. However, you do exactly that:
FProductList.Free;
So you are going to be destroying FProductList multiple times which is a clear error.
What to do next? You need to deal with the lifetime issues. I cannot know from the code presented here what you are trying to achieve, and how the lifetime should be managed. You will need to work out who is responsible for owning what, and make sure that you stick to a clear lifetime management policy.
On the face of it, my best guess would be that you need to remove the FProductList field. When you need to add a new item to FProductDictionary, instantiate a new instance of TProductItemList, populate it, and add it to the dictionary. At that point the dictionary takes control of the lifetime of the TProductItemList.
As one final comment, I would suggest that the type TProductItemList is pointless. I would remove it. Use TObjectList<TProductItem> to make the code clearer to the reader. The reader can look at TObjectList<TProductItem> and know immediately what it is, since TObjectList<T> is such a ubiquitous type.

Delphi - Interfaces inside interfaces

I'm an newbee concerning interfaces. I googled a lot but i can't figure out what to do in the following situation.
i created serveral interfaces, which use each other:
IPart = interface(IInterface)
Function getName: string;
procedure setName(aValue: string)
property Name: string read getName write setname;
end;
IOfferLine= interface(iInterface)
Function getPart: IPart;
function getAmount: double;
procedure setPart(aPart: IPart);
procedure setAmount(value: double);
property Amount: double read getAmount write setAmount;
property Part: IPart read GetPart write setPart;
end;
IOffer= interface(iInterface)
function getOffLines: tList<IOfferline>;
procedure setOffLines(aList: tList<IOfferline>);
property OffLines: tList<IOfferlines> read getOffLines write setOfflines;
end;
Now i want to implement those interface.
TPart = class(TInterfacedObject, IPart)
private
_Name: string;
function getName: string;
procedure setName(aValue: string);
public
property Name: string read getName write setName;
end;
TOfferLine = class(TInterfacedObject, IOfferLine)
private
_amount: double;
_part: TPart;
function getAmount: double;
function getPart: tPart;
procedure setAmount(aValue: double);
procedure setPart(aPart: TPart);
public
property Amount: double read getAmount write setAmount;
property Part: TPart read GetPart write SetPart;
end;
TOffer = class(TInterfacedObject, IOffer)
private
_OfferLines: tList<TOfferline>;
function getOffLines: tList<tOfferline>;
procedure setOffLines(aList: tList<tOfferline>);
public
property offLines: tList<TOfferline> read getOffLines write setOffLines;
end;
I have added the implementation.
function TOfferLine.getPart: tPart;
begin
result := _part;
end;
But i still get 'Missing implementation of interface method IOfferline.GetPart;'
And i Can't figure out why.
I dont know what you are trying to to but if you didn't write you code so messy it would be easier to read. But thank God we have a Source formatter.
There are seval problems in you code:
First You have your property declared as property OffLines: TList<IOfferline**s**> while your interface is named IOfferline
Then TOfferline you have a method procedure setPart(aPart: TPart); that should be procedure setPart(aPart: IPart); because thats how you declared your interface. And all the other places where you Use TPart should be IPart.
And the same goes for TOffer
Here is a cleaned up version of your code :
unit Unit20;
interface
uses
Generics.Collections;
type
IPart = interface(IInterface)
function getName: string;
procedure setName(aValue: string);
property Name: string read getName write setName;
end;
IOfferLine = interface(IInterface)
function getPart: IPart;
function getAmount: double;
procedure setPart(aPart: IPart);
procedure setAmount(value: double);
property Amount: double read getAmount write setAmount;
property Part: IPart read getPart write setPart;
end;
IOffer = interface(IInterface)
function getOffLines: TList<IOfferLine>;
procedure setOffLines(aList: TList<IOfferLine>);
property OffLines: TList < IOfferLine > read getOffLines write setOffLines;
end;
TPart = class(TInterfacedObject, IPart)
private
_Name: string;
function getName: string;
procedure setName(aValue: string);
public
property Name: string read getName write setName;
end;
TOfferline = class(TInterfacedObject, IOfferLine)
private
_amount: double;
_part: TPart;
function getAmount: double;
function getPart: IPart;
procedure setAmount(aValue: double);
procedure setPart(aPart: IPart);
public
property Amount: double read getAmount write setAmount;
property Part: IPart read getPart write setPart;
end;
TOffer = class(TInterfacedObject, IOffer)
private
_OfferLines: TList<TOfferline>;
function getOffLines: TList<IOfferLine>;
procedure setOffLines(aList: TList<IOfferLine>);
public
property OffLines: TList < IOfferLine > read getOffLines write setOffLines;
end;
implementation
{ TOfferline }
function TOfferline.getAmount: double;
begin
end;
function TOfferline.getPart: IPart;
begin
end;
procedure TOfferline.setAmount(aValue: double);
begin
end;
procedure TOfferline.setPart(aPart: IPart);
begin
end;
{ TOffer }
function TOffer.getOffLines: TList<IOfferLine>;
begin
end;
procedure TOffer.setOffLines(aList: TList<IOfferLine>);
begin
end;
{ TPart }
function TPart.getName: string;
begin
end;
procedure TPart.setName(aValue: string);
begin
end;
end.
The reason the compiler is saying that the implementation is missing is simply because the implementation is missing.
Your interface for IOfferLine declares this getPart method:
IOfferLine= interface(iInterface)
..
function getPart: IPart;
..
end;
But your implementing class does not provide this method. The getPart method in your class is implemented to return an object reference, not an interface reference:
TOfferLine = class(TInterfacedObject, IOfferLine)
private
..
function getPart: tPart;
..
end;
You need to ensure that your implementing class actually provides the members required by the interfaces that it implements, exactly and precisely:
TOfferLine = class(TInterfacedObject, IOfferLine)
private
..
function getPart: IPart;
..
end;
function TOfferline.getPart: IPart;
begin
result := _part as IPart;
end;
However, since the reference to the Part maintained by the OfferLine object (in the _part variable) is an object reference, then references to that object obtained using interfaces (via the getPart: IPart method) could result in that Part object being destroyed since the object reference in OfferLine is not counted (literally).
You can of course avoid this by making the Part reference held by OfferLine an interface reference itself, but whether this is valid is difficult to say with out a complete picture of your entire object model. If the lifetimes of your objects are ensured by some other mechanism not apparent from the question then it may not be an issue, but if it is not something that has been specifically considered thus far then it probably does need addressing.
Although it is possible to do safely, as a general rule mixing object references and interface references to the same objects is a recipe for problems.

Why can some arrays be published but not others?

type
TStaticArray = array[1..10] of integer;
TDynamicArray = array of integer;
TMyClass = class(TObject)
private
FStaticArray: TStaticArray;
FDynamicArray: TDynamicArray;
published
property staticArray: TStaticArray read FStaticArray write FStaticArray; //compiler chokes on this
property dynamicArray: TDynamicArray read FDynamicArray write FDynamicArray; //compiler accepts this one just fine
end;
What's going on here? A static array gives the error, "published property 'staticArray' cannot be of type ARRAY" but dynamic arrays are just fine? I'm confused. Anyone know the reasoning behind this, and how I can work around it? (And no, I don't want to redeclare all my static arrays as dynamic. They're the size they are for a reason.)
Published declaration tells the compiler to store information in the virtual method table. Only certain kinds of information can be stored.
The type of a published property cannot be a pointer, record, or array. If it is a set type, it must be small enough to be stored in an integer.
(O'REILLY, DELPHİ IN A NUTSHELL)
You have to have getters and setters. Under D2009 (didn't check other versions), the parameters to the getters/setters can't, for some reason, be const. ?
This works fine under D2009:
type
TMyArray = array[0..20] of string;
type
TMyClass=class(TObject)
private
FMyArray: TMyArray;
function GetItem(Index: Integer): String;
procedure SetItem(Index: Integer; Value: string);
public
property Items[Index: Integer]: string read GetItem write SetItem;
end;
implementation
function TMyClass.GetItem(Index: Integer): string;
begin
Result := '';
if (Index > -1) and (Index < Length(FMyArray)) then
Result := FMyArray[Index];
end;
procedure TMyClass.SetItem(Index: Integer; Value: string);
begin
if (Index > -1) and (Index < Length(FMyArray)) then
FMyArray[Index] := Value;
end;
NOTE: I would not typically just ignore Index values out of range, obviously. This was a quick example of how to make static array properties in a class definition; IOW, it's a compilable example only.
The reason why you can publish a dynamic array property, is that dynamic arrays is implemented as references, or 'implicitly pointer'. They work more like strings, really.
The reason why you can't publish a static array, I don't know. It's just the way it's made, I guess..
For more details on how dynamic arrays work, take a look at DrBobs site
TMyClass = class(TObject)
private
FStaticArray: TStaticArray;
FIdx: Integer;
function GetFoo(Index: Integer): Integer;
procedure SetFoo(Index: Integer; Value: Integer);
public
property Foo[Index: Integer] : Integer read GetFoo write SetFoo;
published
property Idx: Integer read fidx write fidx;
property AFoo: Integer read GetAFoo writte SetAFoo;
end;
implementation
function TMyClass.GetAFoo: Integer;
begin
result := FStaticArray[FIdx];
end;
procedure TMyClass.SetAFoo(Value: Integer);
begin
FStaticArray[FIdx] := Value;
end;
Array properties cannot be published.
So the following code does not work. The work around probably is to make it public.
TMyClass = class(TObject)
private
FStaticArray: TStaticArray;
function GetFoo(Index: Integer): Integer;
procedure SetFoo(Index: Integer; Value: Integer);
public
property Foo[Index: Integer] : Integer read GetFoo write SetFoo;
end;

Resources