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;
        }
        
    }
}


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

原文地址:https://www.cnblogs.com/xhan/p/1751515.html