• DynamicMethod应用例子实现实体类的对应属性的复制


    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection.Emit;
    using System.Reflection;

    namespace FastMapper
    {
        
    public delegate TTarget MapMethod<TTarget, TSource>(TSource source);


        
    public static class FastMapper<TTarget,TSource>
        {
            
    private static MapMethod<TTarget, TSource> mapMethod;
           
            
    public static MapMethod<TTarget, TSource> GetMapMethod()
            {
                
    if (mapMethod == null)
                {
                    mapMethod 
    = CreateMapMethod(typeof(TTarget), typeof(TSource));
                }
                
    return mapMethod;
            }

            
    public static TTarget Map(TSource source)
            {
                
    if (mapMethod == null)
                {
                    mapMethod 
    = CreateMapMethod(typeof(TTarget), typeof(TSource));
                }
                
    return mapMethod(source);     
            }

            
    private static MapMethod<TTarget, TSource> CreateMapMethod(Type targetType, Type sourceType)
            {


                DynamicMethod map 
    = new DynamicMethod("Map", targetType, new Type[] { sourceType }, typeof(TTarget).Module);

                ILGenerator il 
    = map.GetILGenerator();
                ConstructorInfo ci 
    = targetType.GetConstructor(new Type[0]);
                il.DeclareLocal(targetType);
                il.Emit(OpCodes.Newobj, ci);
                il.Emit(OpCodes.Stloc_0);
                
    foreach (var sourcePropertyInfo in sourceType.GetProperties())
                {
                    var targetPropertyInfo 
    = (from p in targetType.GetProperties()
                                              
    where p.Name == sourcePropertyInfo.Name && p.PropertyType == sourcePropertyInfo.PropertyType
                                              select p).FirstOrDefault();

                    
    if (targetPropertyInfo == nullcontinue;

                    il.Emit(OpCodes.Ldloc_0);
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Callvirt, sourcePropertyInfo.GetGetMethod());
                    il.Emit(OpCodes.Callvirt, targetPropertyInfo.GetSetMethod());

                }
                il.Emit(OpCodes.Ldloc_0);
                il.Emit(OpCodes.Ret);

                
    return (MapMethod<TTarget, TSource>)map.CreateDelegate(typeof(MapMethod<TTarget, TSource>));

            }
        }
    }


    下面是测试

    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection.Emit;
    using System.Reflection;
    using System.Diagnostics;
    using System.Linq.Expressions;
    namespace FastMapper
    {
        
    public class TargetModel 
        {
            
    public string Name { getset; }
            
    public int Age { getset; }
            
    public object Pic { getset; }
        }
        
    public class SourceModel
        {
            
    public string Name { getset; }
            
    public int Age { getset; }
            
    public object Pic { getset; }
        }

        
    class Program
        {
            
    static void Main(string[] args)
            {
                mytest();
                Console.ReadKey();

            }

            
    private static void mytest()
            {
                
    int count = 1000000;
                SourceModel source 
    = new SourceModel { Name = "xhan", Age = 33, Pic = new object() };


                
    long normal = Test1(count, source);
                Console.WriteLine(
    "Normal Map Time:{0}", normal);


                
    long faster = Test2(count, source);
                Console.WriteLine(
    "FastMapper Time:{0}", faster);

                Test3(count, source);
                Console.WriteLine((
    double)faster / normal);
            }
            
    private static long Test3(int count, SourceModel source)
            {
                Stopwatch stopwatch1 
    = new Stopwatch();
                stopwatch1.Start();
                
    for (int i = 0; i < count; i++)
                {
                    TargetModel target 
    = ExpMapper<TargetModel,SourceModel>.Map(source);
                    System.Diagnostics.Debug.Assert(target.Name 
    == source.Name);
                    System.Diagnostics.Debug.Assert(target.Age 
    == source.Age);
                    System.Diagnostics.Debug.Assert(target.Pic 
    == source.Pic);

                }
                stopwatch1.Stop();
                
    long faster = stopwatch1.ElapsedMilliseconds;
                Console.WriteLine(
    "ExpMapper Time:{0}", faster);
                
    return faster;
            }
           

            
    private static long Test1(int count, SourceModel source)
            {
                Stopwatch stopwatch 
    = new Stopwatch();
                stopwatch.Start();
                
    for (int i = 0; i < count; i++)
                {
                   TargetModel target 
    = NormalMap(source);
                   System.Diagnostics.Debug.Assert(target.Name 
    == source.Name);
                   System.Diagnostics.Debug.Assert(target.Age 
    == source.Age);
                   System.Diagnostics.Debug.Assert(target.Pic 
    == source.Pic);
                }
                stopwatch.Stop();

                
    long normal = stopwatch.ElapsedMilliseconds;
                
    return normal;
            }

            
    private static long Test2(int count, SourceModel source)
            {
                Stopwatch stopwatch1 
    = new Stopwatch();
                stopwatch1.Start();
                
    for (int i = 0; i < count; i++)
                {
                   TargetModel target 
    = FastMapper<TargetModel,SourceModel>.Map(source); 
                   
    //TargetModel target = mapper.Invoke(source);
                   System.Diagnostics.Debug.Assert(target.Name == source.Name);
                   System.Diagnostics.Debug.Assert(target.Age 
    == source.Age);
                   System.Diagnostics.Debug.Assert(target.Pic 
    == source.Pic);
                   
                }
                stopwatch1.Stop();
                
    long faster = stopwatch1.ElapsedMilliseconds;
                
    return faster;
            }
            
    public static TargetModel NormalMap(SourceModel source)
            {
                TargetModel target 
    = new TargetModel();
                target.Age 
    = source.Age;
                target.Name 
    = source.Name;
                target.Pic 
    = source.Pic;
                
    return target;
            }
            
        }
    }


    性能理论上和手写的复制一样!

  • 相关阅读:
    C语言函数名与函数指针详解
    在C语言中以编程的方式获取函数名
    Python 数据分析:Pandas 缺省值的判断
    手摸手教你如何在 Python 编码中做到小细节大优化
    如何在 Swoole 中优雅的实现 MySQL 连接池
    Python 数据分析:让你像写 Sql 语句一样,使用 Pandas 做数据分析
    Python 如何连接并操作 Aws 上 PB 级云数据仓库 Redshift
    Swoole 协程 MySQL 客户端与异步回调 MySQL 客户端的对比
    Protobuf 文件生成工具 Prototool 命令详解
    PHP 查看扩展信息的命令
  • 原文地址:https://www.cnblogs.com/xhan/p/1751515.html
Copyright © 2020-2023  润新知