Hi,
I have updated to V 2.28.1-beta.2, but I think this problem has been around for a while.
Situation :
public object - DefaultsObject
has a property - Object2
DefaultsObject.Object2 = createobject("SomeClass")
The class SomeClass has properties and methods. For example a method named Method1.
Problem :
The properties are saved/restored correctly, but methods are not recreated properly.
Symptom :
?DefaultsObject.Object2.Method1()
- should return numeric, but instead returns .T.
objectOfXML_propSet() and related functions work with properties, but don't respect methods.
After being restored by objectOfXML_propSet(), DefaultsObject.Object2 looks like it has methods on it (intellisense shows them), but they don't really exist anymore (cannot step into them, do not work at all) and I assume FiC code has an object decorator somewhere that simply returns .T. if an invalid method call is made.
This call makes the object property a "zombie" :
I thought I would bypass the problem by setting DefaultsObject.wcPropSaveNot = "Object2", but this has not helped and the property is still being processed.
Further speculation :
- wcPropSaveNot is not working
- the methods-not-recreated problem might extend to more than just properties on public objects
Paul
Hi Paul,
Doubtful, cXMLofObject() of abOOP.prg
used in the save process saves the class and class library of each contained object, and objectOfXML() of abOOP.prg
recreates the object using the same class and classlibrary if ever user action has changed it, or recycles the existing instance.
will create a test case however.
on your side please make sure of the .class
and .classLibrary
of the restored object.
thanks
cannot step into them, do not work at all
do you mean that if you add a set step on
to the method it does not fire?
I assume FiC code has an object decorator somewhere that simply returns .T. if an invalid method call is made
no such thing, just a plain call to your object's method
the methods-not-recreated problem might extend to more than just properties on public objects
what does 'more than just properties' mean?
Methods are never, and can't be, 'recreated' at run time (.writeMethod()
only works at design time).
FoxInCloud keeps the object alive, and just swaps its properties; nothing happens on the methods.
If your classLibrary is a prg, you may want to compile
it…
wcPropSaveNot is not working
You're right, cXMLofObject()
overlooked .wcPropSaveNot
; here is a quick fix:
modify command abOOP.prg
replace the cXMLofObject_lPropSave() code by:
* -----------------------------------------
function cXMLofObject_lPropSave(toObj, tcProp, llFIC) && [cXMLofObject() private] {fr} Propriété modifiable à sauvegarder {en} Updateable property to be saved
local lcProp as String
lcProp = ',' + lower(m.tcProp) + ','
return .t.;
and !PEMstatus(m.toObj, m.tcProp, 1); && {en} Read-only
and !m.lcProp $ ',' + chrtran(lower('wcPropSave,wcPropSaveNot,_MemberData,Name'), ' ', '') + ','; && ,dataSession,dataSessionID
and (!m.llFIC or (.T.;
and m.lcProp $ ',' + Lower(chrtran(nvl(m.toObj.wcPropSave, ''), ' ', '')) + ',';
and ! m.lcProp $ ',' + Lower(chrtran(nvl(m.toObj.wcPropSaveNot, ''), ' ', '')) + ',';
);
and .t.
endfunc
I found the problem :
function objectOfXML_object_oClass(lcClass, lcClassLib, loClass) && [Internal] {en} [objectOfXML_object() private] class instance {fr} [privée de objectOfXML_object()] instance d'une classe
&& 2018-01-10 thn -- {FiC V 2.26.1-beta.1} {en} created
try
loClass = newobject(m.lcClass, m.lcClassLib, 0)
catch
loClass = newobject(m.lcClass, m.lcClassLib)
endtry
return m.loClass
endfunc
--> newobject(m.lcClass, m.lcClassLib, 0)
From VFP help :
"0 Specifies that the class or object is instantiated without executing any of the event or method code in the class or object. This feature is not supported in runtime applications." (emphasis is mine)
The problem is that using the 0 parameter creates "zombie" methods on the object which are unusable.
Calling NewObject() without the 0 parameter creates an object with usable methods.
I can see why the code is like this, but I suggest an exception is at least made for classes derived from relation and custom - I know this isn't a perfect solution, but the best I have at the moment.
I will be customising the code to behave like this until a better workaround is available.
Also, I noticed that the m.lcClassLib parameter is incorrect in my situation - it is set to sfic.vcx, but really the class is defined in a program file (or .fxp). While this is not correct, it isn't a problem at the moment because the class is found in the "set procedure" and "set classlib" paths anyway.
Paul
Great debugging again, thanks for sharing
Not sure why we used the 0
parameter, probably to avoid re-running the .init()
method when recreating the object instance while the original instance was released by another user. After thinking (or rather guessing) there's no reason why we should not re-run .init()
.
I suggest we do the other way round:
* ========================================
function objectOfXML_object_oClass(lcClass, lcClassLib, loClass) && [Internal] {en} [objectOfXML_object() private] class instance {fr} [privée de objectOfXML_object()] instance d'une classe
&& 2018-01-10 thn -- {FiC V 2.26.1-beta.1} {en} created
&& 2019-02-20 thn -- {FiC V 2.28.1-beta.3} {en} https://support.west-wind.com/ReplyMessage.wwt?id=5F317HTX0#5F317HTX0
try
loClass = newobject(m.lcClass, m.lcClassLib)
catch
loClass = newobject(m.lcClass, m.lcClassLib, 0)
endtry
return m.loClass
endfunc
m.lcClassLib
is equal to m.toObj.ClassLibrary
, so VFP rules.