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


Using the Policy Injection Application Block in ASP.NET : Page 3


An ASP.NET Example Application
To demonstrate how you can use the Policy Injection Application Block in your ASP.NET applications, Figure 2 shows a simple example that uses most of the features of the block. The example provides buttons to execute several methods on two business objects, named AttributedCustomerModel and InterfaceCustomerModel. Both objects contain methods that access an XML file containing a list of customers. The InterfaceCustomerModel class also exposes a property, demonstrating how you can use the Policy Injection Application Block with target object properties as well as methods. You can download the example application in both VB.NET and C# versions.

Figure 2. Trace Information: The figure shows the sample application displaying the trace information.
In Figure 2, notice that the application has tracing enabled so you can see the messages generated by the members of the business objects as the main application code calls them (the screenshot has been altered to remove some of the ancillary details so that you can more easily see the tracing information, which helps to show the operation of handlers such as the Caching Handler).

Business Objects in the Example Application
The two business objects used in the example application demonstrate the two different types of target object for which the Policy Injection Application Block can create handler pipelines. The AttributedCustomerModel class (in the App_Code subfolder) inherits from MarshalByRefObject, and so the Create and Wrap methods of the block's PolicyInjection class can create instances directly, building a suitable proxy and injecting a handler pipeline for any class members that have a policy defined in the configuration, or that carry handler attributes.

The second business object class, InterfaceCustomerModel, does not inherit from MarshalByRefObject, and so the example includes a interface definition (named ICustomerInterface) for this class that the Create and Wrap methods can use to create the appropriate proxy and handler pipelines. However, to demonstrate the way that the block relies on this interface, one of the public members of the InterfaceCustomerModel class does not exist in the interface definition. Table 1 shows the methods exposed by the two business objects.

Member Attributed Customer Model Interface Customer Model Notes
GetCustomerList() Yes Yes  
GetCustomerName(String customerID) Yes No  
GetCustomerNameWithWildcard(String customerID) No Yes Uses GetCustomerName method with a wildcard.
GetCustomerDetails(String customerID) Yes Yes Not defined in interface.
GetCityList(Int32 minimumCount) No Yes  
CityCount No Yes Property. Uses GetCityList

The Example Application UI
The UI for the example application resides in one page named Default.aspx, seen in Figure 2. Each button has an event handler in the associated code-behind file Default.aspx.cs, which creates an instance of the appropriate target class and calls the required method. Depending on the type of data returned (a String, a DataRow, or a DataSet), the event handlers display it in the page. If an exception occurs, the text "ERROR:" followed by the exception message appears instead.

For the AttributedCustomerModel class, which inherits MarshalByRefObject, the event handlers can create an instance using the Create method and the class type:

AttributedCustomerModel customers = PolicyInjection.Create<AttributedCustomerModel>();

For the InterfaceCustomerModel class, which does not inherit MarshalByRefObject, the event handlers must specify the known interface for this class as well as the class type when they call the Create method:

ICustomerInterface customers = PolicyInjection.Create<InterfaceCustomerModel, ICustomerInterface>();

Note that this approach returns an object of the interface type and not the actual class type. This is because the proxy between the application and the target object can only see the members of the interface, and not members of the concrete class. If you try to cast the returned interface reference to a concrete type, the result is null—as demonstrated by this code in the event handler that attempts to get the customer details from the InterfaceCustomerModel class:

ICustomerInterface customers = PolicyInjection.Create<InterfaceCustomerModel, ICustomerInterface>(); // NOTE: this method is not declared in the ICustomerInterface interface. // To access it, you might try to cast it to the concrete type. However, // the following cast of the proxy to the concrete class returns null InterfaceCustomerModel realObject = (customers as InterfaceCustomerModel); // and so the following code will fail because realObject is null DataRow[] details = realObject.GetCustomerDetails( txtID_InterfaceCustDetails.Text); if (details.GetLength(0) > 0) ...

If you click the corresponding button in the example page, you will see that it produces an error, as shown in Figure 3.

Figure 3. Expected Error: The figure shows an error when attempting to access a member not declared in the interface.
The code in the event handler for the button gets a list of customers from the InterfaceCustomerModel class, demonstrating how you can use the Wrap method with an existing instance of a target object. The code first creates an instance of the InterfaceCustomerModel class using the new operator. The Policy Injection Application Block will not be able to see this object, and so cannot create a proxy and handler pipeline for it. However, calling the Wrap method with the interface type and passing the existing target object to it allows the block to create the required proxy and pipeline:

InterfaceCustomerModel customerObject = new InterfaceCustomerModel(); // now wrap the existing object so that PIAB can see it ICustomerInterface customers = PolicyInjection.Wrap<ICustomerInterface>( customerObject);

Comment and Contribute








