4
votes

TRTTIProperty.SetValue( ) takes an TValue instance, but if the provided TValue instance is based on a different type then the property, things blow up.

E.g.

TMyObject = class
published
  property StringValue: string read FStringValue write FStringValue;
end;

procedure SetProperty(obj: TMyObject);
var
  context: TRTTIContext;
  rtti: TRTTIType;
  prop: TRTTIProperty;
  value: TValue;
begin
  context := TRTTIContext.Create;
  rtti := context.GetType(TMyObject);
  prop := rtti.GetProperty('StringValue');
  value := 1000;
  prop.SetValue(obj, value);
end;

Trying to cast the value to a string wont work either.

prop.SetValue(obj, value.AsString);
prop.SetValue(obj, value.Cast(prop.PropertyType.Handle));

Any ideas on how solve this?

UPDATE:

Some of you wonder why I want to assign an integer to an string, and I will try to explain. (Actually, it's more likely that I want to assign a string to an integer, but that's not that relevant...)

What I'm trying to accomplish, is to make a general 'middle-man' between gui and model. I want to somehow hook a textedit field to an property. Instead of making such an middle man for each model that I have, I hoped that the new RTTI/TValue thing would work some magic for me.

I'm also new to generics, so I'm not sure how generics could have helped. Is it possible to instantiate a generic at runtime with a dynamically decided type, or do the compile need to know?

E.g.

TMyGeneric<T> = class
end;

procedure DoSomething( );
begin
  prop := rtti.getProperty('StringValue');
  mygen := TMyGeneric<prop.PropertyType>.Create;
  //or
  mygen := TMyGeneric<someModel.Class>.Create;
end;

Maybe the age of magic has yet to come... I guess I can manage with a couple of big case structures...

3
What would you expect to happen, if this were "solved"? An integer is not a string, so what should happen when you try to store an integer in a string-typed property? "Things blow up" sounds pretty reasonable to me.Rob Kennedy
He's most likely expecting it to contain the value '1000', as Andreas implied in his answer.Mason Wheeler
Have added some info about what what I'm trying to do. Guess I'm just expecting to much...Vegar

3 Answers

5
votes

TValue is not a Variant. You can only read the datatype that "you" put into it.

TValue.Cast doesn't work because it has the same semantic that implicit type casts have. You cannot assign an integer to a string or vice versa. But you can assign an integer to a float, or you can assign an integer to a int64.

0
votes

Can't try it right now, but I would have written:

  value := '1000'; 
  prop.SetValue(obj, value);
0
votes

try

prop.SetValue(obj, value.ToString)

But for me it is same question as for François. Why you want to set the property with a value of the wrong datatype?