【问题标题】:Autofac Intercept Target MethodAutofac拦截目标方法
【发布时间】:2015-04-29 05:17:45
【问题描述】:

我正在使用 Autofac.Extras.DynamicProxy2 对服务实现执行一些方法拦截。

该服务有很多方法,我只想针对一些。

除了根据我想要拦截的方法的批准字符串字典检查调用目标名称之外,还有更好的做法吗?

   public void Intercept(IInvocation invocation)
    {
        invocation.Proceed();
        if (ContinueIntercept(invocation))
        {
            // Do intercept work
        }
    }

    private bool ContinueIntercept(IInvocation invocation)
    {            
        // Logic to compare invocation.MethodInvocationTarget.Name 
    }

它确实不会增加太多开销,但它仍然是一种糟糕的方式。特别是因为将它添加到特定的服务实现意味着它将拦截基类公共实现的所有方法调用。如果只拦截派生类就不会那么糟糕了。

我看到 Castle.DynamicProxy2 可以指定调用目标,但我不知道如何将其与 autofac 连接起来。

【问题讨论】:

  • 我没试过,但是docs 说“类拦截要求被拦截的方法是虚拟的,因为它使用子类作为代理技术。”,所以你可以尝试删除虚拟修饰符。

标签: c# aop autofac interceptor castle-dynamicproxy


【解决方案1】:

您可以使用IProxyGenerationHook 来指定ProxyBuilder 应该在哪种方法上生成代理。

public class FooProxyGenerationHook : IProxyGenerationHook
{
    public void MethodsInspected()
    { }

    public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo)
    { }

    public Boolean ShouldInterceptMethod(Type type, MethodInfo methodInfo)
    {
        if (type == typeof(Foo) && methodInfo.Name == "Do")
        {
            return true;
        }
        return false;
    }
}

然后,你可以这样注册:

    ProxyGenerator generator = new ProxyGenerator();
    FooProxyGenerationHook hook = new FooProxyGenerationHook();
    IFoo foo = generator.CreateClassProxyWithTarget<Foo>(new Foo(), new ProxyGenerationOptions(hook), new FooInterceptor());

为了避免为每个代理调用IProxyGenerationHook,您应该只有一个hook 实例。

使用 DynamicProxy2,您可以使用以下代码:

    FooProxyGenerationHook hook = new FooProxyGenerationHook();

    ContainerBuilder builder = new ContainerBuilder();
    builder.RegisterType<FooInterceptor>().AsSelf();
    builder.RegisterType<Foo>().As<IFoo>()
            .EnableClassInterceptors(new ProxyGenerationOptions(hook))
            .InterceptedBy(typeof(FooInterceptor));

【讨论】:

  • +1 来自我。值得指出的是“[出于性能原因] 始终在所有实现 IProxyGenerationHook 的类上覆盖 Equals/GetHashCode 方法”github.com/castleproject/Core/blob/master/docs/…
  • 但是使用这种方法,您仍然必须在此 ShouldInterceptMethod() 方法中维护要拦截的方法列表。有没有办法在 method 级别 with parameters 中使用属性,例如 [Logging(OutputLevel="Verbose")]?
  • @Calvin : 在 shouldintercept 方法中,您可以使用 GetCustomAttributes 方法访问该方法的属性
猜你喜欢
  • 1970-01-01
  • 2011-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-23
  • 2011-04-16
  • 1970-01-01
  • 2012-03-31
相关资源
最近更新 更多