Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


How To Create a Custom Policy Injection Application Block Handler : Page 2

Using custom policy injection, you can configure and apply policies exactly the way you want—but doing it right requires a little effort.

The General Implementation of a Call Handler
Call handlers follow a basic pattern, described in the following code. You can see that they implement the ICallHandler interface, which defines a method named Invoke. The interface also defines the GetNextHandlerDelegate that the Invoke method receives and uses to invoke the next handler in the pipeline or the target object member. The Invoke method receives an invocation message as an instance of a class that implements the IMethodInvocation interface, and must return an instance of a class that implements the IMethodReturn interface:

public class CallHandlerOutine : ICallHandler { ... constructor(s), properties, and local variable declarations here ... public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { ... pre-processing code goes here ... // decide whether to invoke the next handler, or short-circuit execution if (some-condition-based-on-parameters-or-environment) { // invoke the next handler or the target member IMethodReturn msg = getNext()(input, getNext); ... post-processing code goes here ... // return the message passed back from following handlers to // the caller return msg; } else { // short-circuit the process and return an exception Exception ex = new Exception("Some Error Message"); // create a ReturnMessage instance from the original invocation object IMethodReturn msg = input.CreateExceptionMethodReturn(ex) // return the new message to the caller return msg; } } }

Notice how the handler can create a return message from the original invocation message. You can use the CreateMethodReturn method of the invocation message to generate a non-error return message, or (as shown in the code above) the CreateExceptionMethodReturn method to generate a return message containing an exception and error message. You will see how to access the contents of the request and return invocation messages later in this article.

Implementing the NeverOnASunday Handler
Before starting work, consider whether you want to update your existing version of Enterprise Library, or create an entirely new modified version of the library. Bear in mind that because the new handler does not fundamentally change any other parts of the library, the easiest approach is to integrate it into your existing version. To do that, you edit the project in your EntLibSrc folder where you installed the source code. If you did not install the source code when you originally installed Enterprise Library, you can rerun setup to install it.

The sample code for this article contains the new and updated files for you to use with Enterprise Library 3.0 to implement the custom NeverOnASunday handler. Note that the Resources files in the two Properties folders, and the PolicyInjectionNodeMapRegistrar.cs and PolicyInjectionCallHandlerCommandRegistrar.cs files all replace existing files, while the rest are additions to the existing Enterprise Library files. If you have previously edited these files, you must merge the resource entries and the changes detailed in the later section "Registering the Configuration Node Class" with your existing files.

You'll find a complete version of this simple NeverOnASunday handler implementation in a single class located in the file SimpleNeverOnASundayCallHandler.cs. As you will see later, the actual handler used in the example code contains some extra features. However, to help you understand the basic approach, the next code example shows the simple implementation (minus the XML comments).

Notice that the class implements the ICallHandler interface, and is decorated with a ConfigurationElementType attribute specifying the class that exposes the configuration data for the handler (NeverOnASundayCallHandlerData). You will see this class later in this article:

[ConfigurationElementType(typeof(NeverOnASundayCallHandlerData))] public class NeverOnASundayCallHandler : ICallHandler { public static readonly Boolean DefaultNotSaturdayEither = false; private Boolean notSaturday; public NeverOnASundayCallHandler() : this(DefaultNotSaturdayEither) { } public NeverOnASundayCallHandler(Boolean notSaturdayEither) { this.notSaturday = notSaturdayEither; } public Boolean NotSaturdayEither { get { return notSaturday; } set { notSaturday = value; } } public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { Exception ex = null; // Calculate the current weekday. GregorianCalendar cal = new GregorianCalendar(); DayOfWeek weekDay = cal.GetDayOfWeek(DateTime.Now); if (weekDay == DayOfWeek.Sunday) { // Create the Exception to return and the return message. ex = new Exception(Resources.NotSundayExceptionMessage); } if ((notSaturday == true) && (weekDay == DayOfWeek.Saturday)) { // Create the Exception to return and the return message. ex = new Exception(Resources.NotSaturdayExceptionMessage); } if (ex != null) { // Return the exception in the return message. IMethodReturn msg = input.CreateExceptionMethodReturn(ex); return msg; } else { // Do nothing except invoke the next handler. return getNext()(input, getNext); } } }

The handler exposes a public property named NotSaturdayEither that specifies whether it should block invocations on Saturday as well as Sunday. The default for this parameter is False, as exposed by the field named DefaultNotSaturdayEither. Two constructors allow code to instantiate the handler with either the default value for the NotSaturdayEither property, or with a specified value.

The Invoke method simply checks the current day of the week, and either invokes the next handler; or creates an exception and returns it in a ReturnMessage instance to the caller.

Finally, notice that the handler uses values from the Resources for the project for the exception-message strings. This makes it easier to localize the code, or change the messages in the future if required. However, because this example handler uses the GregorianCalendar and English day names, it will not localize in any kind of sensible way to cultures that do not use this calendar! Table 1 shows the entries added to the Resources.resx file in the Properties folder of the PropertyInjection.CallHandlers project.

Table 1. The table lists the values added to the Resources.resx file in the PolicyInjection.CallHandlers project.
Name Value
NotSaturdayExceptionMessage Invocation not permitted on a Saturday
NotSundayExceptionMessage Invocation not permitted on a Sunday

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.