Wiki Home

Throw Exception Revisited

Namespace: VFP
This is some code that Bob Wright wrote based on the original Throw Exception topic posted by Mike Helland.

See Bob's comments at the bottom of the page.

&& this code is based on that global throw function that 
&& was on that fox wiki link you sent me.  I hope you find this 
&& interesting.
&& Main try block
&& this next method call is really interesting approach
&& Keeps responsibility of adding custom properties and augmenting
&& original exception properties to custom exceptions.

&& this next example is just a simple string assign to exception thrown
*!*    ThrowException(CREATEOBJECT("SimpleStringException"))

      SET STEP ON 
&& End of main try block

DEFINE CLASS SimpleStringException as MyCustomException
   FUNCTION SetExceptionProperties(oException as Exception) as VOID 
      && Assign user defined values to original exception
      oException.Message = "User Message goes here"
      oException.UserValue = This

&& Derived from MyCustomException
&& A little more complex Custom exception
DEFINE CLASS CustomerNotFoundException as MyCustomException
   && Overriding an abstract method
   FUNCTION SetExceptionProperties(oException as Exception) as VOID 
   && Assign user defined values to original exception
      oException.Message = "Customer not found"
      oException.UserValue = This  && Put Reference to UD Exception in userValue property reference. 

   && Additional excption method code.
   FUNCTION AddUserdefinedProperties(oException as Exception) as VOID 
   && Add user defined properties to original exception
      oException.AddProperty("CustomExceptionProperty1", "Raised by custom Exception")
      oException.AddProperty("CustomExceptionProperty2", "What everelse")
   FUNCTION DoWhateverElse()
   && Not really practical use.  Just example that one could use endless 
   && Method call to suit ones needs
      MESSAGEBOX("Nothing to add")

&& Base class for customExceptions
DEFINE CLASS MyCustomException as Exception 
   FUNCTION SetExceptionProperties(oException as Exception) as VOID 

&& Global Exception Function 
FUNCTION ThrowException(vException as Variant)
   LOCAL sClassString
      sClassString = GetClassHierarchy(vException)
      && check to see if exception "is a" MyCustomException
&&      CATCH TO oCaughtException WHEN "MYCUSTOMEXCEPTION" $ UPPER(sClassString)
      CATCH TO oCaughtException WHEN InClassHierarchy(vException, "MYCUSTOMEXCEPTION")

FUNCTION InClassHierarchy(oException as Exception, sClassName as String ) as Boolean 
   LOCAL ARRAY aClassArray(1) 	&& Array of class hierarchy
   LOCAL ReturnVal as Boolean, nElement as Number 

   IF TYPE("oException") = "O"
      ACLASS(aClassArray, oException)
      nElement = ASCAN(aClassArray,sClassName,1,-1,-1)
      ReturnVal = nElement > 0
   RETURN ReturnVal

&& Function to get class hierarchy
FUNCTION GetClassHierarchy(oException as Exception) as String 
   LOCAL ARRAY aClassArray(1) 	&& Array of class hierarchy
   LOCAL sClassString,;		&& String of class hierarchy
      	 nClassCount,;		&& Number of classes in hierarchy
	 sClassString = ""
   IF TYPE("oException") = "O"
      nClassCount = ACLASS(aClassArray, oException)
      FOR I = 1 TO nClassCount
         sClassString = sClassString + "'" + aClassArray(I) + "',"
   RETURN sClassString

When issuing a statement such as this: "THROW Create Object('MyCustomException')" Fox will throw a "User Defined" Exception. I thought this was misleading in a sense, it really raises a VFP Exception object and stores a reference to the object of type "MyCustomException" in the property UserValue of the VFP Exception object. Well what if the MyCustomException that I raised had responsibilities?? What if a higer error handler needed to be informed of the responsiblities this exception object just performed?

Well with Mike's idea with a global Throw Exception() function, one could kind of mask this desired behavior. If I where to Catch an Exception only if the object THROWN "is a MyCustomException" I could run all my custom code with one line of code in Mike's Throw Exception() funtion for any object derived from type "MyCustomException". So now if I were create a class "CustomerNotFound as MyCustomException" with Mike's approach when I throw this object it will be caught as well.

Since MyCustomException has an abstract method with a signiture of SetExceptionProperties(vException as variant) as void, one could pass the original Exception to the object derived from "MyCustomException" augment the VFP Exception to look like what ever you want and escalate the original exception. It won't escalate the responsibilities (Methods) that "MyCustomException" has, but you can make the VFP Exception kindof look like it.

This is just a idea that I had one night. I know there is a little bit of overhead with this approach but I think this encapsulates the responsiblities to the userdefined object and allows one to alter the original exception object to look like something else. Any thoughts or constructive criticism are welcome. Bob Wright

It's great to see that someone was able to incorporate custom Exception objects - in fact, before I tried setting all the properties on the caught exception in Throw Exception I tried this instead but it unfortunately ignored the variable re-reference:

Function ThrowException(oCustomException)
Local oExp
Catch To oExp
	oExp = oCustomException

- but I think the 90% use case is covered by Throw Exception; granted, you'd want to be using constants for the message names making them easily adjustable and compareable. Unless anyone can think of an ultra spiffy advantage to having an exception object with method's on it? -- Mike Helland

Category Code Samples Category Error Handling
( Topic last updated: 2003.04.30 02:27:20 PM )