Reputation: 95
When I'm using interceptors in Castle Windsor, I can get access to the invocation target whenever a function is called (invocation parameter of type IInvocation).
Is it possible to get the target of the interceptor already in the constructor of this interceptor, so that I can write code like follows:
public class MyInterceptor: IInterceptor
{
public MyInterceptor(ITargetOfInterception target, ILogger logger)
{
logger.Log("Interceptor created for target type: " + target.GetType() );
}
}
Upvotes: 0
Views: 353
Reputation: 27374
It's not possible to get access to the target in the constructor but you can achieve what you're after by implementing IOnBehalfAware
(see doco here)
public void SetInterceptedComponentModel(ComponentModel target)
{
logger.Log("Interceptor created for target: " + target.ToString());
}
Upvotes: 1
Reputation:
You should have your instance already...
container.Register(Component.For<IInterceptor>().ImplementedBy<Logger>().Named("myinterceptor"));
Then each class you will decorate with an attribute with your interceptor.
[Interceptor("myinterceptor")]
public class Logger : IInterceptor
{
public void Intercept(IInvocation invocation) {
Console.WriteLine(">> type in <<");
invocation.Proceed();
Console.WriteLine(">> type out <<");
}
}
If you implement interceptor you will be able to know which type is resolved because you have defined such cross cutting concerns to be addressed by the interceptor.
I think you are wanting to have your interceptor know all types that require a contract with the interceptor instead of all types that are bound to the interceptors' instructions. I hope this helps!!
EDIT: This is how I use Unity to Logger:
Public Class LoggingInterceptionBehavior
Implements IInterceptionBehavior
Public Function Invoke(input As IMethodInvocation, getNext As GetNextInterceptionBehaviorDelegate) As IMethodReturn Implements IInterceptionBehavior.Invoke
' Before invoking the method on the original target.
Dim icp As ClaimsPrincipal = TryCast(Thread.CurrentPrincipal, ClaimsPrincipal)
' Access IClaimsIdentity which contains claims
Dim claimsIdentity As ClaimsIdentity = DirectCast(icp.Identity, ClaimsIdentity)
Dim param = GetParam(input)
If claimsIdentity IsNot Nothing Then
If param IsNot Nothing Then
WriteLog([String].Format("{0} is invoking method {1} at {2} with a parameter of {3}", claimsIdentity.Name, input.MethodBase, DateTime.Now.ToLongTimeString(), param))
Else
WriteLog([String].Format("{0} is invoking method {1} at {2} without a parameter", claimsIdentity.Name, input.MethodBase, DateTime.Now.ToLongTimeString()))
End If
Else
'no claim
WriteLog([String].Format("NO CLAIM Invoking method {0} at {1} with a parameter of {2}", input.MethodBase, DateTime.Now.ToLongTimeString(), param))
End If
' Invoke the next behavior in the chain.
Dim result = getNext()(input, getNext)
' After invoking the method on the original target.
If result.Exception IsNot Nothing Then
WriteCriticalLog([String].Format("Method {0} threw exception {1} at {2}", input.MethodBase, result.Exception.Message, DateTime.Now.ToLongTimeString()))
Else
WriteLog([String].Format("Method {0} returned {1} at {2}", input.MethodBase, result.ReturnValue, DateTime.Now.ToLongTimeString()))
End If
Return result
End Function
End Class
How I register them :
container.RegisterType(Of IXXXService, XXXService)(New Interceptor(Of InterfaceInterceptor)(),
New InterceptionBehavior(Of LoggingInterceptionBehavior))
Upvotes: 0
Reputation: 22310
While I do not know why you need it, I can think of 2 possible solutions for this.
First, you can hook on container.ComponentRegistered event (or some other event of your choosing), and inspect the handler to see the interceptors.
Second, you can use some static hash table in the interceptor, and log when a "new" target is detected on Intercept.
Probably the first solution is what you want.
Upvotes: 0