Partager via


Sending an Exception to the Exception Handling Application Block

Interaction between application code and the Exception Handling Application Block occurs when the application code catches an exception and sends it to the block to be handled. Application developers do not have to know how exceptions will be handled because they have to specify only the name of the relevant exception policy.

There are three main scenarios in which you may need to handle exceptions. The most common is the first of these, but this topic explains how you can use the block to implement all three scenarios. The scenarios are:

  • Handling All Exceptions in a Catch Section
  • Handling Specific Exceptions in a Catch Section
  • Executing Code Before or After Handling an Exception

Handling All Exceptions in a Catch Section

In most of your code, you are likely to just catch the base Exception type and handle all of the more specific exception types that inherit from Exception in the same way. The following code shows a typical outline implementation of a try...catch statement that does just this.

try
{
  // ... code here to carry out the tasks of the method ...
}
catch(Exception ex)
{
  // ... code here to handle the exception ...
}
'Usage
Try
  ' ... code here to carry out the tasks of the method ...
Catch ex As Exception
  ' ... code here to handle the exception ...
End Try

You can save considerable time and effort when implementing this common scenario by using the Process method of the Exception Handling Application Block to execute the code that does the work, and leave it to the block to handle any exception that may occur. The following code shows how you can implement this technique. It assumes you will resolve the class through the Enterprise Library container to populate the constructor parameter with an instance of the ExceptionManager class.

public class MyClass
{
  private ExceptionManager exManager;

  public MyClass(ExceptionManager exceptionManager)
  {
    exManager = exceptionManager;
  }

  public void ProcessActionMethod()
  {
    exManager.Process(MyActionMethod, "MyExceptionPolicy");
  }

  private void MyActionMethod()
  {
    // ... code here to carry out the application tasks ...
  }
}
'Usage
Public Class MyClass

  Private ExceptionManager exManager;

  Public Sub New(exceptionManager As ExceptionManager)
    exManager = exceptionManager
  End Sub

  Public Sub ProcessActionMethod()
    exManager.Process(AddressOf MyActionMethod, "MyExceptionPolicy")
  End Sub

  Private Sub MyActionMethod()
    ' ... code here to carry out the application tasks ...
  End Sub

End Class

Your application code would, in this example, call the ProcessActionMethod method to carry out the tasks required by the application. The Process method of the ExceptionManager class executes the code you specify in the delegate (method). If an exception occurs while this code is executing, the Process method sends the exception to the Exception Handling Application Block to be handled using the policy you specify in the parameters of the Process method. The policy can, if required, apply different rules to each exception type, including rules for the base type Exception if the specific exception type sent to the block is not one of those for which specific rules are defined. The Exception Handling Application Block will throw or ignore the exception, as stipulated by the relevant rule.

You can also use the Process method anywhere in your code where you call another method and capture the return value from the target method (if it returns a value). You can use a lambda expression to execute the target method, as shown in the following examples:

  • To execute a routine that does accept parameters but does not return a value:

    exManager.Process(() => method-name(param1, param2), 
                      "Exception Policy Name");
    
    'Usage
    exManager.Process(Function() method-name(param1, param2), _
                      "Exception Policy Name")
    
  • To execute a routine that accepts parameters and returns a value:

    var result = exManager.Process(() => method-name(param1, param2), 
                                   "Exception Policy Name");
    
    'Usage
    Dim result As [function-result-type] 
    result = exManager.Process(Function() result _
                                = method-name(param1, param2), _
                                  "Exception Policy Name")
    
  • To execute a routine that accepts parameters and returns a value, and supply a default value to be returned should an exception occur (and if the policy that executes does not throw the exception). If you do not specify a default value and the Post Handling Action is set to None, the Process method will return null (C#) or Nothing (Visual Basic) for reference types, zero for numeric types, or the default empty value for other types should an exception occur.

    var result = exManager.Process(() => method-name(param1, param2), 
                                   default-result-value,
                                   "Exception Policy Name");
    
    'Usage
    Dim result As [function-result-type] 
    result = exManager.Process(Function() result _
                                = method-name(param1, param2), _
                                  default-result-value, _
                                  "Exception Policy Name")
    
  • To execute code defined within the lambda expression itself (in Visual Basic, this technique is only available with version 10 and Visual Studio 2010):

    exManager.Process(() =>
      {
        // Code lines here to execute application feature    // that may raise an exception that the Exception    // Handling block will handle using the policy named    // in the final parameter of the Process method.    // If required, the lambda expression defined here     // can return a value that the Process method will    // return to the calling code.
      },
      "Exception Policy Name");
    
    'Usage
    ' NOTE: This applies only to Visual Basic 2010.
    exManager.Process(Function(param As type) _
        ' Code lines here to execute application feature    ' that may raise an exception that the Exception    ' Handling block will handle using the policy named    ' in the final parameter of the Process method.    ' If required, the lambda expression defined here     ' can return a value that the Process method will    ' return to the calling code.
      End Function, _
      "Exception Policy Name")
    

Note

The Process method is optimized for use with Lambda expressions, which are supported in C# 3.0 on version 3.5 of the .NET Framework and in Visual Studio 2008 onwards. However, Visual Basic only fully supports Lambda expressions in version 10 on version 4.0 of the .NET Framework and in Visual Studio 2010. If you are not familiar with lambda functions or their syntax, see Lambda Expressions (C# Programming Guide) or Lambda Expressions (Visual Basic). For a full explanation of using the HandleException method, see Key Scenarios in the online documentation for Enterprise Library 4.1.

Specifying the Post Handling Action with the Process Method

In general, when you use the Process method, you will configure the exception handling policy with a post-handling action of ThrowNewException unless you want your code to continue to execute after the Exception Handling Application Block handles the exception. The exception that the block will throw is the original exception you sent to the block; unless your policy includes a Wrap handler that wraps the original exception in a new exception, or a Replace handler that replaces the original exception with a new exception.

If you configure an exception handling policy with a post-handling action of NotifyRethrow and use the Process method, the block will either throw the exception automatically or ignore it. You cannot detect the value returned by the Exception Handling Application Block. Internally, the Process method calls the HandleException method, and throws the exception if this method returns true.

Handling Specific Exceptions in a Catch Section

In some cases, you may want to be able to handle different types of exceptions in different ways. The following code shows an outline example of this approach.

try
{
  // ... code here to carry out the tasks of the method ...
}
catch(ArgumentOutOfRangeException arex)
{
  // ... code here to handle invalid value exceptions ...
}
catch(SecurityException secx)
{
  // ... code here to handle security exceptions ...
}
catch(Exception ex)
{
  // ... code here to handle all other exceptions ...
}
'Usage
Try
  ' ... code here to carry out the tasks of the method ...
Catch arex As ArgumentOutOfRangeException
  ' ... code here to handle invalid value exceptions ...
Catch secx As SecurityException
  ' ... code here to handle security exceptions ...
Catch ex As Exception
  ' ... code here to handle all other exceptions ...
End Try

There are two approaches you can follow for this scenario. You can apply the technique shown in the previous example, Handling All Exceptions in a Catch Section. Instead of handling each exception type individually, you can use the Process method to execute your method code and send any type of exception that occurs to a single policy configured in the Exception Handling Application Block. This policy can apply different rules to each exception type, including rules for the base type Exception if the specific exception type sent to the block is not one of those for which specific rules are defined.

An alternative approach is to send some or all of the exceptions to the Exception Handling block, to be handled using the policy you specify in the parameters of the HandleException method, and decide whether to ignore or throw the exception based on the return value from the HandleException method. You can define a policy that applies to different types of exception, and send the exceptions from more than one catch section to the same policy if required. The following section describes use of the HandleException method.

Executing Code Before or After Handling an Exception

A less common, but still valid scenario is where you need to perform processing in the catch section before, after, or both before and after you handle the exception. This code will usually be there to clean up resources, or perform other processing that is required to ensure that the application behaves correctly. The following outline shows a possible implementation of this scenario.

try
{
  // ... code here to carry out the tasks of the method ...
}
catch(Exception ex)
{
  // ... code here to perform clean up tasks ...
  if (some-condition) 
  {
    throw new MyCustomException("some custom message");
  }
  else
  {
    // ... code here to perform any other processing ...
    throw new Exception("another custom message");
  }
}
'Usage
Try
  ' ... code here to carry out the tasks of the method ...
Catch ex As Exception
  ' ... code here to perform clean up tasks ...
  If some-condition Then 
    Throw New MyCustomException("some custom message")
  Else
    ' ... code here to perform any other processing ...
    Throw New Exception("another custom message")
  End If
End Try

In this scenario, you can use the Exception Handling Application Block to handle any exceptions that you need to expose, and check the return value from the HandleException method to control the execution flow of your code. This allows you to apply policies that are configurable, yet still perform any necessary processing within your catch section.

For example, the following code shows how you can perform processing and make use of the policies you define in the Exception Handling Application Block. It assumes you have resolved an instance of the ExceptionManager class through the Enterprise Library container and saved it in a variable named exManager. For more information on instantiating objects, see Creating and Referencing Enterprise Library Objects.

...
catch(Exception ex)
{
  // ... code here to perform clean up tasks ...
  Exception newException;
  bool rethrow = exManager.HandleException(ex, "MyPolicy", out newException);
  if (rethrow) 
  {
    // ... any other processing required before re-throwing the exception ...
    if (newException != null) throw newException;
    throw;
  }
  // ... any other processing, including deciding whether to re-throw or not ...
}
'Usage
...
Catch ex As Exception
  ' ... code here to perform clean up tasks ...
  Dim newException As Exception
  Dim rethrow As Boolean = exManager.HandleException(ex, "MyPolicy", newException)
  If rethrow Then 
    ' ... any other processing required before re-throwing the exception ...
    If Not newException Is Nothing Then
      Throw newException
    End If
    Throw
  End If
  ' ... any other processing, including deciding whether to re-throw or not ...
End Try

Note

The non-static facade named ExceptionManager replaces the static ExceptionPolicy facade used in earlier versions of the Exception Handling Application Block. However, the static facade is still included, and existing applications that use the previous approach to handling exceptions will continue to work in this release.