Home > OS >  Invoke a function when my class' methods trow an exception
Invoke a function when my class' methods trow an exception

Time:12-30

I have the following code :

Class MyClass {

  [AnotherClass] myInstance

  A(){
    myInstance.myFirstFunction($a, $b, $c)
  }

  B(){
    myInstance.mySecondFunction($d, $e)
  }

}

Each time I call the a method from the AnotherClass object, this one can throw on exception (in the backend, it is a timeout for an external service that forces me to refresh the connection).

What I would like each time a method of the "MyClass" class throws a specific exception, handle that one with an internal private method that will do some task (hence, refresh the connection).

Is it possible to do that? Like an excpetion handler you can do with SpringBoot in java?

If it is not can I refactor the code so that I will only call on private method in the MyClass class, passing the function and the parameter I want to call the myInstance instance with? Something like:

Class MyClass {

  [AnotherClass] myInstance

  A(){
    myHandler("myFirstFunction", @($a, $b, $c))
  }

  B(){
    myHandler("mySecondFunction", @($d, $e))
  }

  myHandler($name, $params){
    try{
      $this.myInstance.$name($param)
    } catch {
      $this.myInstance.refreshConnection();
    }

  }

}

Thanks a lot !

CodePudding user response:

You're on the right track; here's a simple, self-contained example class:

Class MyClass {

  # The wrapped object.
  [string] $myInstance = 'foo-bar-baz'

  [object] A() {
    return $this.myHandler('Split', @('-'))
  }

  [object] B() {
    return $this.B(2)
  }
  [object] B([int] $count) {
    return $this.myHandler('Split', @('-', $count))
  }

  # Hidden helper method that invokes the specified
  # method with the specified arguments and handles exceptions.
  hidden [object] myHandler($name, $params) {
    try {
      return $this.myInstance.$name.Invoke($params)
    } catch {
      # ... handle the exception
      Write-Verbose -Verbose "An exception occurred: $_"
      return $null
    }
  }

}

Sample calls:

$o=[MyClass]::new()

$o.A() # -> 'foo', 'bar', 'baz'
$o.B() # -> 'foo', 'bar-baz'
$o.B(-1) # -> exception, handled internally

Note:

  • The above relies on PowerShell's ability to reflect on a method without invoking it, if you access it without (); e.g.:

    'foo'.Split # lists the overloads of the string type's .Split() method
    
  • Doing so returns a System.Management.Automation.PSMethodinstance, which has an .Invoke() method to which you can pass an array of arguments; e.g., the following two calls are equivalent:

    # Regular method call -> 'foo', 'bar-baz'
    'foo-bar-baz'.Split('-', 2)
    
    # Equivalent call, via reflection.
    $methodName = 'Split'; $paramVals = @('-', 2) 
    'foo-bar-baz'.$methodName.Invoke($paramVals)
    

Therefore, in the class definition above, you could alternatively pass $this.myInstance.Split to the myHandler() method and call .Invoke() directly on it. In terms of performance, this probably won't make a difference, but if you're using Visual Studio Code with the PowerShell extension, you'll benefit from IntelliSense; here's a simplified example:

& { 
  param($method, $paramVals)
  $method.Invoke($paramVals) 
}  'foo-bar-baz'.Split  @('-', 2)
  • Related