反射的Emit实现(2)

考虑了一下,将字段实现给贴了出来,但是说实话,我琢磨不定哪一个是最佳方案(原因如下)。

 

ExpandedBlockStart.gif 代码
  public   class  User
    {
        
internal   string  _username;
        
public   string  Username {  get  {  return   this ._username; }  set  {  this ._username  =  value; } }

        
internal   int ?  _id;
        
public   int ?  ID {  get  {  return   this ._id; }  set  {  this ._id  =  value; } }
    }

 

 

 

也就是说,字段必须是internal属性。 囧~~

 

ExpandedBlockStart.gif 代码

    
public   class  FieldProperty < T >
    {
        
public   delegate   void  SetValueDelegateHandler(T owner,  object  value);
        
private   readonly  Type ParameterType  =   typeof ( object );

        
private  T _owner;
        
public  T Owner {  get  {  return   this ._owner; } }

        
private  Type _ownerType;

        
public  FieldProperty(T owner)
        {
            
this ._owner  =  owner;
            
this ._ownerType  =   typeof (T);
        }

        
private  Dictionary < int , SetValueDelegateHandler >  _cache  =   new  Dictionary < int , SetValueDelegateHandler > ();
        
public   void  SetPropertyValue( string  propertyName,  object  value)
        {
            SetValueDelegateHandler sv;
            
int  hashCode  =  propertyName.GetHashCode();
            
if  ( this ._cache.ContainsKey(hashCode))
            {
                sv  =   this ._cache[hashCode];
            }
            
else
            {

                
string  fieldName  =   " _ "   +  propertyName;

                var filedInfo  =   this ._ownerType.GetField(fieldName, BindingFlags.Instance  |  BindingFlags.IgnoreCase  |  BindingFlags.Public  |  BindingFlags.NonPublic);

                
//  创建动态函数
                DynamicMethod method  =   new  DynamicMethod( " EmitCallable " null new  Type[] {  this ._ownerType, ParameterType },  this ._ownerType.Module);
                
//  获取动态函数的 IL 生成器
                var il  =  method.GetILGenerator();
                
//  创建一个本地变量,主要用于 Object Type to Propety Type
                var local  =  il.DeclareLocal(filedInfo.FieldType,  true );
                
//  加载第 2 个参数【(T owner, object value)】的 value
                il.Emit(OpCodes.Ldarg_1);
                
if  (filedInfo.FieldType.IsValueType)
                {
                    il.Emit(OpCodes.Unbox_Any, filedInfo.FieldType); //  如果是值类型,拆箱 string = (string)object;
                }
                
else
                {
                    il.Emit(OpCodes.Castclass, filedInfo.FieldType); //  如果是引用类型,转换 Class = object as Class
                }

                il.Emit(OpCodes.Stloc, local); //  将上面的拆箱或转换,赋值到本地变量,现在这个本地变量是一个与目标函数相同数据类型的字段了。
                il.Emit(OpCodes.Ldarg_0);    //  加载第一个参数 owner
                il.Emit(OpCodes.Ldloc, local); //  加载本地参数
                il.Emit(OpCodes.Stfld, filedInfo); // 调用字段,新值赋予旧值
                il.Emit(OpCodes.Ret);    //  返回
                 /*  生成的动态函数类似:
                 * void EmitCallable(T owner, object value)
                 * {
                 *     T local = (T)value;
                 *     owner.Field = local;
                 * }
                 
*/
                sv  =  method.CreateDelegate( typeof (SetValueDelegateHandler))  as  SetValueDelegateHandler;
                
this ._cache.Add(hashCode, sv);
            }

            sv( this ._owner, value);
        }
    }

 

 

 

转载于:https://www.cnblogs.com/sofire/archive/2010/06/10/1755415.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值