zoukankan      html  css  js  c++  java
  • 源码发布 DynamicMethodProxyFactory组件

    在前面的文章改进的“以非泛型方式调用泛型方法”之基于DynamicMethod的实现中,提到了一种通过DynamicMethod以非泛型方法代理访问泛型方法的较佳方法(无额外代码定义需要,执行时间大约相当于直接调用泛型方法的3-4倍)。本文介绍的组件在前文思路的基础上,进行进一步的扩展,封装成一个较通用的DynamicMethodProxyFactory组件。除了可以较高性能访问任意的静态或非静态、泛型或非泛行方法之外,利用DynamicMethod可将代码插入内存中已载入的Module的能力,提供了在程序集外实例化指定Module中的internal类型,在程序集外调用internal类型的方法和public类型的internal方法的支持。

    该组件实现如下功能:
    1、以通用的非泛行方法Delegate访问任意方法(泛型或非泛型,静态或非静态);
    2、支持在程序集外调用指定Module中的internal类型的任意属性(属性本质上可以通过它的get/set方法以方法的形式访问)和方法和public类型的internal方法;
    3、支持创建并返回指定Module中的internal类型的实例;

    以非泛型方式调用泛型方法的意义在前文中已经讨论过了,对很多支持泛型方法的框架来说,是非常必要的代替反射的功能(相比反射性能提升3-4个数量级)。

    那么访问internal类型和方法有什么意义呢?除了突破原来的CLR的不能跨程序集访问internal成员的限制这个明显的好处之外,更大的意义在于我们可以使用.Net Framework提供的很多非常有用的internal组件,这些组件,MS出于各种原因标记为了internal,但是,既然提供了,我们就有理由去使用它,对于实现我们自己的组件时充分利用.Net Framework内置的这些组件而减少我们重复劳动的工作量也很有意义。


    使用演示:

     1using System;
     2using System.Collections.Generic;
     3using System.Reflection;
     4using System.Reflection.Emit;
     5using System.Text;
     6
     7namespace DynamicMethodProxyTest
     8{
     9    public class Program
    10    {
    11        //用于测试的静态方法
    12        public static void Add<T>(T obj, IList<T> list)
    13        {
    14            //list.Add同时也是用于测试的非静态方法
    15            list.Add(obj);
    16        }

    17
    18        private const int REPEAT_TIME = 20000000;
    19
    20        static void Main(string[] args)
    21        {
    22            //创建一个内置缓存支持的DynamicMethodProxyFactory实例
    23            NBear.DynamicMethodHelper.DynamicMethodProxyFactory fac = new NBear.DynamicMethodHelper.CachableDynamicMethodProxyFactory();
    24
    25            //创建一个internal的System.Web.HttpDictionary类实例
    26            Console.WriteLine("Create an instance of internal type - System.Web.HttpDictionary.");
    27            object temp = fac.CreateInstance(typeof(System.Web.HttpApplication).Module, "System.Web.HttpDictionary"falsefalse);
    28
    29            //创建访问该实例的SetValue和GetValue方法的DynamicMethosProxyDelegate
    30            Console.WriteLine("Create DynamicMethodProxyDelegate of HttpDictionary's SetValue and GetValue methods.");
    31            NBear.DynamicMethodHelper.DynamicMethodProxyDelegate setDelegate = fac.GetMethodDelegate(typeof(System.Web.HttpApplication).Module, temp.GetType().GetMethod("SetValue", BindingFlags.NonPublic | BindingFlags.Instance));
    32            NBear.DynamicMethodHelper.DynamicMethodProxyDelegate getDelegate = fac.GetMethodDelegate(typeof(System.Web.HttpApplication).Module, fac.GetMethodInfoBySignature(temp.GetType(), "System.Object GetValue(System.String)"falsefalse));
    33
    34            //在该实例上 Set & Get 测试数据
    35            Console.WriteLine("set \"test value\" on the internal type instance");
    36            setDelegate(temp, "test""test value");
    37            Console.WriteLine("get the test value from the internal type instance: " + getDelegate(temp, "test"));
    38
    39            //测试DynamicMethodProxyDelegate的性能
    40            Console.WriteLine("Test the performance of DynamicMethodProxyDelegate.");
    41            List<int> list = new List<int>();
    42            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
    43            watch.Reset();
    44            watch.Start();
    45            for (int i = 0; i < REPEAT_TIME; i++)
    46            {
    47                //这里是直接泛型调用
    48                Program.Add<int>(i, list);
    49            }

    50            watch.Stop();
    51            long l1 = watch.ElapsedMilliseconds;
    52            watch.Reset();
    53            MethodInfo mi = typeof(Program).GetMethod("Add");
    54            //创建一个静态方法的StaticDynamicMethodDelegate
    55            NBear.DynamicMethodHelper.StaticDynamicMethodProxyDelegate sdmd = fac.GetStaticMethodDelegate(mi, typeof(int));
    56            watch.Start();
    57            for (int i = 0; i < REPEAT_TIME; i++)
    58            {
    59                //通过StaticDynamicMethodDelegate以非泛型方式访问泛型方法
    60                sdmd(i, list);
    61            }

    62            watch.Stop();
    63            long l2 = watch.ElapsedMilliseconds;
    64            watch.Reset();
    65            MethodInfo mi2 = list.GetType().GetMethod("Add");
    66            //创建一个DynamicMethodDelegate访问同样的Add方法
    67            NBear.DynamicMethodHelper.DynamicMethodProxyDelegate dmd = fac.GetMethodDelegate(mi2);
    68            watch.Start();
    69            for (int i = 0; i < REPEAT_TIME; i++)
    70            {
    71                //通过DynamicMethodDelegate访问
    72                dmd(list, i);
    73            }

    74            watch.Stop();
    75            long l3 = watch.ElapsedMilliseconds;
    76            Console.WriteLine("{0}\nDirectly vs Static vs Non-static\n{1} vs {2} vs {3}", list.Count, l1, l2, l3);
    77            Console.ReadLine();
    78        }

    79    }

    80}


    下载测试代码和类库源码

  • 相关阅读:
    JS LeetCode 1423. 可获得的最大点数简单题解
    SpringBoot 学集 (第六章) Docker
    Linux 学记 (第三章)
    Linux 学记 (第二章)
    Linux 学记 (第一章)
    SpringBoot 学集 (第五章) Web开发续
    SpringBoot 学集 (第四章)Web开发
    SpringBoot 学集 (第三章) 日志框架
    SpringBoot 学集 (第二章) 配置文件
    SpringBoot 学集 (第一章)
  • 原文地址:https://www.cnblogs.com/teddyma/p/690946.html
Copyright © 2011-2022 走看看