动态代理

反射机制:程序运行时自省的能力,通过反射操作类与对象,获取对象的类定义,类声明的属性与方法,调用方法与构造对象,甚至在运行时修改类的定义。

动态代理:是一种方便运行时动态构建代理,动态处理代理方法调用机制。代理是对调用目标的一个包装,对目标代码不是直接发生,而是通过代理发生,

动态代理,很多情况可以看作是装饰器的一个运用,反射是实现的一种常用的方式。

 

Autofac与Castle.DynamicProxy实现AOP功能

1、定义拦截器,实现 Castle.DynamicProxy.IInterceptor 

public interface IInterceptor
{
    void Intercept(IInvocation invocation);
}

其中:IInvocation的接口的方法,invocation.Arguments是数组,args[0]是第一个参数

invocation.Proceed(); // 调用下一个拦截器,直到最终的目标方法。

定义好了拦截器后,如何应用到相关对象呢?有两种方式:

     1)使用 Autofac.Extras.DynamicProxy.InterceptAttribute 特性将拦截器添加到相关的类或接口上;
     2)使用 ContainerBuilder 的 InterceptedBy() 方法在注册对象的同时添加拦截器。
 
基于接口的拦截器
   在注册对象的同时启用 EnableInterfaceInterceptors() 方法。
基于类的拦截器

      在注册对象的同时启用 EnableClassInterceptors() 方法。

比如:注册两个拦截器,然后通过autofac 的Ioc容器,实现Resolve服务,执行顺序:CalculaterInterceptor  --> CalculaterInterceptor2 --> Target Method --> CalculaterInterceptor2 --> CalculaterInterceptor 。拦截器中 invocation.Proceed() 方法用于调用下一个拦截器(若存在),直到最终的目标方法(Target Method)。不过 invocation.Proceed() 并不是一定要调用的,例如,对于有返回值的目标方法,我们在拦截器中设置 invocation.ReturnValue 值就可正确执行,这样便不会执行目标方法。在有些场景中,如身份验证、缓存读取等还是特别有用

 var builder = new ContainerBuilder();
            builder.RegisterType()
                .As()
                .EnableInterfaceInterceptors()
                .InterceptedBy(typeof(CalculaterInterceptor), typeof(CalculaterInterceptor2));  // 这里定义了两个拦截器,注意它们的顺序

            builder.RegisterType();  // 注册拦截器
            builder.RegisterType();  // 注册拦截器2

            var ioc = builder.Build();

            var calculater = ioc.Resolve();
            var addResult = calculater.Add(2, 3);

            Console.WriteLine($"add result: {addResult}");

另外:接口上以特性的形式注册,如上面代码中注释掉的那部分。若是既有在类型上注册,也有在 Autofac 的 Builder 中注册,那么这个拦截器会重复执行。

非虚方法,所有拦截器不会在该方法中调用。

 

在ABP vnext的实现方式,其中CastleAbpInterceptorAdapter<>的泛型参数才是用户定义的拦截器

if (serviceType.IsInterface)
            {
                registrationBuilder = registrationBuilder.EnableInterfaceInterceptors();
            }
            else
            {
                (registrationBuilder as IRegistrationBuilder)?.EnableClassInterceptors();
            }

            foreach (var interceptor in interceptors)
            {
                registrationBuilder.InterceptedBy(
                    typeof(CastleAbpInterceptorAdapter<>).MakeGenericType(interceptor)
                );
            }

            return registrationBuilder;

IInterceptor的实现是CastleAbpInterceptorAdapter的适配器,在此方法没有看到invocation.Proceed() 方法,而且这个方法需要用户定义的拦截器,恰是适配器的泛型参数,委托给他

 public void Intercept(IInvocation invocation)
        {
            var proceedInfo = invocation.CaptureProceedInfo();

            var method = invocation.MethodInvocationTarget ?? invocation.Method;

            if (method.IsAsync())
            {
                InterceptAsyncMethod(invocation, proceedInfo);
            }
            else
            {
                InterceptSyncMethod(invocation, proceedInfo);
            }
        }

拦截器有无返回值

  private async Task ExecuteWithoutReturnValueAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo)
        {
            await Task.Yield();

            await _abpInterceptor.InterceptAsync(
                new CastleAbpMethodInvocationAdapter(invocation, proceedInfo)
            );
        }

        private async Task ExecuteWithReturnValueAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo)
        {
            await Task.Yield();

            await _abpInterceptor.InterceptAsync(
                new CastleAbpMethodInvocationAdapter(invocation, proceedInfo)
            );

            return await (Task)invocation.ReturnValue;
        }

这里有个IAbpMethodInvocation的实现CastleAbpMethodInvocationAdapter,如何官方的实现的InvocationInvocation进行无缝结果,实现有什么差别ProceedInfo.Invoke()应该是调用目标的方法

在Castle.Core/DynamicProxy/AbstractInvocation.cs的Proceed()有InvokeMethodOnTarget()方法。 

 public void Proceed()
        {
            ProceedInfo.Invoke();

            if (Invocation.Method.IsAsync())
            {
                AsyncHelper.RunSync(() => (Task)Invocation.ReturnValue);
            }
        }

        public Task ProceedAsync()
        {
            ProceedInfo.Invoke();

            _actualReturnValue = Invocation.ReturnValue;

            return Invocation.Method.IsAsync()
                ? (Task)_actualReturnValue
                : Task.FromResult(_actualReturnValue);
        }

 

 

 问题:如何写这个适配器,原理是什么,作用是什么,如何解决异步的问题,这是一个很值得学习的地方

 

 

 

 

你可能感兴趣的:(动态代理)