使用Simple Injector进行方法级别的属性拦截

使用Unity,我可以快速添加基于属性的拦截

public sealed class MyCacheAttribute : HandlerAttribute, ICallHandler { public override ICallHandler CreateHandler(IUnityContainer container) { return this; } public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { // grab from cache if I have it, otherwise call the intended method call.. } } 

然后我这样注册Unity:

 container.RegisterType( new ContainerControlledLifetimeManager(), new Interceptor(), new InterceptionBehavior()); 

在我的存储库代码中,我可以选择性地装饰要缓存的某些方法(具有可以为每个方法单独定制的属性值):

  [MyCache( Minutes = 5, CacheType = CacheType.Memory, Order = 100)] public virtual PlanInfo GetPlan(int id) { // call data store to get this plan; } 

我正在探索在Simple Injector中执行此操作的类似方法。 从我读取和搜索的内容看起来只有接口/类型级别拦截可用。 但我希望能够选择使用这种类型的属性控制拦截行为来装饰各个方法。 有什么建议吗?

[编辑:将Autofac移至自己的问题以保持此问题的重点]

Simple Injector缺乏动态拦截的开箱即用function,因为这不符合其设计原则,如此处所述。 但是可以添加拦截function,例如使用Castle DynamicProxy,如此处所示。 也应该可以在Simple Injector之上使用Unity的拦截function,但我从未尝试过。

但是,在使用DynamicProxy时,必须将拦截器类与属性类分开。 这实际上是一种更好的做法,因为这会使您的属性保持被动,并防止强制您的代码库依赖于拦截库。

使用DynamicProxy实现此function时,它可能如下所示:

 public class MyCacheInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { var method = invocation.GetImplementationMethod(); var attribute = method.GetCustomAttribute(); if (attribute == null) { // Calls the decorated instance. invocation.Proceed(); } else { // caching here } } } public static class InvocationExtensions { public static MethodInfo GetImplementationMethod(this IInvocation invocation) { // NOTE: bit naive implementation var method = invocation.GetConcreteMethod(); return invocation.InvocationTarget.GetType().GetMethod(method.Name); } } 

然而,Simple Injector通过应用SOLID原则和使用装饰器来促进面向方面编程。 在我编写的应用程序中,我定义了通用抽象,例如IRepositoryIQueryHandler ,这使得通过装饰器应用缓存变得微不足道。 装饰器的好处在于它们更清洁(因为它们根本不依赖于任何框架)并且性能更高。