Attribute based interception with Castle.DynamicProxy and Simple Injector

I am using Simple Injector in my project. To integrate Simple injector with Castle.DynamicProxy I am using this example .

I have the following attributes:

public class MyLogAttribute : Attribute { // some code. }

public class MyTimerAttribute : Attribute { // some code. }

      

Then these attributes are applied to a 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 applied to a 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 are registered using the following code:

container.InterceptWith<MyLogIntercept>(
     type => type == typeof(IMyService));

container.InterceptWith<MyTimerIntercept>(
     type => type == typeof(IMyService));

      

My problem is that when I try to use the method Intercept()

I get the custom attribute I get null

( attribute == null

). How can I get my custom attributes?

PS If there is a single intercept ( MyTimerIntercept

or MyLogIntercept

it doesn't matter) registered for my service, in the method Intercept()

I can get the custom attribute successfully ( attribute != null

), but if both interceptors are registered, I have a problem ( attribute == null

).

PS I am using Castle.Core 3.3.3

+3


source to share


2 answers


The outer interceptor decorates the second interceptor, so when you call invocation.InvocationTarget.GetType()

you may not get typeof(MyService)

, but the type will become Castle.Proxy.IMyServiceProxy

. This type clearly has no attributes declared, so it returns null

.

I honestly don't know how to solve this, but this is one of the many reasons why I prefer to have SOLID code and use decorators instead of using interceptors.



With SOLID code, the problem goes away completely because your services usually have one method , which removes the need for tagging methods with attributes. When you do this, your decorator or interceptor can simply apply to the entire intercepted interface (because it will only have one method), and you don't need to wrap such attributes.

Once you start using common interfaces (such as the ICommandHandler <T> abstraction and the IQueryHandler <T> , you can apply decorators to a wide variety of implementations, eliminating the need to write interceptors. Decorators eliminate the need to depend on external libraries such as Castle Dynamic Proxy or even from your DI library and this makes your code a lot cleane4 and more maintainable.

+2


source


As Stephen wrote above, this code:

 var method = invocation.GetConcreteMethod();

 method = invocation.InvocationTarget.GetType().
    GetMethod(method.Name);

      

Get a method for the proxy type.



To get a method on a real type, you can use the MethodInvocationTarget property:

method = invocation.MethodInvocationTarget;

      

0


source







All Articles