一个生成接口方法代理的Emit代码,支持泛型方法.
由于该方法是针对自需求编写的,所以不一定适合你的需要,但对于想学习的朋友可以作一个参考.
private void MethodGenerator(ILGenerator il, MethodInfo method)
{
Type[] types = GetParameterTypes(method.GetParameters());
Type[] gtypes;
MethodInfo callmethod;
il.DeclareLocal(typeof(MethodBase));
il.DeclareLocal(typeof(object[]));
bool isvoid = method.ReturnType.ToString() == "System.Void";
if (!isvoid)//定义返回值变量
{
il.DeclareLocal(GetType(method.ReturnType));
}
il.DeclareLocal(typeof(object[]));
il.DeclareLocal(typeof(Type[]));
il.Emit(OpCodes.Nop);
callmethod = typeof(MethodBase).GetMethod("GetCurrentMethod", new Type[0]);
il.Emit(OpCodes.Call, callmethod);
il.Emit(OpCodes.Stloc_0);//把调用GetCurrentMethod的返回值封送到局部变量0里
AddGenericTypes
if (types.Length > 0)//存在方法参数
{
il.Emit(OpCodes.Ldc_I4, types.Length);//加载数组长度
il.Emit(OpCodes.Newarr, typeof(object));//定义数组,并保存以下局部变量中
if (!isvoid)
il.Emit(OpCodes.Stloc_3);
else
il.Emit(OpCodes.Stloc_2);
for (int i = 0; i < types.Length; i++)//将参数加载到局部变量数组里面
{
if (!isvoid)
il.Emit(OpCodes.Ldloc_3);
else
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldarg, i + 1);
if (types[i].IsValueType || types[i].IsGenericParameter || types[i].IsGenericType)
{
//是值类型,泛型参,泛型拖进来打包装箱
il.Emit(OpCodes.Box, GetType(types[i]));
}
il.Emit(OpCodes.Stelem_Ref);
}
if (!isvoid)//加载相关局部变量
il.Emit(OpCodes.Ldloc_3);
else
il.Emit(OpCodes.Ldloc_2);
}
else
{
il.Emit(OpCodes.Ldnull);
}
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldloc_0);//加载method类型变量
if (!isvoid)//加载泛型类型数组变量
il.Emit(OpCodes.Ldloc_S, 4);
else
il.Emit(OpCodes.Ldloc_3);
il.Emit(OpCodes.Ldloc_1);//加载参数数组变量
callmethod = typeof(Context).GetMethod("CallMethod", new Type[] { typeof(MethodBase),typeof(Type[]), typeof(object[]) });
il.Emit(OpCodes.Call, callmethod);//把方法参数和相关信息扔到一个上下文方法处理
if (!isvoid)
{
if (method.ReturnType.IsValueType || method.ReturnType.IsGenericType|| method.ReturnType.IsGenericParameter)
{
//是值类型,泛型参,泛型拖进来脱衣服
il.Emit(OpCodes.Unbox_Any,GetType(method.ReturnType));
}
else
{
il.Emit(OpCodes.Castclass, method.ReturnType);
}
il.Emit(OpCodes.Stloc_2);
il.Emit(OpCodes.Ldloc_2);
}
else
{
il.Emit(OpCodes.Pop);
}
il.Emit(OpCodes.Ret);
}
{
Type[] types = GetParameterTypes(method.GetParameters());
Type[] gtypes;
MethodInfo callmethod;
il.DeclareLocal(typeof(MethodBase));
il.DeclareLocal(typeof(object[]));
bool isvoid = method.ReturnType.ToString() == "System.Void";
if (!isvoid)//定义返回值变量
{
il.DeclareLocal(GetType(method.ReturnType));
}
il.DeclareLocal(typeof(object[]));
il.DeclareLocal(typeof(Type[]));
il.Emit(OpCodes.Nop);
callmethod = typeof(MethodBase).GetMethod("GetCurrentMethod", new Type[0]);
il.Emit(OpCodes.Call, callmethod);
il.Emit(OpCodes.Stloc_0);//把调用GetCurrentMethod的返回值封送到局部变量0里
AddGenericTypes
if (types.Length > 0)//存在方法参数
{
il.Emit(OpCodes.Ldc_I4, types.Length);//加载数组长度
il.Emit(OpCodes.Newarr, typeof(object));//定义数组,并保存以下局部变量中
if (!isvoid)
il.Emit(OpCodes.Stloc_3);
else
il.Emit(OpCodes.Stloc_2);
for (int i = 0; i < types.Length; i++)//将参数加载到局部变量数组里面
{
if (!isvoid)
il.Emit(OpCodes.Ldloc_3);
else
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldarg, i + 1);
if (types[i].IsValueType || types[i].IsGenericParameter || types[i].IsGenericType)
{
//是值类型,泛型参,泛型拖进来打包装箱
il.Emit(OpCodes.Box, GetType(types[i]));
}
il.Emit(OpCodes.Stelem_Ref);
}
if (!isvoid)//加载相关局部变量
il.Emit(OpCodes.Ldloc_3);
else
il.Emit(OpCodes.Ldloc_2);
}
else
{
il.Emit(OpCodes.Ldnull);
}
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldloc_0);//加载method类型变量
if (!isvoid)//加载泛型类型数组变量
il.Emit(OpCodes.Ldloc_S, 4);
else
il.Emit(OpCodes.Ldloc_3);
il.Emit(OpCodes.Ldloc_1);//加载参数数组变量
callmethod = typeof(Context).GetMethod("CallMethod", new Type[] { typeof(MethodBase),typeof(Type[]), typeof(object[]) });
il.Emit(OpCodes.Call, callmethod);//把方法参数和相关信息扔到一个上下文方法处理
if (!isvoid)
{
if (method.ReturnType.IsValueType || method.ReturnType.IsGenericType|| method.ReturnType.IsGenericParameter)
{
//是值类型,泛型参,泛型拖进来脱衣服
il.Emit(OpCodes.Unbox_Any,GetType(method.ReturnType));
}
else
{
il.Emit(OpCodes.Castclass, method.ReturnType);
}
il.Emit(OpCodes.Stloc_2);
il.Emit(OpCodes.Ldloc_2);
}
else
{
il.Emit(OpCodes.Pop);
}
il.Emit(OpCodes.Ret);
}