zoukankan      html  css  js  c++  java
  • DProxy介绍 – 一种高性能轻量级AOP开发组件(.NET 1.1)

     现在体会到什么是最痛苦的事情,刚才在Blog上直接写文章,俺一直认为这种倒霉的事情不可能发生在这个时候,结果快要结束的时候突然弹出一个错误对话框,紧接着是浏览器毫无预兆的自动关闭………………….又一次从头到脚的体会到随时保存的确是一个好习惯。

    再来一次唧唧歪歪(就当刚才写的是草稿)

    感觉最近大家讨论AOP的话题越来越多了,于是呢,俺也来凑个热闹,俺花了些时间,也对AOP方面琢磨了一下,这一琢磨呢,就琢磨出来一个东西,什么东西,就是AOP。目前大家见到的AOP平台一大堆,俺就不在这里列举了。并且考虑到到现在为止了解Aspect#的人们还是挺多,为了利用这一资源,俺的DProxy也是提供了类似Aspect#的接口,只有少许地方的不同。因此你如果了解Aspect#的话,那么应该对下面的内容应该比较熟悉。

    虽说是轻量级,但也实现了Aspect#的两大拳头功能: Mixin Intercept
    为了让所有的.NET玩家能够快速了解到什么是Mixin和Intercept,俺给出下面两个实验场景

    试验场景
    1:俺写了个客户管理的程序,俺想将每个操作做为日志记录下来,于是乎写了下面几行代码

    public class Customer
    {
        
    public string Ask(string a, string b)
        
    {
            Log.WriteLog(
    "Customer::Ask begin");
    Console.WriteLine(
    "Ask: {0} or {1}", a, b));
            Log.WriteLog(
    "Customer::Ask end");
            
    return string.Format("I choose {0}",a));
        }

    }


    public class Log
    {
        
    public static void WriteLog(string s)
        
    {
            Console.WriteLine(s);
        }

    }


    static void Main(string[] args)
    {
        Customer c 
    = new Customer();
        Console.WriteLine(c.Ask(
    "red","blue"));
        Console.ReadLine();
    }



    上面每当ASK函数被调用的时候,在开始和结束的时候都会输出调试信息,如下图:


     但是俺总觉得这个方法有点不爽,为什么呢?如果将来Log类修改了怎么办,俺岂不是要在用过的地方全部修改一下,而且Log的代码和处理的逻辑代码放在一起总是有点别扭,怎么办?

    俺用DProxy想出了一个办法

     增加一个拦截类,在Ask函数被调用的时候拦截到它,犹如很久以前的 API HOOK,哈哈

    public class LogInterceptor  : IInterceptor
    {
        
    public object Intercept(IInvocation invocation, params object[] args)
        
    {
            Log.WriteLog(
    "Customer::Ask begin");
            
    object ret = invocation.Proceed(args);
            Log.WriteLog(
    "Customer::Ask end");
            
    return ret;
        }

    }

    然后Ask函数就可以写为

    public class Customer
    {
        
    public virtual string Ask(string a, string b)
    {
            Console.WriteLine(
    string.Format("Ask: {0} or {1}", a, b));
            
    return string.Format("I choose {0}", a);
        }

    }

    然后将Main函数修改一下

    [STAThread]
    static void Main(string[] args)
    {
        EmitProxyContract contract 
    = new EmitProxyContract();
        contract.Target(
    typeof(Customer));
    contract.Intercept(
    typeof(LogInterceptor),"Ask",typeof(string),typeof(string));

        EmitProxy proxy 
    = (new EmitProxyFactory()).GetProxy(contract);

        Customer c 
    = proxy.Wrap() as Customer;
        Console.WriteLine(c.Ask(
    "red","blue"));
        Console.ReadLine();
    }

    Customer这个类一下子就变得清爽多了,屏幕输出依旧:


    大家可以看到俺的
    Customer类中的代码已经不包含任何被Log的迹象,但事实上却被Log了,这个就是Hook。由于使用了DProxy俺就能很容易的实现它。

    试验场景
    2:俺上面写的客户程序,俺想加一些方法进去,比如说俺要获取客户的姓名。

    一般俺会这么做

    public class Customer
    {
        
    internal string myname = “TOX”; 
        
    public string GetName()
        
    {
            
    return "My name is " + this.myname;
        }

    }

    [STAThread]
    static void Main(string[] args)
    {
        Customer c 
    = new Customer();
        Console.WriteLine(c.GetName());
        Console.ReadLine();
    }

    这段程序的输出是:


    但是俺又想到,这个GetName可以是Customer类的,也可以是别的类的啊,那岂不是俺就要给每个需要实现GetName功能的类增加相同的代码?

    俺是懒人,因此就要研究如何才能够更偷懒,之所以俺才用.NET而不用VC6。于是呢,俺又想起 DProxy,于是俺用DProxy重新写了俺的代码,如下面所示:

    显示代码

    看看结果如何


    实现的功能是一样的哦,但是这可是把数据层和逻辑层分开了,而且代码的重用效率非常之高,用过Aspect#的人因该都知道。

    无聊至极,俺用俺的DProxyAspect#做了一个测试,结果如下:






    Aspect#创建的时候花的时间比较高是因为其内部有一个语言分析器,估计花了不少时间,而DProxy则没有。

    因为俺不知道Aspect#动态生成的代码是啥样的,因此俺也不知道为什么Aspect#在调用的时候要花那么长的时间,DProxy生成的代理使用的都是直接调用和接口调用,估计Aspect#使用的是Invoke

    关于直接调用,接口调用,Invoke等之间的性能对比可以参考MSDN的文章:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp02172004.asp

    目前DProxy尚在开发过程中,如果今后有了可供使用的版本,我会通知大家。

    2006/02/13 更新:
    DProxy 更名为 Sophus 并在 http://research.grapecity.com.cn/cs/files/7/sophus/default.aspx 提供免费下载

  • 相关阅读:
    这一年来,我的初三
    LGOJP4381 [IOI2008]Island
    BZOJ4484: [Jsoi2015]最小表示
    二分图染色及最大匹配(匈牙利算法)略解
    2019牛客多校第三场 F.Planting Trees
    性能优化 | 30个Java性能优化技巧,你会吗?
    进程 | 线程 | 当Linux多线程遭遇Linux多进程
    性能面试 | 性能测试常见面试题
    性能调优 | 如何通过性能调优突破 MySQL 数据库性能瓶颈?
    性能分析 | Java服务器内存过高&CPU过高问题排查
  • 原文地址:https://www.cnblogs.com/e2tox/p/285990.html
Copyright © 2011-2022 走看看