考虑了一下,将字段实现给贴了出来,但是说实话,我琢磨不定哪一个是最佳方案(原因如下)。
代码
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 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 " , 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);
}
}
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);
}
}