I'm using Simple Injector in my project. For integration Simple Injector with Castle.DynamicProxy I'm using this example.
I have following attributes:
public class MyLogAttribute : Attribute { // some code. }
public class MyTimerAttribute : Attribute { // some code. }
Then these attributes apply to method in my service.
public interface IMyService
{
void Do();
}
public class MyService : IMyService
{
[MyLog, MyTimer]
public void Do() { // some code. }
}
In my interceptors i am trying to get a custom attribute that applied to method, using the following code:
public class MyLogIntercept : Castle.DynamicProxy.IInterceptor
{
public void Intercept(Castle.DynamicProxy.IInvocation invocation)
{
var method = invocation.GetConcreteMethod();
method = invocation.InvocationTarget.GetType().
GetMethod(method.Name);
var attribute = method.GetCustomAttribute<MyLogAttribute>();
if(attribute != null)
{
// some code.
}
else
invocation.Proceed();
}
}
public class MyTimerIntercept : Castle.DynamicProxy.IInterceptor
{
public void Intercept(Castle.DynamicProxy.IInvocation invocation)
{
var method = invocation.GetConcreteMethod();
method = invocation.InvocationTarget.GetType().
GetMethod(method.Name);
var attribute = method.GetCustomAttribute<MyTimerAttribute>();
if(attribute != null)
{
// some code.
}
else
invocation.Proceed();
}
}
These interceptors registered using following code:
container.InterceptWith<MyLogIntercept>(
type => type == typeof(IMyService));
container.InterceptWith<MyTimerIntercept>(
type => type == typeof(IMyService));
My problem is that when i am trying in Intercept()
method get a custom attribute i get null
(attribute == null
). How can i get my a custom attributes?
P.S. If registered one intercept (MyTimerIntercept
or MyLogIntercept
it doesn't metter) for my service, in Intercept()
method i can get a custom attribute successfully (attribute != null
), but if both interceptor registered i have problem (attribute == null
).
P.S. I am using Castle.Core 3.3.3
The outer interceptor decorates the second interceptor, so when you call invocation.InvocationTarget.GetType()
, you might not get typeof(MyService)
, but the type becomes Castle.Proxy.IMyServiceProxy
. This type obviously doesn't have the attributes declared, so that's why it returns null
.
I honestly don't know how to solve this, but this is one of the many reasons why I prefer having SOLID code and use decorators instead of using interceptors.
With SOLID code, the problem goes away completely, because your services will usually only have one method, which removes the need of marking methods with attributes. When you do that, your decorator or interceptor can just apply to everything of the intercepted interface (because it will only have one method) and you don't have to screw around with attributes like this.
If you start using generic interfaces (such as the ICommandHandler<T> abstraction and IQueryHandler<T> abstraction), you can apply decorators to a wide range of implementations, which removes the need to write interceptors. Decorators remove the need to depend on external libraries such as Castle Dynamic Proxy or even your DI library and this makes your code much cleane4 and more maintainable.