Jump to content

Search the Community

Showing results for tags 'rtti'.



More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Delphi Questions and Answers
    • Algorithms, Data Structures and Class Design
    • VCL
    • FMX
    • RTL and Delphi Object Pascal
    • Databases
    • Network, Cloud and Web
    • Windows API
    • Cross-platform
    • Delphi IDE and APIs
    • General Help
    • Delphi Third-Party
  • C++Builder Questions and Answers
    • General Help
  • General Discussions
    • Embarcadero Lounge
    • Tips / Blogs / Tutorials / Videos
    • Job Opportunities / Coder for Hire
    • I made this
  • Software Development
    • Project Planning and -Management
    • Software Testing and Quality Assurance
  • Community
    • Community Management

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Delphi-Version

Found 14 results

  1. Yellow, I have about following situation. FInstance is any TObject descendant and enum property can be any public or published Enum property, code must not link to hard coded enum type. procedure TMyThingy.SetEnumPropertyValue(const AValue: string); var LContext: TRttiContext; LRtttiType: TRttiType; LProperty: TRttiProperty; begin LContext := TRttiContext.Create; LRtttiType := LContext.GetType(FInstance.ClassType); LProperty := LRtttiType.GetProperty(FPropertyName); // Here I should convert lets say TMyEnum = (A, B, C) from string into the property value // if I call SetEnumPropertyValue('B') property FPropertyName from FInstance-object should be set. end; This should be quite simple, couple lines of code most likely. Could not find sample code that was good enough fit to get this to work, there usually was too much knowns, like enum type TMyEnum, This should be totally dynamic. Circled around this quite long time, just could not find the way to connect all the dots... -Tee-
  2. Hi mates, I have something on my mind but I couldn't implement it correctly, imagine a generic interface, some classes inherited from that interface, and one method in each class with the same name, now I'm trying to use this interface type every where for different approaches but it doesn't compile correctly. Please have a look at the code if you get a chance and share your thoughts with me, I do appreciate you in advance. The question is how can I implement such an idea properly and safely? I have attached a sample project to save you time too. unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Rtti; type IMyInterface<T> = interface function DoSomething: T; end; TMyClass<T> = class(TInterfacedObject, IMyInterface<T>) function DoSomething: T; end; TForm1 = class(TForm) procedure FormCreate(Sender: TObject); private { Private declarations } function UseInterface<T>(obj: IMyInterface<T>): T; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} { TMyClass<T> } function TMyClass<T>.DoSomething: T; var ctx: TRttiContext; typ: TRttiType; begin ctx := TRttiContext.Create; typ := ctx.GetType(TypeInfo(T)); if typ.TypeKind = tkInteger then Result := 20 // E2010 Incompatible types: 'T' and 'Integer' else if typ.TypeKind = tkString then Result := T('Hello') // E2089 Invalid typecast else if typ.AsInstance.MetaclassType.InheritsFrom(TStringList) then Result := (typ.AsInstance.MetaclassType.InitInstance(typ) as TStringList) //E2010 Incompatible types: 'T' and 'TStringList' else Result := Default(T); ctx.Free; end; { TForm1 } function TForm1.UseInterface<T>(obj: IMyInterface<T>): T; begin Result := obj.DoSomething; end; procedure TForm1.FormCreate(Sender: TObject); var obj1: IMyInterface<Integer>; obj2: IMyInterface<String>; obj3: IMyInterface<TStringList>; begin try obj1 := TMyClass<Integer>.Create; obj2 := TMyClass<String>.Create; obj3 := TMyClass<TStringList>.Create; ShowMessage(UseInterface<Integer>(obj1).ToString); ShowMessage(UseInterface<String>(obj2)); ShowMessage(UseInterface<TStringList>(obj3).Text); except on E: Exception do Writeln('Exception: ', E.ClassName, ': ', E.Message); end; end; end. Generic Interface.zip
  3. As per title. For instance: A) Second method hides the first ClassA = class procedure Test(I: Integer); end; ClassB = class(classA) procedure Test(S: string); end; B) Second method overloads the first ClassA = class procedure Test(I: Integer); overload; end; ClassB = class(classA) procedure Test(S: string); overload; end; How can you tell the difference with Rtti. GetMethods would show both methods in a similar way.
  4. TTest = class A: string; class var B: string; end; Is it possible to tell that B is a class field using Rtti? Ditto for properties. And if you get a chance have a look at my other Rtti question.
  5. In a 5 year old answer to a stackoverflow question @David Heffernan responded that "class properties cannot be accessed via RTTI". Is this still the case with recent versions of Delphi?
  6. Is it possible to use attributes in these scenarios: // First scenario [MyAttr] TMyGuid = TGuid; // Second scenario [MyAttr] TMyDT = TDateTime; I found this article that says it's not possible to use attributes on aliases of simple ordinal types, only on actual sub-types by using the type keyword. I'm asking this because I believe declaring my TMyGuid type as a sub-type for TGuid rather than an alias will break a lot of my code. Is there really no way to use attributes on aliases like this? Update: I realized that changing my declaration to TMyGuid = type TGuid; will only cause the loss of TGuidHelper. Unfortunately, class helper inheritance is still not available so I will have to rewrite it for my sub-type.
  7. System.Rtti contains a lesser known, but powerful class TMethodImplementation, which is basically hidden and used in TVirtualMethodInterceptor. Outside this use, it cannot be created directly and it can only be accessed by TRttiMethod.CreateImplementation. I recently discovered that Spring4d extends its use through a helper for TRttiInvokableType, so it can be used with standalone procedures and functions as well as with events. Here is a small console app showing how it can be used: program MethodImplementationTest; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.TypInfo, System.Rtti, Spring; type TSimpleProc = function(I: Integer): Integer; procedure ImplCallback(UserData: Pointer; const Args: TArray<TValue>; out Result: TValue); begin WriteLn('From Implementation'); Result := Args[0].AsInteger * 2; end; var Proc: TSimpleProc; begin ReportMemoryLeaksOnShutdown := True; try var RTTIContext := TRttiContext.Create; var RTTIType := RTTIContext.GetType(TypeInfo(TSimpleProc)); var ProcImplementation := (RTTIType as TRttiInvokableType).CreateImplementation(nil, ImplCallback); Proc := TSimpleProc(ProcImplementation.CodeAddress); WriteLn(Proc(2)); ProcImplementation.Free; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; ReadLn; end. Output: From Implementation 4 Simple and easy. Spring4D is full of gems. I wish the above functionality was part of the standard library. I can think of many uses: Python4Delphi contains a unit MethodCallback which uses complex assembly to convert methods into stubs that can be used with external C libraries. It could be rewritten using TMethodImplementation, without assembly code. Also in Python4Delphi, the implementation of Delphi events using python code could be very much simplified and generalized using TMethodImplementation. You can create Delphi functions, procedures and methods, event handlers on the fly that are implemented by python code. Similarly functionality can be provided with other scripting languages.
  8. Hi I have been using a generic record to convert combo-boxes to enumerated type. But Delphi spits the dummy if the type has any numbers specified. For example with this code the compiler throws up the error message "E2134 Type 'TDDArrangementId' has no type info. In the generic type TypeInfo(T) returns nil. type TDDArrangementId = (daOutstanding = 1, daWeeklyGap, daAmount, daGapAmount); ... procedure Test; var ti: PTypeInfo; begin ti := TypeInfo(TDDArrangementId); But removing the " = 1" makes it all build and run just fine. Can anyone confirm that Delphi's rtti system simply does not handle enumerated types if they are not zero-based? I'm using 10.4 --- Mark
  9. Hello everyone, I hope this message finds you all in good health! This year and really weird.... But anyway, let's get back to the point. I recently found a little nugget on the Internet developed by the brilliant @Uwe Raabe : it's a Dataset helper that automatically fills in the properties (or even fields) of an object. The source code can be found at this address : https://www.uweraabe.de/Blog/2017/02/09/dataset-enumerator-reloaded/ I have slightly adapted the source code to use TMS Aurelius attributes (using "Column" attribute instead of "DBField" one provided bu Uwe). The Dataset helper works perfectly well "simple" classes such TCustomer = class private [Column('CustNo')] FCustNo: Double; FCompany: string; FAddress1: string; public [DBField('Addr1')] property Address1: string read FAddress1 write FAddress1; property Company: string read FCompany write FCompany; end; But it gets more difficult as soon as my fields are declared this way: TCustomer = class private [Column('CustNo')] FCustNo: Nullable<Double>;; FCompany: Nullable<String>;; FAddress1: string; FEntity: TObject; public [DBField('Addr1')] property Address1: string read FAddress1 write FAddress1; property Company: string read FCompany write FCompany; property Entity: TObject read FEntity write FEntity; end; At runtime application is throwing "Invalid Type Typecast" exception on every TRTTI.GetValue or TRRTI.SetValue procedure TDataSetHelper.TDataSetRecord<T>.TFieldMapping.LoadFromField(var Target: T); begin FRTTIField.SetValue(GetPointer(Target), TValue.FromVariant(FField.Value)); end; procedure TDataSetHelper.TDataSetRecord<T>.TFieldMapping.StoreToField(var Source: T); begin FField.Value := FRTTIField.GetValue(GetPointer(Source)).AsVariant; end; procedure TDataSetHelper.TDataSetRecord<T>.TPropMapping.StoreToField(var Source: T); begin FField.Value := FRTTIProp.GetValue(GetPointer(Source)).AsVariant; end; procedure TDataSetHelper.TDataSetRecord<T>.TPropMapping.LoadFromField(var Target: T); begin FRTTIProp.SetValue(GetPointer(Target), TValue.FromVariant(FField.Value)); end; I guess this is happening because of either reading/writing values from a Record or an Object. I searched (maybe not enough nor thoroughly) the Internet but I wasn't able to solve this by myself. Can someone helps me sorting this out adapting attached unit to handle simple properties types (integer, double, date, string, boolean....) values as well Nullable one ! (and rejects complex types too 🙂 ) I'll really appreciate some help. Kind regards, Stéphane Ps: I have attached modified Uwe's unit file. Ps2: I'm working with Delphi Sydney Aurelius.Dataset.helper.pas
  10. I was looking at an old blog post by Barry Kelly. In particular the function: function TLocation.FieldRef(const name: string): TLocation; var f: TRttiField; begin if FType is TRttiRecordType then begin f := FType.GetField(name); Result.FLocation := PByte(FLocation) + f.Offset; Result.FType := f.FieldType; end else if FType is TRttiInstanceType then begin f := FType.GetField(name); Result.FLocation := PPByte(FLocation)^ + f.Offset; Result.FType := f.FieldType; end else raise Exception.CreateFmt('Field reference applied to type %s, which is not a record or class', [FType.Name]); end; I am puzzled by the line: Result.FLocation := PPByte(FLocation)^ + f.Offset; If Flocation is an object (FType is TRttiInstance type) and I am having a record field inside the object, the Result.FLocation should be PByte(FLocation) + f.offset, i.e. the same as for FType is TRttiRecord. Barry Kelly is probably the guy that wrote the Rtti stuff, so he knows what he is talking about. What I am missing?
  11. I want to get a list of interfaces registered in a Delphi 2007 application (with code from within that application) in order to check for possible duplicate GUIDs. There is a solution on GitHub which uses the System.RTTI unit, but unfortunately that unit is not available in Delphi 2007. Is it possible to do without? I also asked on StackOverflow: https://stackoverflow.com/q/54710667/49925
  12. I can do it without RTTI, but get a compiler error when using RTTI: procedure TForm1.Button1Click(Sender: TObject); var ctx: TRttiContext; rt: TRttiType; fld: TRttiField; proc: TWndMethod; begin proc := TabSet1.WindowProc; // Compiles and works OK without RTTI ctx := TRttiContext.Create; try rt := ctx.GetType(TControl); fld := rt.GetField('FWindowProc'); ShowMessage(fld.GetValue(TabSet1).TypeInfo.Name); // 'TWndMethod' if fld.GetValue(TabSet1).IsType<TWndMethod> then // True proc := fld.GetValue(TabSet1).AsType<TWndMethod>; // E2010 Incompatible types: 'procedure, untyped pointer or untyped parameter' and 'TWndMethod' finally ctx.Free; end; end; Any suggestions?
  13. As you know, modern Delphi versions add the RTTI information to the executable file. RTTI gives you the opportunity to do incredible things in your application. But it is not always necessary. You can disable RTTI in your application by adding the following lines to each unit: {$WEAKLINKRTTI ON} {$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])} But to completely disable RTTI, you need to add these lines to used RTL units too, and rebuild the project. How much will the size of the executable file decrease? Well, I checked it on small utilities from the Delphi Localizer project, and here is the result: kdlscan.exe was 742400 bytes, now 360448 bytes, -51% lngupdate.exe was 727040 bytes, now 282112 bytes, -61% (!!!) The smaller size of an executable file means that the file is read twice as fast from disk. In addition, the processor is more likely to be able to fully fit your utility into its cache. You can give other reasons why this makes sense.
  14. I want to recursively walk the properties of MyVar: TMyOuterType - but the Items list may be empty. How can I walk the base element type of Items, i.e. TMyType - when I have no instance data? type TMyType = class public property One: string; property Two: string; end; TMyType2 = class(TMyType) public property Two: string; end; TMyType3 = class(TMyType2) public property Three: string; end; TMyTypeArray = TArray<TMyType>; // i.e. polymorphic TMyOuterType = class public property Items: TMyTypeArray; end; var MyVar: TMyOuterType;
×