4

I have a service class injected with Ninject 3.0. I have set it up so it's proxy is a class proxy rather than an interface proxy. The service has 2 methods, a first one returning broad result and a second one calling the first one and filtering it. I added a interceptor to cache the result of the first method.

The interception works fine when I call the first method from outside the service.

The problem is that when the interceptor invokes the second method, it invokes it through the service itself and not through the proxy, resulting in my call to the first method from my service not being intercepted, therefor not cached.

How can I get this to work?

UPDATE: Added sample code

This is on the top of my head so sorry if anything doesn't seem to compile

Here is a sample the service class

public class Service : IService
{

    [CacheMethodOutput]
    public virtual object[] GetObjects(int x)
    {
        ...
    }

    public virtual object GetObject(int x, int y)
    {
        return GetObjects(x).SingleOrDefault(o => o.y == y);
    }
}

The CacheMethodOutputAttribute is a simple attribute class

Here is a sample binding (this is the way I make sure to have a class proxy instead of a interface proxy but actually leave the injected reference by interface)

// Binds by type instead of proxy to create a class proxy
Bind<Service>().ToSelf().InSingletonScope().Intercept().With<CacheAttributeInterceptor>()
Bind<IService>().ToMethod<Service>(r => r.Kernel.Get<Service>());

So when I call GetObjects from any class in which the IService is injected, the interceptor is triggered, but it's not triggered from the GetObject method of the Service itself.

The CacheAttributeInterceptor looks like this (but details of implementation is irrelevant):

public class CacheAttributeInterceptor : SimpleInterceptor
{
    public ICacheManager CacheManager {get;set;}

    public override void BeforeInvoke(IInvocation invocation)
    {
        if (Attributes.GetCustomAttribute(invocation.Request.Method, typeof(CacheMethodOutputAttribute) != null)
        {
            string key = GenerateKey(invocation.Request.Method.Name, invocation.Request.Method.Arguments);

            object returnValue;
            if (!CacheManager.TryGet(key, out returnValue))
            {
                 invocation.Proceed();
                 returnValue = invocation.ReturnValue;
                 CacheManager.Add(key, returnValue);
            }
            else
                invocation.ReturnValue = returnValue;

        }
        else
            base.BeforeInvoke(invocation);
    }
}
fireOut
  • 39
  • 1
  • 2

1 Answers1

-1

I found the solution / more detail on the problem.

If I remove the virtual modifier on the GetObject method, it will then not be intercepted anymore and when it will call GetObjects, the incerceptor will trigger.

All this got me thinking that if I want both method to be intercepted, I need to make the interceptor work deeply, if this is even possible.

fireOut
  • 39
  • 1
  • 2