Unity interception before and after a function call.

Topics: Enterprise Library Core
Jan 17, 2011 at 5:59 PM

I have read a few articles on intercpetion with Unity but I have failed to see a simple example that fits what I want to do.

First, I want to intercept (add to the call chain) before AND after the regular interface method implementation. I would like to be able to detect if the interception happened before or after.

Second, If the 'regular' implementation returns a value I don't want the value returned from the intercepted method to interfer with what is already being returned. Of course if the method is intercepted before then there would be no value to return. Just for my information I would like to also know how to override the return value of the method with that of an intercepted method. This becomes more complex if there is a chain of functions that each possibly could return a value.

Thank you.

Jan 17, 2011 at 6:47 PM

Interception always happens before and after. It's up to you in the implementation of the call handler if something happens at each of those points. The handler sits on "top" of the target method, and it can decide to do stuff before calling the target, after calling the target, or even not to call the target at all. Handlers aren't placed in the call chain before or after the target, they're a decorator chain instead.

Have you looked at the implementation of a custom behavior or call handler yet? In the Invoke method of every once, you'll see a call like this:

IMethodReturn result = getNext()(input, getNext);

This call is what calls either the next handler in the chain, or the target if there isn't any. If you want to do stuff before calling the target, put that code before this call. If you want to do stuff after calling the target, put code after this call. It's that simple.

Also notice the return value result - this contains the value that was returned from the target or exception that was thrown, if any.

The ultimate return value from an intercepted called is determined by the IMethodReturn object returned from the Invoke method. There's nothing that requires you to return the same IMethodReturn object you got back from the target. The input parameter you received contains two methods you can use: CreateMethodReturn and CreateExceptionMethodReturn. These methods can be used to construct whole new return values, and either return a value or cause an exception to be thrown.

I hope this points you in the right direction.

 

 

Jan 17, 2011 at 10:07 PM

Thank you for the tips.

A couple of questions if you have time.

You state:

This call is what calls either the next handler in the chain, or the target if there isn't any. If you want to do stuff before calling the target, put that code before this call. If you want to do stuff after calling the target, put code after this call. It's that simple.

If I have

(before code)
IMethodReturn result = getNext()(input, getNext);
(after code)

How do I know which of the results is from the target?

If the result is an exception can I just return the result or do I need to explicitly call ‘CreateExceptionMethodReturn’ ?

From: ctavares [email removed]
Sent: Monday, January 17, 2011 1:48 PM
To: rkevinburton@charter.net
Subject: Re: Unity interception before and after a function call. [entlib:242122]

From: ctavares

Interception always happens before and after. It's up to you in the implementation of the call handler if something happens at each of those points. The handler sits on "top" of the target method, and it can decide to do stuff before calling the target, after calling the target, or even not to call the target at all. Handlers aren't placed in the call chain before or after the target, they're a decorator chain instead.

Have you looked at the implementation of a custom behavior or call handler yet? In the Invoke method of every once, you'll see a call like this:

IMethodReturn result = getNext()(input, getNext);

This call is what calls either the next handler in the chain, or the target if there isn't any. If you want to do stuff before calling the target, put that code before this call. If you want to do stuff after calling the target, put code after this call. It's that simple.

Also notice the return value result - this contains the value that was returned from the target or exception that was thrown, if any.

The ultimate return value from an intercepted called is determined by the IMethodReturn object returned from the Invoke method. There's nothing that requires you to return the same IMethodReturn object you got back from the target. The input parameter you received contains two methods you can use: CreateMethodReturn and CreateExceptionMethodReturn. These methods can be used to construct whole new return values, and either return a value or cause an exception to be thrown.

I hope this points you in the right direction.

Jan 18, 2011 at 2:10 AM
Edited Jan 18, 2011 at 4:40 AM

How do I know which of the results is from the target?

The result came from the Target should be after or the result variable itself from the "IMethodReturn result = getNext()(input, getNext);

If the result is an exception can I just return the result or do I need to explicitly call ‘CreateExceptionMethodReturn’ ?

As far as I know, yes you can just return the result as an exception (if for example the exception raised came from the Target). My understanding with "CreateExceptionMethodReturn" is if you opt to raise an exception within the handler class and return it as a result.

Hope this helps.

Gino Terrado
Global Technologies and Solutions
Avanade, Inc.
entlib.support@avanade.com

Jan 18, 2011 at 3:43 AM

The return value from the call to getNext()(input, getNext) is the return value from the target. There's only one result. Or, it might have been a return value that was modified by a handler that is later in the call chain than you. You can't tell the difference, and if you think you need to know you're Doing It Wrong (tm).

If you're not modifying the return value (replacing the value, swapping out one exception for another one, throwing an exception when the target didn't, etc) you can just return the IMethodReturn object you got directly. You only need to call one of the methods to create a return object if you're actually going to return something different.

 

Jan 18, 2011 at 7:08 AM

OK, now I am confused. There is the target, the method(s) that are chained together, and this handler that has an Invoke method. When I ‘register’ an interceptor am I registering the handler or the method that gets chained? I thought I understood this as each interceptor method was registered and called before or after the call to the target. But now you are saying that each interceptor could execute code before getNext() and after. So it seems possible that the target gets executed and one or more of the interceptor methods don’t get a chance to execute before the target executes. For example say I have interceptor methods A and B as part of the ‘Invoke’ code for A getNext calls the target then calls B. So B never has the chance to execute before the target. The worst case would be if the target was at the start of the chain then A and B wouldn’t get a chance to execute before the target. Or is this prevented by imposing some kind of call order? Putting the target at the end of the call chain would do it.

From: ctavares [email removed]
Sent: Monday, January 17, 2011 10:43 PM
To: rkevinburton@charter.net
Subject: Re: Unity interception before and after a function call. [entlib:242122]

From: ctavares

The return value from the call to getNext()(input, getNext) is the return value from the target. There's only one result. Or, it might have been a return value that was modified by a handler that is later in the call chain than you. You can't tell the difference, and if you think you need to know you're Doing It Wrong (tm).

If you're not modifying the return value (replacing the value, swapping out one exception for another one, throwing an exception when the target didn't, etc) you can just return the IMethodReturn object you got directly. You only need to call one of the methods to create a return object if you're actually going to return something different.

Jan 18, 2011 at 11:13 AM

I'm not really that clear with your stated scenario. Though, anyway not also sure if you have already read this section in the documentation - http://msdn.microsoft.com/en-us/library/ff660871%28v=PandP.20%29.aspx, I'm just thinking it might help out for clarity. HTH.

Gino Terrado
Global Technologies and Solutions
Avanade, Inc.
entlib.support@avanade.com

Jan 18, 2011 at 5:16 PM
KevinBurton wrote:

OK, now I am confused. There is the target, the method(s) that are chained together, and this handler that has an Invoke method. When I ‘register’ an interceptor am I registering the handler or the method that gets chained? I thought I understood this as each interceptor method was registered and called before or after the call to the target. But now you are saying that each interceptor could execute code before getNext() and after. So it seems possible that the target gets executed and one or more of the interceptor methods don’t get a chance to execute before the target executes. For example say I have interceptor methods A and B as part of the ‘Invoke’ code for A getNext calls the target then calls B. So B never has the chance to execute before the target. The worst case would be if the target was at the start of the chain then A and B wouldn’t get a chance to execute before the target. Or is this prevented by imposing some kind of call order? Putting the target at the end of the call chain would do it.


When you set up interception, you specify two (or three, it's "historic" :-) ) pieces.

The first is the interceptor. This is the mechanism used to actually perform the interception. You have three choices, and the one you pick depends on the type you're intercepting and the methods you want to intercept.

The second is the interception behaviors.These contain the logic that is executed when an intercepted method gets called.

The third part is the "historic" bit. Older versions of Entlib included the Policy Injection Block. This let you specify call handlers, which basically work like behaviors, with the exception that behaviors are invoked on every method call, while call handlers are only invoked on the methods they're specifically configured for. Policy Injection in Entlib 5 is implemented as a behavior.

When you set up interception, the system guarantees that the target is always at the end of the chain. A behavior/call handler cannot "choose to call the target" - it can only call the next thing in the chain.