Can datatype redefine getter/setter?
I have a lot of string properties, which need custom but similar Getters and Setters.
Currently I'm generating Getter and Setter in class generation code but that expands class definition.
Is there a way to specify custom datatype which would generate custom getters and setters?
I could imagine inheriting standard data types for a customized data type and then
adding methods LogicalToStorage and StorageToLogical similar as LogicalToObs, ....
So your manipulations happen on the way from Global to the local variable.
Additional Parameters eventually may control the generated code.
It's just a vague idea.
Here's what I've coded.
Property:
Class:
However reference to property does not return anything (expected to return property name):
Any ideas?
Can you please provide an example?
I'm aware only of %XML.PropertyParameters but there's nothing but parameters.
Turns out it's much easier than I thought:
Example:
set obj = ##class(Test.Obj).%New() write obj.prop >0 set obj.prop=1 write obj.prop >1
Okay, how do I make this work with methods?
On property get/set I need to call instance method.
I've tried this:
And class:
But it fails to compile.
instead of
do %code.WriteLine($c(9) _ "Quit ..Test()")
use
do %code.WriteLine($c(9) _ "Quit zTest()")
It worked for me best
Can you share the code please?
Changed .. to z and compilation fails for me.
It doesn't work for me too, there is an error
#1056: Missing subscript : '}'
Thank you!
NoContext helped. What does it mean?
This works too btw:
d %code.WriteLine(" q ..Test()")
NoContext
With the same success it is possible to specify NoContext for the class:
It doesn't work for me:
MPP5376 : Method or Property 'Test' does not exist in this class.
That's because first code generation is run during Test.String compilation, which does not have Test method.
Add something like this at the beginning:
#; don't generate any code if it not for a property quit:%mode="method" $$$OK
Then it's better:
Sorry, I had more changes.
My approach in details
ClassMethod Get() As %String [ CodeMode = objectgenerator ]
{ do %code.WriteLine($c(9) _ "Quit $g(^Test.String, 0)")
quit $$$OK }
ClassMethod Set(%val As %String) [ CodeMode = objectgenerator ] {
do %code.WriteLine($c(9) _ "Set ^Test.String = %val")
do %code.WriteLine($c(9) _ "do zTest()")
quit $$$OK }
/// this generates Method propTest()
/// but satisfies the Compiler for this class
ClassMethod Test() { quit ;; from Data definition }
}
compiles this routine:
;(C)InterSystems, generated for class DC.String. Do NOT edit. 10/04/2019 12:00:42PM
;;42345370;DC.String
;
zGet() public { Quit $g(^Test.String, 0) }
zSet(%val) public { Set ^Test.String = %val
do zTest() }
zTest() public { quit ;; from Data definition }
and the using class
Property prop As DC.String;
Method Test()
{ b quit ;; from using Class }
}
compiled as
;(C)InterSystems, generated for class DC.StringTest. Do NOT edit. 10/04/2019 12:02:35PM
;;49614632;DC.StringTest
;
%NormalizeObject() public {
If '$system.CLS.GetModified() Quit 1
If m%prop Set:i%prop'="" i%prop=(..propNormalize(i%prop))
Quit 1 }
%ValidateObject(force=0,checkserial=1) public {
set sc=1
If '$system.CLS.GetModified() Quit sc
If m%prop Set iv=..prop If iv'="" Set rc=(..propIsValid(iv)) If ('rc) Set sc=$$EmbedErr^%occSystem(sc,rc,5802,"prop",iv)
Quit sc }
zTest() public {
b quit ;; from using Class
}
zpropGet() public {
Quit $g(^Test.String, 0) }
zpropSet(%val) public {
Set ^Test.String = %val
do zTest() }
zpropTest() public {
quit ;; from Data definition
}
and the test
SAMPLES>set obj.prop=123
b quit ;; from using Class
^
<BREAK>zTest+1^DC.StringTest.1
SAMPLES 3d1>
Well, the code generator can be tricky.
It's not one of my favorites. But sometimes you have no choice.
Try this
OK.
StorageTo../..ToStorage only works in persistent classes where you move content from/to globals.
No chance without storage.
It doesn't get called in Registered Classes and not when the object wasn't saved.
see my test with %Persistent
write obj.prop ;nothing loaded yet
set obj.prop=77 write obj.prop ; unchanged as neither stored nor loaded
77
do obj.%Save(),obj,%Reload() ; force reload to trigger StorageToLogical
write obj.prop ; and here we go
prop
This proves that there is limited use of the approach.
Sorry, usually I use it to add custom methods to properties. Did not not, that it doesn't work for such methods as Set/Get. But you can add any other method.
Why do not use PropertyClass, so, you can generate own getter and setter for any property in a class?