ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2019-06-09 15:53:45  阅读:430  来源: 互联网

标签:c dependency-injection ioc-container 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<IPlanRepository, PlanRepository>(
    new ContainerControlledLifetimeManager(),
    new Interceptor<VirtualMethodInterceptor>(),
    new InterceptionBehavior<PolicyInjectionBehavior>());

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

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

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

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

解决方法:

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

但是,在使用DynamicProxy时,必须将拦截器类与属性类分开.这实际上是一种更好的做法,因为这样可以保留属性passive,并防止强制您的代码库依赖拦截库.

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

public class MyCacheInterceptor : IInterceptor 
{   
    public void Intercept(IInvocation invocation) {
        var method = invocation.GetImplementationMethod();
        var attribute = method.GetCustomAttribute<MyCacheAttribute>();

        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原则和使用装饰器来促进面向方面编程.在我编写的应用程序中,我定义了一般的抽象,例如IRepository< TEntity>和IQueryHandler< TQuery,TResult>这使得通过装饰器应用缓存变得微不足道.装饰器的好处在于它们更清洁(因为它们根本不依赖于任何框架)并且性能更高.

标签:c,dependency-injection,ioc-container,simple-injector
来源: https://codeday.me/bug/20190609/1205651.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有