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

ExpandedBlockStart.gif 代码
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  ==   null continue ;

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

        }
    }
}


下面是测试

ExpandedBlockStart.gif 代码
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 {  get set ; }
        
public   int  Age {  get set ; }
        
public   object  Pic {  get set ; }
    }
    
public   class  SourceModel
    {
        
public   string  Name {  get set ; }
        
public   int  Age {  get set ; }
        
public   object  Pic {  get set ; }
    }

    
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/archive/2010/06/04/1751515.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值