4

我有一个注入了 Ninject 3.0 的服务类。我已经设置了它,所以它的代理是类代理而不是接口代理。该服务有 2 种方法,第一种方法返回广泛的结果,第二种方法调用第一种方法并对其进行过滤。我添加了一个拦截器来缓存第一种方法的结果。

当我从服务外部调用第一个方法时,拦截工作正常。

问题是当拦截器调用第二个方法时,它是通过服务本身而不是通过代理调用它,导致我从我的服务调用第一个方法没有被拦截,因此没有被缓存。

我怎样才能让它工作?

更新:添加了示例代码

如果有任何东西似乎没有编译,这在我的头上很抱歉

这是服务类的示例

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);
    }
}

CacheMethodOutputAttribute 是一个简单的属性类

这是一个示例绑定(这是我确保使用类代理而不是接口代理但实际上通过接口保留注入引用的方式)

// 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>());

因此,当我从注入 IService 的任何类调用 GetObjects 时,会触发拦截器,但不会从 Service 本身的 GetObject 方法触发。

CacheAttributeInterceptor 看起来像这样(但实现细节无关紧要):

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);
    }
}
4

1 回答 1

-1

我找到了解决方案/有关问题的更多详细信息。

如果我删除 GetObject 方法上的 virtual 修饰符,它将不再被拦截,当它调用 GetObjects 时,拦截器将触发。

所有这一切让我想到,如果我希望两种方法都被拦截,我需要让拦截器深入工作,如果这可能的话。

于 2012-11-16T19:06:37.413 回答