Create mobile apps with HTML5, JavaScript and Visual Studio

(Elle) #1

msdnmagazine.com February 2014 73


crosscutting concerns. The Unity container instantiates objects


of the derived type at run time. Instance interception can only


intercept public instance methods. Type interception can intercept


both public and protected virtual methods. Keep in mind that,


due to platform constraints, Unity interception does not support


Windows Phone and Windows Store app development, though


the core Unity container does.


For a primer on Unity, see “Dependency Injection with Unity”


(Microsoft patterns & practices, 2013) at amzn.to/16rfy0B. For more


information about interception in the Unity container, see the


MSDN Library article, “Interception using Unity,” at bit.ly/1cWCnwM.


Intercepting Task-Based Asynchronous Pattern


(TAP) Asynchronous Methods


Th e interception mechanism is simple enough, but what happens


if the intercepted method represents an asynchronous operation


that returns a Task object? In a way, nothing really changes: A


method is invoked and returns a value (the Task object) or throws


an exception, so it can be intercepted just like any other method.


But you’re probably interested in dealing with the actual outcome


of the asynchronous operation rather than the Task representing


it. For example, you might want to log the Task’s return value, or


handle any exception the Task might produce.


Fortunately, having an actual object representing the out-


come of the operation makes interception of this asynchro-


nous pattern relatively simple. Other asynchronous patterns


are quite a bit more diffi cult to intercept: In the Asynchronous


Programming Model (bit.ly/ICl8aH) two methods represent


a single asynchronous operation, while in the Event-based


Asynchronous Pattern (bit.ly/19VdUWu) asynchronous opera-


tions are represented by a method to initiate the operation


and an associated event to signal its completion.


In order to accomplish the interception of the


asynchronous TAP operation, you can replace the Task


returned by the method with a new Task that performs


the necessary post-processing after the original Task


completes. Callers of the intercepted method will receive the new


Task matching the method’s signature, and will observe the result


of the intercepted method’s implementation, plus whatever extra


processing the interception behavior performs.


We’ll develop a sample implementation of the basic approach to


intercept TAP asynchronous operations in which we want to log the


completion of asynchronous operations. You can adapt this sample to


create your own behaviors that can intercept asynchronous operations.


Simple Case


Let’s start with a simple case: intercepting asynchronous methods


that return a non-generic Task. We need to be able to detect that


the intercepted method returns a Task and replace that Task with


a new one that performs the appropriate logging.


Return
Value

Return
Value

Invoke
Object

Client


Proxy Object or
Derived Class

Target Object or
Original Class
Method

Behavior Behavior Behavior


Behaviors Pipeline


Invoke
GetNextHandlerDelegate

Message

Figure 1 Unity Interception Mechanism


public class LoggingAsynchronousOperationInterceptionBehavior : IInterceptionBehavior
{
public IMethodReturn Invoke(IMethodInvocation input,
GetNextInterceptionBehaviorDelegate getNext)
{
// Execute the rest of the pipeline and get the return value
IMethodReturn value = getNext()(input, getNext);

return value;
}

#region additional interception behavior methods

public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}

public bool WillExecute
{
get { return true; }
}

#endregion
}

Figure 2 Simple Interception


public IMethodReturn Invoke(IMethodInvocation input,
GetNextInterceptionBehaviorDelegate getNext)
{
// Execute the rest of the pipeline and get the return value
IMethodReturn value = getNext()(input, getNext);

// Deal with tasks, if needed
var method = input.MethodBase as MethodInfo;
if (value.ReturnValue != null
&& method != null
&& typeof(Task) == method.ReturnType)
{
// If this method returns a Task, override the original return value
var task = (Task)value.ReturnValue;
return input.CreateMethodReturn(this.CreateWrapperTask(task, input),
value.Outputs);
}

return value;
}

Figure 3 Returning a Task


Fortunately, having an actual


object representing the


outcome of the operation makes


interception of this asynchronous


pattern relatively simple.

Free download pdf