反射的Emit实现(2)

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

 

代码
 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属性。 囧~~

 

代码

    
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"nullnew 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);
        }
    }

 

 

 

posted @ 2010-06-10 11:14  Treenew Lyn  阅读(947)  评论(3编辑  收藏  举报