Home RAP
New Blog Posts: Merging Reports - Part 1 and Part 2

Problems with RTTI

edited August 2002 in RAP
I wrote an RTTI for TField a few weeks ago so I could get my field objects
at the beginning of the report instead of using the Pipeline['fieldName']
syntax (which is slow at runtime). I exposed the IsNull and AsString
properties of TField. Everything went fine and I've been using this in
production.

Today I wanted to add AsDateTime. I added it and found that it was always
returning Now instead of the TDateTime in the field object. So I started
debugging. My debugging revealed very strange behavior that I need help
with.

First, I found that my TRAPTFieldRTTI.GetPropValue function never gets
called. I put a breakpoint in it, but it never breaks. I thought, "How
odd." So I changed the name of my AsString method to "Foo".
TRAPTFieldRTTI.GetPropValue still never gets called and, not surprisingly,
my Foo property always evaluates to empty string.

I've boiled this down in a simple Delphi project which can be downloaded
from here:

http://msedd.com/bug.zip

My RTTI code looks like this:

---------------------------
const
AsStringStr='AsString';

{ TRAPTFieldRTTI }
TRAPTFieldRTTI = class(TraTComponentRTTI)
public
class procedure GetPropList(aClass: TClass; aPropList: TraPropList);
override;
class function GetPropRec(aClass: TClass; const aPropName: string; var
aPropRec: TraPropRec): boolean; override;
class function GetPropValue(aObject: TObject; const aPropName: string;
var aValue): boolean; override;
class function RefClass: TClass; override;
class function SetPropValue(aObject: TObject; const aPropName: string;
var aValue): boolean; override;
end;

class procedure TRAPTFieldRTTI.GetPropList( aClass: TClass;
aPropList: TraPropList);
begin
inherited GetPropList(aClass, aPropList);
aPropList.AddProp(AsStringStr);
end;

class function TRAPTFieldRTTI.GetPropRec(
aClass: TClass; const aPropName: string;
var aPropRec: TraPropRec): boolean;
begin
result:=true;
if ppEqual(aPropName, AsStringStr) then
PropToRec(aPropName, daString, false, aPropRec)
else result:=inherited GetPropRec(aClass, aPropName, aPropRec)
end;

class function TRAPTFieldRTTI.GetPropValue(
aObject: TObject; const aPropName: string; var aValue): boolean;
begin
result:=true;
if ppEqual(aPropName, AsStringStr) then
string(aValue):=TField(aObject).AsString
else result:=inherited GetPropValue(aObject, aPropName, aValue)
end;

class function TRAPTFieldRTTI.RefClass: TClass;
begin
result:=TField
end;

class function TRAPTFieldRTTI.SetPropValue(
aObject: TObject; const aPropName: string; var aValue): boolean;
begin
result:=true;
if ppEqual(aPropName, AsStringStr) then
TField(aObject).AsString:=string(aValue)
else result:=inherited SetPropValue(aObject, aPropName, aValue)
end;

initialization
raRegisterRTTI(TRAPTFieldRTTI);

finalization
raUnregisterRTTI(TRAPTFieldRTTI);
---------------------
My report contains a label with this RAP OnGetText handler:

var
blah: TField;
begin
blah:=DBPipeline1.FieldObjects['GenDate'];
Text := blah.AsString
end;

And yet, GetPropValue never executes. If you simply change the const
AsStringStr to "Foo" and then change the RAP to read "Text := blah.Foo",
you'll (hopefully) see that Foo always evaluates to empty string and
GetPropValue still never runs.

What's up? Am I missing something fundamental here?

Thanks,
Kevin Donn

Comments

  • edited August 2002
    class function TRAPTFieldRTTI.RefClass: TClass;
    begin
    result:=TField
    end;

    result := TppField;

    Likely it...

    Tom Ollar
    Digital Metaphors Corporation

    P.S.
    Great work utilizing RTTI ;)
  • edited August 2002
    This doesn't seem to be it either. I started with my bug project, still
    available at:

    http://msedd.com/bug.zip

    And did the following:

    1) Changed the RefClass to TppField (which requires using ppDB).
    2) Changed cast to TField in GetPropValue to TppField.
    3) Removed SetPropValue entirely because TppField.AsString is read only and
    changed the ReadOnly flag in PropToRec to true.
    4) Change the RAP declaration to "blah: TppField."

    Compiling this produces exactly the same result that it did before.
    GetPropValue still doesn't execute. But now GetPropRec also doesn't run.
    Since GetPropRec no longer runs, I can't add any new properties:

    1) Change const definition of AsStringStr to 'Foo'.
    2) Change the RAP to read:
    var
    blah: TppField;
    begin
    blah:=DBPipeline1.FieldObjects['GenDate'];
    Text := blah.Foo;
    end;

    Now the report can't even compile because Foo isn't recognized since
    GetPropRec doesn't run.

    Please grab my bug project and take a look. It's tiny, uses only standard
    D5 classes and exhibits all of this behavior. Alternately, just give me an
    example of how to write pass throughs for TField so I can get AsString,
    IsNull, and AsDateTime in RAP.

    kd

  • edited August 2002
    var
    lField: TppField;
    begin
    lField := Customer.FieldObjects['Company'];
    Label1.Caption := lField.AsString;
    end;

    This code works for me in RAP, RB Enterprise 6.03. All of the RTTI you
    mention (except AsDateTime - use AsDouble) is already registered.

    Cheers,

    Tom Ollar
    Digital Metaphors Corporation
This discussion has been closed.