views:

621

answers:

4

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...

A: 

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

  value := '1000'; 
  prop.SetValue(obj, value);
François
+5  A: 

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.

Andreas Hausladen
A: 

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?

Heinz Z.
A: 

I have the same problem. Any Solution?

Frank