Hi Everyone.

Hi Everyone.
There is no way to instantiate generics at runtime?

Eg:
TMyGen = class
Value: T;
Default: T;
Min: T;
Max: T;
end;

TMyClass = class
// usually....
FMyByte: TMyGen;
FMyWord: TMyGen;
FMyDWord: TMyGen;

// but now I'd like to instatiate the variable FMyValue
// as Byte, Word or DWord at runtime
FMyValue: TMyGen; // <-- obviously... compiler error
end;

how to do that?
It's possible?
Thanks.

Comments

  1. Lars Fosdal Thanks for the sample code.
    I'm trying to implement it but I don't understand how to write a value because the WritePLC function don't accept any argument and the Value property isn't exposed outside.

    Eg: my program should write a value on a "Entity" X (Word entity) or write on a "Entity Y" (DWord entity).

    ReplyDelete
  2. Davide Visconti​ - It is difficult to do a good recommendation of "how to", when I don't know exactly how you are using the entity references.

    What is the source of the value? How do you know that the particular value should be of this or that type?

    Example 1:

    If it is from an input (grid, edit, etc), you could introduce a

    function TEntity.SetValueFromString(const aStr:String; out ErrorInfo:String):boolean;

    where you do the conversion and validate the input.
    If the input was valid, you call WritePLC - either inside SetValueFromString, or conditionally outside

    if Entity.SetValueFromString(Edit.Text, ErrInfo)
    then Entity.WritePLC
    else ShowMessage(Format('"%s" is not valid: %s' , [Edit.Text, ErrInfo]));

    (Note that I do NOT recommend using ShowMessage :P)

    That way, you don't really need to know the type in the code that handles the input.

    Example 2:

    If it is a direct reference, f.x. where you know the identities and the value they should have, you could use something like

    function EntityList.FindByName(const aNameStr):T;

    and "bind" the reference to local variables of the desired type.

    var
    b: TEntityList.TByte;
    w: TEntityList.TWord;
    begin
    b := OurList.FindByName('OurBValue');
    w := OurList.FindByName('OurWValue');

    w.Value := 256; // Since Value is a word, this is ok
    b.Value := 256; // Since value is byte - you get compile time error

    Why not cast directly? This way you can handle the type checks, casts, and error reporting in one method.

    ReplyDelete
  3. Lars Fosdal sounds good.
    I'll try the second one.
    Thank you all for any tips

    ReplyDelete

Post a Comment