Castle 学习 之 动态代理

作者: 转交遇见陈绮贞 | 来源:发表于2016-04-14 00:16 被阅读346次

    前几天看见在项目中用Castle来实现动态代理,觉得很有意思,就找个时间自己研究一下。介绍就免了,那开始吧。

        public class AccountController : Controller
        {
            private AccountService accountService = new AccountService();
            // GET: Account
            public ActionResult Index(string name)
            {
                ViewBag.Msg = accountService.GetUser(name);
                return View();
            }
        }
    

    以前Service的实现基本上是IOC或者单例,今天我们就用动态代理来实现。

            public ActionResult Index(string name)
            {
                var proxy = new ProxyGenerator(); //提供类和接口的代理对象
                var interceptor =new AccountInterceptor();  //拦截器
                //var logInterceptor = new LogInterceptor();
                var accountService = proxy.CreateClassProxy<AccountService>(interceptor);
                ViewBag.Msg = accountService.GetUser(name);
                return View();
            }
    

    ProxyGenerator类会创建一个代理类来继承目标类,并重写目标类中虚方法。

        public class AccountInterceptor : IInterceptor
        {
            public void Intercept(IInvocation invocation)
            {
                var arguments = invocation.GetArgumentValue(0) as string;
    
                if (string.IsNullOrWhiteSpace(arguments))
                {
                    invocation.ReturnValue = "nono";
                    invocation.SetArgumentValue(0, "Stranger");
                    invocation.Proceed();
                    invocation.ReturnValue = "Stranger";
                    return;
                }
                else if (arguments.Equals("陈绮贞"))
                {
                    invocation.SetArgumentValue(0,arguments+"SAMA!");
                    invocation.Proceed();
                    return;
                }
                invocation.Proceed();
                return;
            }
        }
    

    拦截器需要需要实现IInterceptor接口,实现Intercept方法。Intercept接受一个实现了IInvocation接口类的参数,invocation个参数封装了一个代理的方法,其中Proceed用于调用目标方法。看一下方法注释。

            // 摘要:(度娘翻译)
            //     Proceeds the call to the next interceptor in line, and ultimately to the target
            //     method.将调用到下一个拦截线,并最终向目标方法。
            //
            // 备注:
            //     Since interface proxies without a target don't have the target implementation
            //     to proceed to, it is important, that the last interceptor does not call this
            //     method, otherwise a System.NotImplementedException will be thrown.
            没有目标的接口代理没有目标实现要继续进行,这是很重要的,即最后一个拦截不调用这个方法,否则会抛出 system.notimplementedexception。
            void Proceed();
    

    解释一下:ProxyGenerator的CreateClassProxy方法接受的是一个实现了IInterceptor接口的拦截器可变数组,并按顺序执行,类似一个调用链。Proceed被调用时,若果当前拦截器之后还有拦截器等待执行,则将调用传递到下一个拦截器,而不会去调用需要执行的方法,等到最后一个拦截器时才调用目标方法。如果我们调用的方法不是虚方法,也不会抛出异常的。(这里有个疑问:记得我在公司时,当我们调用的方法不是虚函数时也能被拦截到,Proceed方法不调用目标方法,然后拦截器结束后才会调用目标方法,今天debug时却发现拦截器一直没进去,不知道是不是由于使用的CreateClassProxy重载方法不同,明天去公司看一下。更新:虽然调用的方法不是虚函数,但是其内部调用了一个虚函数,这个虚函数被拦截到了,而不是调用的方法被拦截到。)

    IInvocation接口里有一些方法可以使我们获取和设置目标方法的参数可返回值,在这里我们就可以做一些参数上的验证和日志的记录。

    Castle的动态代理很简单明了,也是AOP实现方式的一种,有兴趣的可以了解一下。

    PS:有错误欢迎指摘。

    相关文章

      网友评论

        本文标题:Castle 学习 之 动态代理

        本文链接:https://www.haomeiwen.com/subject/tkkglttx.html