Finding yourself in a property bind

From the wishful thinking department, I would love to be able to

var  
Src: TSomeClass;
MyObject : TBoundObject;
begin
MyObject.Bind(Src, CompilerMagic(TSomeClass.SomeBooleanProperty));
end;

instead of

var  
Src: TSomeClass;
MyObject : TBoundObject;
begin
MyObject.Bind(Src, 'SomeBooleanProperty');
end;

Why? Because the first one is resilient to property renaming.
Until I can, I am stuck with using something similar to

var
Src: TSomeClass;
MyObject : TBoundObject;
begin
MyObject.Bind(Src,
function (const Ref:TSomeClass):Boolean // reads the bound prop
begin
Result = Ref.SomeBooleanProperty;
end,
procedure (const Ref: TSomeClass; const Value:Boolean) // writes the bound prop
begin
Ref.SomeBooleanProperty := Value;
end);
end;

which actually has some benefits – such as being able to sanitize assigned values – but is way too verbose.

I wish…

10 thoughts on “Finding yourself in a property bind

  1. Oh how I wish there was something like:type  TProp = reference to property: T;var  myProp: TProp;begin  myProp := myObject.SomeBooleanPropery;end;

  2. Surely MyObject.Bind(Src, 'SomeBooleanProperty') CAN be resilient to property renaming, it just depends on the implementation of “Bind”.I guess you mean having an earlier failure case, i.e. compilation failure, rather than a unit test failure with a “property does not exist” exception.But if you have that form of resilience (which is better than NO resilience), then isn't what you gain on the swings (less verbose = greater clarity in the code) worth what you trade on the roundabouts (failure during testings vs compilation).I also am assuming that you have unit tests in place. 😉

  3. That would be a nice syntax, Stefan.Jolyon, In theory, the unit test would catch the missing string change, but I have yet to see a project of a decent size, developed under time pressure, that has 100% test coverage. Sad, but true.Strong typing implies spotting such errors at compile time, and that is my lament. I get by without property binding – but it would be a great asset.

  4. How about this. The string is still there but at a very easy to maintain location.type  TTestObject = class(TObject)  private    FSomeBoolean: Boolean;  public    property SomeBoolean: Boolean      read FSomeBoolean write FSomeBoolean;      const SomeBooleanProperty = 'SomeBoolean';  end;procedure Main;var  Src: TTestObject;  MyObj: TBoundObject;begin  Src := TTestObject.Create;  MyObj := TBoundObject.Create;  MyObj.Bind(Src, TTestObject.SomeBooleanProperty);end;Unfortunately Delphi's RTTI doesn't contain any class property information. Otherwise the string could be eliminated by using a class property and initializing them in a class constructor.

  5. @Andreas – Good suggestion for best practice.@Stefan – This looks really interesting. What kind of stability issues are there? Can it be made stable based on the current compiler and RTTI? Also – any usage examples?

  6. Stability issues in the case of I only tested it with 2 objects and 2 properties of Integer and string and I have no clue how it turns out with tons of objects, other types and more complex life cycles.Look at Sample9 how to use it.

  7. Still to use XE2 myself but it occurs to me that even MyObject.Bind(Src, 'SomeBooleanProperty');makes it easier to spot necessary name changes than a TDBEdit.FieldName property inside the object inspector.

  8. @Francois – I did :)@Lachlan – I agree. I liked Andreas' suggestion of using a const. That would really improve the odds where there are multiple references.

Leave a Reply