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…
Oh how I wish there was something like:type TProp = reference to property: T;var myProp: TProp;begin myProp := myObject.SomeBooleanPropery;end;
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. 😉
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.
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.
You might want to look at this:http://code.google.com/p/delphisorcery/source/browse/trunk/source/Library/System/System.Properties.pasIt's far from being stable but to get an idea of what is possible. 🙂
@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?
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.
You'll want to answer the new survey about the next version wanted feature….
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.
@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.