• 使用动态代理,提高工作效率


        动态代理的一个最主要的应用场合就是实现AOP - 截获方法调用,加入自己的预处理、后处理或Around处理。
        我在ESBasic.Emit中实现了对这些截获的支持。
        首先,介绍两个截获者:
        /// <summary>
        
    /// IMethodInterceptor 对方法进行截获并加入预处理和后处理。
        
    /// </summary>
        public interface IMethodInterceptor
        {
            
    void PreProcess(InterceptedMethod method);

            
    void PostProcess(InterceptedMethod method ,object returnVal);
        }
        IMethodInterceptor 很容易理解,用于为截获插入预处理、后处理。这个非常容易理解。
         /// <summary>
        
    /// IAroundInterceptor 对方法进行Around截获处理。注意,必须要触发目标方法的调用。
        
    /// </summary>
        public interface IAroundInterceptor
        {
            
    object AroundCall(InterceptedMethod method);
        }
        Around处理由IAroundInterceptor完成。什么是Around处理了?比如,我们想捕获目标方法的异常,需要使用TryCatch将目标方法Around起来,这就是Around处理的一个例子。
        在上面的接口方法中都有一个参数InterceptedMethod,它封装了被截获的目标方法的基本信息。
    public sealed class InterceptedMethod
        {
            
    #region Ctor
            
    public InterceptedMethod() { }
            
    public InterceptedMethod(object _target, MethodInfo _method, object[] paras)
            {
                
    this.target = _target;
                
    this.method = _method;
                
    this.arguments = paras;
            } 
            
    #endregion

            
    #region Method
            
    private MethodInfo method;
            
    /// <summary>
            
    /// Method 被截获的目标方法
            
    /// </summary>
            public MethodInfo Method
            {
                
    get { return method; }
                
    set { method = value; }
            }
            
    #endregion

            
    #region Target
            
    private object target;
            
    /// <summary>
            
    /// Target 被截获的方法需要在哪个对象上调用。
            
    /// </summary>
            public object Target
            {
                
    get { return target; }
                
    set { target = value; }
            } 
            
    #endregion

            
    #region Arguments
            
    private object[] arguments;
            
    /// <summary>
            
    /// Arguments 调用被截获的方法的参数
            
    /// </summary>
            public object[] Arguments
            {
                
    get { return arguments; }
                
    set { arguments = value; }
            } 
            
    #endregion       

            
    #region Invoke
            
    /// <summary>
            
    /// Invoke 执行目标方法
            
    /// </summary>        
            public object Invoke()
            {
                
    return this.method.Invoke(this.target, this.arguments);
            } 
            
    #endregion
        }

        好,如何使用ESBasic.Emit来创建动态代理了?很简单,你只需要调用
    public static TInterface CreateAopProxy<TInterface>(object origin, IMethodInterceptor methodInterceptor, IAroundInterceptor aroundInterceptor)
        如果不需要某种截获处理,对应的参数传入null即可。
        举个例子,我们需要使用动态代理截获IComputer所有方法调用抛出的异常,并记录日志。IComputer定义如下:
        public interface IComputer 
        {
            
    int Add(int a, int b);      
        }

        
    public class Computer : IComputer
        {
            
    public int Add(int a, int b)
            {
                
    throw new Exception("TestException");
                
    return a + b;
            }   
        } 
        我可以使用Around截获者来截获异常,所以我实现一个自己的IAroundInterceptor
        public class ExceprionAroundInterceptor : IAroundInterceptor
        {
            
    #region IAroundInterceptor 成员
            
    public object AroundCall(InterceptedMethod method)
            {
                
    try
                {
                    
    return method.Invoke();
                }
                
    catch (Exception ee)
                {
                    ee 
    = ee;
                    
    //.. log Exception

                    
    throw;
                }
            }
            
    #endregion
        }
        现在,我们可以这样获得针对IComputer的动态代理的引用:
        IComputer proxy = ESBasic.Emit.Application.DynamicProxyFactory.CreateAopProxy<IComputer>(new Computer() ,null ,new ExceprionAroundInterceptor()) ;
        proxy.Add(
    12);
        这样就ok了,Add方法抛出的异常会被ExceprionAroundInterceptor截获。

        最后,提醒一下,如果你让Computer不从IComputer继承,运行结果也一样。你应该已经看到DynamicProxyFactory.CreateAopProxy方法的第一个参数是object类型,而不是泛型T,这说明只要对应的object包含了和目标接口一样的方法(签名完全一致)就可以 -- 这就是所谓的“换脸”能力,可以在这里看到更详细的说明。
        由于动态代理是使用Emit发射实现,所以效率上来说,和你手写的代码是没有区别的。

        下载 ESBasic.Emit.dll。

        











  • 相关阅读:
    MyEclipse 2016CI破解版for Mac
    关于Mac系统中my sql 和navicat for mysql 的连接问题。
    二分总结
    递推总结
    区间DP学习笔记 6/20
    搜索考试
    模板整理
    防线 2020/3/31
    JS 循环遍历JSON数据
    pm am 12小时格式化
  • 原文地址:https://www.cnblogs.com/zhuweisky/p/1204230.html
Copyright © 2020-2023  润新知