Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Subclass any COM object in VFP
Message
 
To
11/12/2000 14:25:40
General information
Forum:
Visual FoxPro
Category:
COM/DCOM and OLE Automation
Miscellaneous
Thread ID:
00451752
Message ID:
00451860
Views:
37
Erik, that's cool!!

Here is my analysis what's going on if you run it, obtained with good old SET DOHISTORY ON. :) And my comments just to clarify the sequence for myself in the first place. :)
oXML = CREATEOBJECT("myXML")
THIS.Async = .T.
* note that INIT() of oXML ( instance of myXML session class) 
* assigns a value to the property which does not exist in it. 
* But the try to set it does not cause an error "PEM does not exist... " etc.
* because This_Access method fires first and checks the existence of the property.
	IF PEMSTATUS(THIS, cPEM, 5) && This_Access method fired the first time
	* As the .Async property does not exist. the method returns This.oDom property 
	* which at the moment is still NULL.
	RETURN THIS.oDOM && At this point oDom_Access method fires 
					&& as RETURN statement is trying to access it
		* oDom_Access method:			
		IF ISNULL(THIS.oDom) && It's still NULL at the moment
		THIS.oDom = CREATEOBJECT("Microsoft.XMLDOM") && create it
		ENDIF
		RETURN THIS.oDom && Returns just created This.oDom object. 
					* That's where it get substituted instead of oXML itself 
					* to actually assign the .Async property value
					
* Setting the second property (which does not exist in oXML object)
THIS.PreserveWhiteSpace = .T.
	* This_Access method fires the second time
		IF PEMSTATUS(THIS, cPEM, 5) && As the .PreserveWhiteSpace property does not exist. 
		* the method returns This.oDom property 
		* which at the moment is already pointing to Microsoft.XMLDOM object (this.oDom property)
		RETURN THIS.oDOM && Returns This.oDom object reference which causes oDom_Access method to fire again
		* oDom_Access method:
			IF ISNULL(THIS.oDom) && It exists now.
			RETURN THIS.oDom && Return it. 
			* That's where it get substituted instead of oXML itself 
			* to actually assign the .PreserveWhiteSpace property value
			
* oXML instantiation finished

* Next command:
?oXML.Async && Causes This_Access to fire
	IF PEMSTATUS(THIS, cPEM, 5) && It exists
	RETURN THIS.oDOM && Returns This.oDom object reference which causes oDom_Access method to fire again
		* oDom_Access method:
		IF ISNULL(THIS.oDom) && It exists
		RETURN THIS.oDom && return it
?oXML.loadxml('')  && Causes This_Access to fire
* The sequence repeats
	IF PEMSTATUS(THIS, cPEM, 5)  && This "overridden" method exists for oXML itself
	RETURN THIS && the reference to oXML object to continue with oXML.LoadXML() method
	* oXML.LoadXML method fires
		IF cXML <> '' && cXML is a parameter. 
		* Calling THIS.oDOM.LoadXML(cXML) method
		RETURN THIS.oDOM.LoadXML(cXML) && Call to THIS.oDOM.LoadXML method causes This_Access method to fire again
		* Here it is more complicated as it causes This_Access to fire twice and oDom_Access once
		IF PEMSTATUS(THIS, cPEM, 5) && it exists
		RETURN THIS && the reference to oXML object
			* oDom_Access method fires
			IF ISNULL(THIS.oDom) && Causes This_Access to fire
				* This_Access method fires
				IF PEMSTATUS(THIS, cPEM, 5) 
				RETURN THIS && it exists
			RETURN THIS.oDom && return it. (causes This_Access method fire once again)
				IF PEMSTATUS(THIS, cPEM, 5) && it exists
				RETURN THIS && return it

?oXML.XML
* the sequence for querying the property repeats 
* like in case of ?oXML.Async command.
IF PEMSTATUS(THIS, cPEM, 5)
RETURN THIS.oDOM
IF ISNULL(THIS.oDom)
RETURN THIS.oDom
*********************
>Believe it or not, the following technique arose out of a real need, and I think that it might come in useful in several places.
>
>I have come up with a technique that allows me to effectively 'subclass' any COM object. We can already do this with ActiveX controls, but have previously been unable to do it with non-visual COM objects.
>
>The key is a little used VFP method called THIS_Access. Giving an object a THIS_Access method causes that method to run when any process accesses the object, even over COM boundaries. The THIS_Access method normally returns a reference to THIS, but you can return a reference to any object you want. The THIS_Access method receives a single parameter that holds the name of the PEM being accessed. So I can create an object that holds a reference to a COM object, and in the THIS_Access method put code to check the PEM being accessed against any PEM in my object. If it exists, return a reference to THIS, if it does not, assume that the caller wants to access a property native to the 'subclassed' object, and return a reference to that object.
>
>Using this technique, I can use a 'subclass' of a COM object to set default values, or create wrapper methods around commonly used methods, all the while giving the caller the impression that she is accessing the COM object directly.
>
>The object below is a simple wrapper around the Microsoft XML parser. All it does 'change' a couple of default properties in the DOM object, and ensure that any XML passed to the LoadXML method starts with ''.
>
>I have done this by setting the property values in the Init method (note the use of "THIS.Async"), and by creating an overriding "LoadXML" method where I can place my own code. In the overriding method, I can call the 'superclass' LoadXML method by simply calling THIS.oDOM.LoadXML. (Note DODEFAULT() will not work since I am not really overriding a parent class method).
>
>Besides the inability to call DODEFAULT(), and the fact that Intellisense doesn't work correctly on 'subclassed' object (I already tried IMPLEMENTS), this technique is perfectly analogous to real subclassing.
>
>
>
>oXML = CREATEOBJECT("myXML")
>?oXML.Async
>?oXML.loadxml('<test></test>')
>?oXML.XML
>
>DEFINE CLASS myXML AS Session
>
>	oDOM = .NULL.
>	LastXML = ""
>	
>	FUNCTION Init
>		THIS.Async = .T.
>		THIS.PreserveWhiteSpace = .T.
>	ENDFUNC
>
>	FUNCTION oDOM_Access
>		IF ISNULL(THIS.oDom)
>			THIS.oDom = CREATEOBJECT("Microsoft.XMLDOM")
>		ENDIF
>		RETURN THIS.oDom
>	ENDFUNC
>
>	FUNCTION THIS_Access
>		LPARAMETERS cPEM
>		IF PEMSTATUS(THIS, cPEM, 5)
>			RETURN THIS
>		ELSE
>			RETURN THIS.oDOM
>		ENDIF
>	ENDFUNC
>
>	FUNCTION LoadXML
>		LPARAMETERS cXML
>		IF cXML <> '<?xml version="1.0">'
>			cXML = '<?xml version="1.0"?>' + cXML
>		ENDIF
>		RETURN THIS.oDOM.LoadXML(cXML)
>	ENDFUNC
>ENDDEFINE
>
>
Nick Neklioudov
Universal Thread Consultant
3 times Microsoft MVP - Visual FoxPro

"I have not failed. I've just found 10,000 ways that don't work." - Thomas Edison
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform