public class FastProperty<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 FastProperty(T owner)
{
this._owner = owner;
this._ownerType = typeof(T);
}
public SetValueDelegateHandler SetPropertyValue(string propertyName, object value)
{ // 指定函数名
string methodName = "set_" + propertyName;
// 搜索函数,不区分大小写 IgnoreCase
var callMethod = this._ownerType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic);
// 获取参数
var para = callMethod.GetParameters()[0];
// 创建动态函数
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(para.ParameterType, true);
// 加载第 2 个参数【(T owner, object value)】的 value
il.Emit(OpCodes.Ldarg_1);
if (para.ParameterType.IsValueType)
{
il.Emit(OpCodes.Unbox_Any, para.ParameterType);// 如果是值类型,拆箱 string = (string)object;
}
else
{
il.Emit(OpCodes.Castclass, para.ParameterType);// 如果是引用类型,转换 Class = object as Class
}
il.Emit(OpCodes.Stloc, local);// 将上面的拆箱或转换,赋值到本地变量,现在这个本地变量是一个与目标函数相同数据类型的字段了。
il.Emit(OpCodes.Ldarg_0); // 加载第一个参数 owner
il.Emit(OpCodes.Ldloc, local);// 加载本地参数
il.EmitCall(OpCodes.Callvirt, callMethod, null);//调用函数
il.Emit(OpCodes.Ret); // 返回
/* 生成的动态函数类似:
* void EmitCallable(T owner, object value)
* {
* T local = (T)value;
* owner.Method(local);
* }
*/
return method.CreateDelegate(typeof(SetValueDelegateHandler)) as SetValueDelegateHandler;
}
}详情:http://www.cnblogs.com/mrlen/archive/2010/06/10/1755357.html
这个方法可以访问非私有的函数或属性。
可是对于私有属性就无能为力了。我这里有 3.5 才有 LINQ 方式。可是我希望是基于 2.0 实现的。不知道上面有哪个地方需要“改”?好久没有发200分的帖子了……可用分一直很少。都不敢发问。囧~~~~
{
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 FastProperty(T owner)
{
this._owner = owner;
this._ownerType = typeof(T);
}
public SetValueDelegateHandler SetPropertyValue(string propertyName, object value)
{ // 指定函数名
string methodName = "set_" + propertyName;
// 搜索函数,不区分大小写 IgnoreCase
var callMethod = this._ownerType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic);
// 获取参数
var para = callMethod.GetParameters()[0];
// 创建动态函数
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(para.ParameterType, true);
// 加载第 2 个参数【(T owner, object value)】的 value
il.Emit(OpCodes.Ldarg_1);
if (para.ParameterType.IsValueType)
{
il.Emit(OpCodes.Unbox_Any, para.ParameterType);// 如果是值类型,拆箱 string = (string)object;
}
else
{
il.Emit(OpCodes.Castclass, para.ParameterType);// 如果是引用类型,转换 Class = object as Class
}
il.Emit(OpCodes.Stloc, local);// 将上面的拆箱或转换,赋值到本地变量,现在这个本地变量是一个与目标函数相同数据类型的字段了。
il.Emit(OpCodes.Ldarg_0); // 加载第一个参数 owner
il.Emit(OpCodes.Ldloc, local);// 加载本地参数
il.EmitCall(OpCodes.Callvirt, callMethod, null);//调用函数
il.Emit(OpCodes.Ret); // 返回
/* 生成的动态函数类似:
* void EmitCallable(T owner, object value)
* {
* T local = (T)value;
* owner.Method(local);
* }
*/
return method.CreateDelegate(typeof(SetValueDelegateHandler)) as SetValueDelegateHandler;
}
}详情:http://www.cnblogs.com/mrlen/archive/2010/06/10/1755357.html
这个方法可以访问非私有的函数或属性。
可是对于私有属性就无能为力了。我这里有 3.5 才有 LINQ 方式。可是我希望是基于 2.0 实现的。不知道上面有哪个地方需要“改”?好久没有发200分的帖子了……可用分一直很少。都不敢发问。囧~~~~
不是我是希望这么赋值:我有一个 object 实例,我不知道它的类型。
public void SetValue(object target,string propertyName,object value)
{
动态调用 t = new 动态调用(target);
t.SetValue(propertyName,value);
}
听说“Emit”什么都可以。所以我就想问问方法。
{
public string Username { get; private set;}
}
{
TestClass obj = new TestClass();
FastProperty<TestClass> fp = new FastProperty<TestClass>(obj);
fp.SetPropertyValue2("Value", 5000);
Console.ReadKey();
}public static void SetPropertyValue2(object Owner, string propertyName, object value)
{
PropertyInfo[] pis = Owner.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (PropertyInfo pi in pis)
{
if (pi.Name == propertyName)
{
pi.SetValue(Owner, value, null);
}
}
}public class TestClass
{
private int _value = 500;
private int Value
{
get
{
return _value;
}
set
{
_value = value;
Console.WriteLine("Value changed! New value is " + value.ToString());
}
}
}
static void Main(string[] args)
{
//声明自定义类型,实例化
TestClass obj = new TestClass();
//调用静态方法设置值
SetNonePublicPropertyValue(obj, "Value", 5000);
Console.ReadKey();
}/// <summary>
/// 设置Protected/Private类型的属性值
/// </summary>
/// <param name="Owner">要设置的对象</param>
/// <param name="propertyName">属性名</param>
/// <param name="value">值</param>
public static void SetNonePublicPropertyValue(object Owner, string propertyName, object value)
{
//获取非公开的成员属性
PropertyInfo pi = Owner.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance);
if (pi != null)//如果获取到了,说明你调用没错
{
pi.SetValue(Owner, value, null);//设置值,这个最后一个属性,是索引值,如果属性本身是Array或List,这里要写索引编号或索引器要求的值。
}
}
上次那个方法不可以么?
可以的。上次的方法是完全可以的。但是 Linq 是在 3.5 实现的。2.0是无法实现的。
测试例子: using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;namespace CSharpConsole06
{
class Program
{
static void Main(string[] args)
{
//声明自定义类型,实例化
TestClass obj = new TestClass();
//调用静态方法设置值
FastProperty<TestClass> fp = new FastProperty<TestClass>(obj);
FastPropertyBufferd<TestClass> fp2 = new FastPropertyBufferd<TestClass>(obj, "Value");
int tick = Environment.TickCount;
for (int i = 0; i < 100000; i++)
{
fp.SetPropertyValue("Value", 5000).Invoke(obj, 5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("FastProperty".PadRight(20) + " : " + tick.ToString());
tick = Environment.TickCount;
for (int i = 0; i < 100000; i++)
{
fp2.SetValue(5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("FastPropertyBufferd".PadRight(20) + " : " + tick);
tick = Environment.TickCount;
for (int i = 0; i < 100000; i++)
{
SetNonePublicPropertyValue(obj, "Value", 5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("Direct reflect".PadRight(20) + " : " + tick);
Console.ReadKey();
} public class TestClass
{
private int _value = 500;
public int Value
{
get
{
return _value;
}
set
{
_value = value;
//Console.WriteLine("Value changed! New value is " + value.ToString());
}
}
} /// <summary>
/// 设置Protected/Private类型的属性值
/// </summary>
/// <param name="Owner">要设置的对象</param>
/// <param name="propertyName">属性名</param>
/// <param name="value">值</param>
public static void SetNonePublicPropertyValue(object Owner, string propertyName, object value)
{
Owner.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).ToList().ForEach(p => Console.WriteLine(p.Name));
//获取非公开的成员属性
PropertyInfo pi = Owner.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Default);
if (pi != null)//如果获取到了,说明你调用没错
{
pi.SetValue(Owner, value, null);//设置值,这个最后一个属性,是索引值,如果属性本身是Array或List,这里要写索引编号或索引器要求的值。
}
} /// <summary>
/// 缓存反射结果的类,提高访问速度
/// </summary>
/// <typeparam name="T">类型</typeparam>
public class FastPropertyBufferd<T>
{
private T _owner = default(T);
MethodInfo mi = null;
public FastPropertyBufferd(T owner,string propertyName)
{
_owner = owner;
mi = typeof(T).GetMethod("set_" + propertyName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic);
}
public void SetValue(object value)
{
mi.Invoke(_owner, new object[] { value });
}
} public class FastProperty<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 FastProperty(T owner)
{
this._owner = owner;
this._ownerType = typeof(T);
} public void SetPropertyValue2(string propertyName, object value)
{
PropertyInfo[] pis = Owner.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (PropertyInfo pi in pis)
{
if (pi.Name == propertyName)
{
pi.SetValue(Owner, value, null);
}
}
} public SetValueDelegateHandler SetPropertyValue(string propertyName, object value)
{
// 指定函数名
string methodName = "set_" + propertyName;
// 搜索函数,不区分大小写 IgnoreCase
var callMethod = this._ownerType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic);
// 获取参数
var para = callMethod.GetParameters()[0];
// 创建动态函数
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(para.ParameterType, true);
// 加载第 2 个参数【(T owner, object value)】的 value
il.Emit(OpCodes.Ldarg_1);
if (para.ParameterType.IsValueType)
{
il.Emit(OpCodes.Unbox_Any, para.ParameterType);// 如果是值类型,拆箱 string = (string)object;
}
else
{
il.Emit(OpCodes.Castclass, para.ParameterType);// 如果是引用类型,转换 Class = object as Class
}
il.Emit(OpCodes.Stloc, local);// 将上面的拆箱或转换,赋值到本地变量,现在这个本地变量是一个与目标函数相同数据类型的字段了。
il.Emit(OpCodes.Ldarg_0); // 加载第一个参数 owner
il.Emit(OpCodes.Ldloc, local);// 加载本地参数
il.EmitCall(OpCodes.Callvirt, callMethod, null);//调用函数
il.Emit(OpCodes.Ret); // 返回
/* 生成的动态函数类似:
* void EmitCallable(T owner, object value)
* {
* T local = (T)value;
* owner.Method(local);
* }
*/
return method.CreateDelegate(typeof(SetValueDelegateHandler)) as SetValueDelegateHandler;
}
}
}
}测试结果:FastProperty : 14618
FastPropertyBufferd : 187
Direct reflect : 172
for (int i = 0; i < 100000; i++)
{
setter(obj, 5000);
}我的结果:
FastProperty : 15
FastPropertyBufferd : 531
Direct reflect : 218
System.Reflection.PropertyInfo p = typeof(T).GetProperty("P", ystem.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);//创建get,set委托
T t = new T();
Func<object> PGet = Delegate.CreateDelegate(typeof(Func<object>), t, p.GetGetMethod(true)) as Func<object>;
Action<object> PSet = Delegate.CreateDelegate(typeof(Action<object>), t, p.GetSetMethod(true)) as Action<object>;//访问属性
PSet(new object());
object o = PGet();
如gomoku所说,那样测试的确有点不合适。
多谢guoyichao的提醒,这样的确很快。
重新修改了测试例子:using System;
using System.Reflection;
using System.Reflection.Emit;class Program
{
static void Main(string[] args)
{
//声明自定义类型,实例化
TestClass obj = new TestClass();
//调用静态方法设置值
FastProperty<TestClass> fp = new FastProperty<TestClass>(obj);
FastPropertyBufferd<TestClass> fp2 = new FastPropertyBufferd<TestClass>(obj, "Value");
int tick = Environment.TickCount;
FastProperty<TestClass>.SetValueDelegateHandler setter = fp.SetPropertyValue("Value", 5000);
for (int i = 0; i < 1000000; i++)
{
setter.Invoke(obj, 5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("FastProperty".PadRight(20) + " : " + tick.ToString());
tick = Environment.TickCount;
for (int i = 0; i < 1000000; i++)
{
fp2.SetValue(5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("FastPropertyBufferd".PadRight(20) + " : " + tick);
tick = Environment.TickCount;
for (int i = 0; i < 1000000; i++)
{
SetNonePublicPropertyValue(obj, "Value", 5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("Direct reflect".PadRight(20) + " : " + tick);
tick = Environment.TickCount;
SetValueHandler del = Delegate.CreateDelegate(typeof(SetValueHandler),obj, "set_Value") as SetValueHandler;
for (int i = 0; i < 1000000; i++)
{
del(5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("CreateDelegate reflect".PadRight(20) + " : " + tick);
Console.ReadKey();
} delegate void SetValueHandler(Int32 value); public class TestClass
{
private int _value = 500;
public int Value
{
get
{
return _value;
}
set
{
_value = value;
//Console.WriteLine("Value changed! New value is " + value.ToString());
}
}
} /// <summary>
/// 设置Protected/Private类型的属性值
/// </summary>
/// <param name="Owner">要设置的对象</param>
/// <param name="propertyName">属性名</param>
/// <param name="value">值</param>
public static void SetNonePublicPropertyValue(object Owner, string propertyName, object value)
{
//Owner.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).ToList().ForEach(p => Console.WriteLine(p.Name));
//获取非公开的成员属性
PropertyInfo pi = Owner.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Default);
if (pi != null)//如果获取到了,说明你调用没错
{
pi.SetValue(Owner, value, null);//设置值,这个最后一个属性,是索引值,如果属性本身是Array或List,这里要写索引编号或索引器要求的值。
}
} /// <summary>
/// 缓存反射结果的类,提高访问速度
/// </summary>
/// <typeparam name="T">类型</typeparam>
public class FastPropertyBufferd<T>
{
private T _owner = default(T);
MethodInfo mi = null;
public FastPropertyBufferd(T owner, string propertyName)
{
_owner = owner;
mi = typeof(T).GetMethod("set_" + propertyName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic);
}
public void SetValue(object value)
{
mi.Invoke(_owner, new object[] { value });
}
} public class FastProperty<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 FastProperty(T owner)
{
this._owner = owner;
this._ownerType = typeof(T);
} public void SetPropertyValue2(string propertyName, object value)
{
PropertyInfo[] pis = Owner.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (PropertyInfo pi in pis)
{
if (pi.Name == propertyName)
{
pi.SetValue(Owner, value, null);
}
}
} public SetValueDelegateHandler SetPropertyValue(string propertyName, object value)
{
// 指定函数名
string methodName = "set_" + propertyName;
// 搜索函数,不区分大小写 IgnoreCase
MethodInfo callMethod = this._ownerType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic);
// 获取参数
ParameterInfo para = callMethod.GetParameters()[0];
// 创建动态函数
DynamicMethod method = new DynamicMethod("EmitCallable", null, new Type[] { this._ownerType, ParameterType }, this._ownerType.Module);
// 获取动态函数的 IL 生成器
ILGenerator il = method.GetILGenerator();
// 创建一个本地变量,主要用于 Object Type to Propety Type
LocalBuilder local = il.DeclareLocal(para.ParameterType, true);
// 加载第 2 个参数【(T owner, object value)】的 value
il.Emit(OpCodes.Ldarg_1);
if (para.ParameterType.IsValueType)
{
il.Emit(OpCodes.Unbox_Any, para.ParameterType);// 如果是值类型,拆箱 string = (string)object;
}
else
{
il.Emit(OpCodes.Castclass, para.ParameterType);// 如果是引用类型,转换 Class = object as Class
}
il.Emit(OpCodes.Stloc, local);// 将上面的拆箱或转换,赋值到本地变量,现在这个本地变量是一个与目标函数相同数据类型的字段了。
il.Emit(OpCodes.Ldarg_0); // 加载第一个参数 owner
il.Emit(OpCodes.Ldloc, local);// 加载本地参数
il.EmitCall(OpCodes.Callvirt, callMethod, null);//调用函数
il.Emit(OpCodes.Ret); // 返回
/* 生成的动态函数类似:
* void EmitCallable(T owner, object value)
* {
* T local = (T)value;
* owner.Method(local);
* }
*/
return method.CreateDelegate(typeof(SetValueDelegateHandler)) as SetValueDelegateHandler;
}
}
}
结果:FastProperty : 47
FastPropertyBufferd : 4618
Direct reflect : 452
CreateDelegate reflect : 16
DynamicMethod method = new DynamicMethod("EmitCallable", null, new Type[] { this._ownerType, ParameterType }, this._ownerType.Module, true);
加上的true意味着跳过检查(skipVisibility),然后私有/非私有就都可以访问了。另:23楼guoyichao的方法有个局限,Func<object>不能推广到Func<T>的情况,除非显式指定属性的类型T。
各位大大帮帮忙,小弟困绕很久了。
{
Type type = obj.GetType();
PropertyInfo p = type.GetProperty(propertyName);
p.SetValue(obj, value, null);
}
{
Type type = obj.GetType();
PropertyInfo p = type.GetProperty(propertyName);
p.SetValue(obj, value, null);
}
后来我又有更好的办法了。如果只是针对 ORM,特别注重效率的话,还是需要 switch + Delegate.CreateDelegate,虽然目前框架中没有使用这个策略,但是我相信这个方式使得 ORM 的性能损耗降到最低!
就可以了,返回的是FastInvokeHandler委托。public delegate object FastInvokeHandler(object target, object[] paramters);
可惜如果是Field就无能为力了,不过这种情况比较少。
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;namespace CSharpConsole06
{
class Program
{
static void Main(string[] args)
{
//声明自定义类型,实例化
TestClass obj = new TestClass();
//调用静态方法设置值
FastProperty<TestClass> fp = new FastProperty<TestClass>(obj);
FastPropertyBufferd<TestClass> fp2 = new FastPropertyBufferd<TestClass>(obj, "Value");
int tick = Environment.TickCount;
for (int i = 0; i < 100000; i++)
{
fp.SetPropertyValue("Value", 5000).Invoke(obj, 5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("FastProperty".PadRight(20) + " : " + tick.ToString());
tick = Environment.TickCount;
for (int i = 0; i < 100000; i++)
{
fp2.SetValue(5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("FastPropertyBufferd".PadRight(20) + " : " + tick);
tick = Environment.TickCount;
for (int i = 0; i < 100000; i++)
{
SetNonePublicPropertyValue(obj, "Value", 5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("Direct reflect".PadRight(20) + " : " + tick);
Console.ReadKey();
} public class TestClass
{
private int _value = 500;
public int Value
{
get
{
return _value;
}
set
{
_value = value;
//Console.WriteLine("Value changed! New value is " + value.ToString());
}
}
} /// <summary>
/// 设置Protected/Private类型的属性值
/// </summary>
/// <param name="Owner">要设置的对象</param>
/// <param name="propertyName">属性名</param>
/// <param name="value">值</param>
public static void SetNonePublicPropertyValue(object Owner, string propertyName, object value)
{
Owner.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).ToList().ForEach(p => Console.WriteLine(p.Name));
//获取非公开的成员属性
PropertyInfo pi = Owner.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Default);
if (pi != null)//如果获取到了,说明你调用没错
{
pi.SetValue(Owner, value, null);//设置值,这个最后一个属性,是索引值,如果属性本身是Array或List,这里要写索引编号或索引器要求的值。
}
} /// <summary>
/// 缓存反射结果的类,提高访问速度
/// </summary>
/// <typeparam name="T">类型</typeparam>
public class FastPropertyBufferd<T>
{
private T _owner = default(T);
MethodInfo mi = null;
public FastPropertyBufferd(T owner,string propertyName)
{
_owner = owner;
mi = typeof(T).GetMethod("set_" + propertyName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic);
}
public void SetValue(object value)
{
mi.Invoke(_owner, new object[] { value });
}
} public class FastProperty<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 FastProperty(T owner)
{
this._owner = owner;
this._ownerType = typeof(T);
} public void SetPropertyValue2(string propertyName, object value)
{
PropertyInfo[] pis = Owner.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (PropertyInfo pi in pis)
{
if (pi.Name == propertyName)
{
pi.SetValue(Owner, value, null);
}
}
} public SetValueDelegateHandler SetPropertyValue(string propertyName, object value)
{
// 指定函数名
string methodName = "set_" + propertyName;
// 搜索函数,不区分大小写 IgnoreCase
var callMethod = this._ownerType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic);
// 获取参数
var para = callMethod.GetParameters()[0];
// 创建动态函数
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(para.ParameterType, true);
// 加载第 2 个参数【(T owner, object value)】的 value
il.Emit(OpCodes.Ldarg_1);
if (para.ParameterType.IsValueType)
{
il.Emit(OpCodes.Unbox_Any, para.ParameterType);// 如果是值类型,拆箱 string = (string)object;
}
else
{
il.Emit(OpCodes.Castclass, para.ParameterType);// 如果是引用类型,转换 Class = object as Class
}
il.Emit(OpCodes.Stloc, local);// 将上面的拆箱或转换,赋值到本地变量,现在这个本地变量是一个与目标函数相同数据类型的字段了。
il.Emit(OpCodes.Ldarg_0); // 加载第一个参数 owner
il.Emit(OpCodes.Ldloc, local);// 加载本地参数
il.EmitCall(OpCodes.Callvirt, callMethod, null);//调用函数
il.Emit(OpCodes.Ret); // 返回
/* 生成的动态函数类似:
* void EmitCallable(T owner, object value)
* {
* T local = (T)value;
* owner.Method(local);
* }
*/
return method.CreateDelegate(typeof(SetValueDelegateHandler)) as SetValueDelegateHandler;
}
}
}
}