简体   繁体   English

注册/使用 Castle.Core.AsyncInterceptor 拦截器

[英]Registering/Using Castle.Core.AsyncInterceptor Interceptors

I'm trying to use the Castle.Core.AsyncInterceptor package to handle exceptions thrown from async methods but I'm struggling to understand how to link it all together.我正在尝试使用 Castle.Core.AsyncInterceptor 包来处理从异步方法抛出的异常,但我很难理解如何将它们链接在一起。

My previous ExceptionInterceptor implemented the standard IInterceptor interface, so I could apply the interceptor to all the relevant classes using something like我以前的 ExceptionInterceptor 实现了标准的 IInterceptor 接口,因此我可以使用类似的东西将拦截器应用于所有相关类

  _container.Register(Classes.FromAssemblyContaining(typeof(BaseDao))
                            .BasedOn<BaseDao>()
                            .Configure(c => c.Interceptors<ExceptionInterceptor>()));

The docs suggest implementing IAsyncInterceptor instead, which I have done, but the last line in the code above now understandably gives me a compile error (no implicit reference conversion from ExceptionInterceptor to IInterceptor) because it's not an IInterceptor any more.文档建议改为实现 IAsyncInterceptor,我已经这样做了,但是上面代码中的最后一行现在可以理解地给我一个编译错误(没有从 ExceptionInterceptor 到 IInterceptor 的隐式引用转换),因为它不再是 IInterceptor。

Instead the docs suggest doing it this way相反,文档建议这样做

var myClass = new ClasThatImplementsIMyInterface(); var generator = new ProxyGenerator(); var interceptor = new ClasThatImplementsIAsyncInterceptor(); IMyInterface proxy = generator.CreateInterfaceProxyWithTargetInterface<IMyInterface>(myClass,interceptor)

But I'm not sure what to do after that.但我不确定在那之后该怎么办。 Do I have to generate a proxy for each of my DAOs and then register them individually with the container before I can use them?我是否必须为我的每个 DAO 生成一个代理,然后在使用它们之前将它们单独注册到容器中?

I've been going through the accompanying unit tests to try and figure it out but I'm struggling to understand how it would work.我一直在通过附带的单元测试来尝试弄清楚它,但我正在努力理解它是如何工作的。

Thanks谢谢

I'll add what I have so far an an answer since it does answer my question to some extent, although needs some work to make it more generic.我将添加到目前为止我所拥有的答案,因为它确实在某种程度上回答了我的问题,尽管需要做一些工作才能使其更通用。 I've no idea how to apply this pattern to every DAO in an assembly but at least it works for one class.我不知道如何将此模式应用于程序集中的每个 DAO,但至少它适用于一个类。 I'd just have to repeat this for each class I want to add the interceptor to.我只需要为每个要添加拦截器的类重复此操作。

_container.Register(
          Component.For<IGroceryDao>()
              .UsingFactoryMethod(() => ServiceFactory.BuildGroceryDao(_container.Resolve<IDbTransaction>()))
              .LifestyleScoped());

It uses a factory method in ServiceFactory (just a class I created that contains the below method) to create the proxied DAO that has had the interceptor applied:它使用 ServiceFactory 中的工厂方法(只是我创建的一个包含以下方法的类)来创建已应用拦截器的代理 DAO:

public static IGroceryDao BuildGroceryDao(IDbTransaction transaction)
    {
      return (IGroceryDao) new ProxyGenerator()
                                .CreateInterfaceProxyWithTargetInterface<IGroceryDao>(new Neo4jGroceryDao(transaction), new ExceptionInterceptor());
    }

The transaction object is something that is already registered with the container that the DAO needs so I just resolve it and then pass it to the factory method.事务对象已经在 DAO 需要的容器中注册,所以我只是解析它,然后将它传递给工厂方法。

Seems to work anyway.似乎无论如何都可以工作。 If anyone can advise how to make this more generic that would be awesome but at least I think this answers the question as I asked it.如果有人可以建议如何使这个更通用,那会很棒,但至少我认为这回答了我提出的问题。

The Castle.Core.AsyncInterceptor nuget contains an extension method Castle.Core.AsyncInterceptor nuget 包含一个扩展方法

Castle.DynamicProxy.ProxyGeneratorExtensions.ToInterceptor(this IAsyncInterceptor interceptor)

that can convert async interceptor to sync interceptor.可以将异步拦截器转换为同步拦截器。 It seems that it's not possible to use an instance for registration, you need to do it some other way.似乎无法使用实例进行注册,您需要以其他方式进行。 It might be possible有可能

  • to register interceptor as a named component and use InterceptorReferences将拦截器注册为命名组件并使用 InterceptorReferences
  • just to create an adapter that converts async interceptor to sync interceptor只是为了创建一个将异步拦截器转换为同步拦截器的适配器

I have gone with adapter and it seems to work fine.我已经使用了适配器,它似乎工作正常。

internal class MyInterceptorAdapter : IInterceptor {
  private readonly IInterceptor inner;

  public MyInterceptorAdapter(SomeDependency dep) {
    inner = new MyAsyncInterceptor(dep).ToInterceptor()
  }

  public void Intercept(IInvocation invocation) 
       => inner.Intercept(invocation);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM