void AddRpc(TypeDefinition newType, MethodDefinition irpc) { var tag = irpc.CustomAttributes.FirstOrDefault(x => x.AttributeType.Name == "TAG"); if (tag is null) { return; } var cmdx = tag.ConstructorArguments.First().Value; var cmd = 0; switch (cmdx) { case Mono.Cecil.CustomAttributeArgument args: cmd = (int)args.Value; break; default: cmd = (int)cmdx; break; } var method = new MethodDefinition(irpc.Name, MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final, irpc.ReturnType); var il = method.Body.GetILProcessor(); var parameters = irpc.Parameters; var paramTypes = ParamTypes(parameters.ToArray(), false); for (int i = 0; i < paramTypes.Length; i++) { method.Parameters.Add(new ParameterDefinition(parameters[i].Name, parameters[i].Attributes, paramTypes[i])); } if (irpc.ContainsGenericParameter) { throw new Exception($"not have generic parameter{irpc.FullName}"); } var returntype = irpc.ReturnType; if (returntype.IsGenericInstance) { var genreturntype = returntype as GenericInstanceType; if (genreturntype.Name != "Task`1") { throw new Exception($"return type error:{genreturntype.FullName}"); } if (genreturntype.GenericArguments[0].Name == "IResult") { ParametersArray args = new ParametersArray(this, il, paramTypes); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, obj); il.Emit(OpCodes.Ldc_I4, cmd); GenericArray <object> argsArr = new GenericArray <object>(this, il, ParamTypes(parameters.ToArray(), true).Length); for (int i = 0; i < parameters.Count; i++) { // args[i] = argi; if (!parameters[i].IsOut) { argsArr.BeginSet(i); args.Get(i); argsArr.EndSet(parameters[i].ParameterType); } } argsArr.Load(); var asyncAction = obj.FieldType.Resolve().Methods.First(p => p.Name == "AsyncFunc"); il.Emit(OpCodes.Callvirt, ModuleDefinition.ImportReference(asyncAction)); il.Emit(OpCodes.Ret); newType.Methods.Add(method); } else { ParametersArray args = new ParametersArray(this, il, paramTypes); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, obj); il.Emit(OpCodes.Ldc_I4, cmd); GenericArray <object> argsArr = new GenericArray <object>(this, il, ParamTypes(parameters.ToArray(), true).Length); for (int i = 0; i < parameters.Count; i++) { // args[i] = argi; if (!parameters[i].IsOut) { argsArr.BeginSet(i); args.Get(i); argsArr.EndSet(parameters[i].ParameterType); } } argsArr.Load(); var genericAsyncFunc = obj.FieldType.Resolve().Methods.First(p => p.Name == "AsyncFunc" && p.CallingConvention == MethodCallingConvention.Generic); il.Emit(OpCodes.Callvirt, ModuleDefinition.ImportReference(MakeGenericInstanceMethod(genericAsyncFunc, genreturntype.GenericArguments.ToArray()))); il.Emit(OpCodes.Ret); newType.Methods.Add(method); } } else if (returntype.FullName == "System.Void") { ParametersArray args = new ParametersArray(this, il, paramTypes); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, obj); il.Emit(OpCodes.Ldc_I4, cmd); GenericArray <object> argsArr = new GenericArray <object>(this, il, ParamTypes(parameters.ToArray(), true).Length); for (int i = 0; i < parameters.Count; i++) { // args[i] = argi; if (!parameters[i].IsOut) { argsArr.BeginSet(i); args.Get(i); argsArr.EndSet(parameters[i].ParameterType); } } argsArr.Load(); var Action = obj.FieldType.Resolve().Methods.First(p => p.Name == "Action"); il.Emit(OpCodes.Callvirt, ModuleDefinition.ImportReference(Action)); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ret); newType.Methods.Add(method); } else if (returntype.FullName == "System.Threading.Tasks.Task") { ParametersArray args = new ParametersArray(this, il, paramTypes); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, obj); il.Emit(OpCodes.Ldc_I4, cmd); GenericArray <object> argsArr = new GenericArray <object>(this, il, ParamTypes(parameters.ToArray(), true).Length); for (int i = 0; i < parameters.Count; i++) { // args[i] = argi; if (!parameters[i].IsOut) { argsArr.BeginSet(i); args.Get(i); argsArr.EndSet(parameters[i].ParameterType); } } argsArr.Load(); var asyncAction = obj.FieldType.Resolve().Methods.First(p => p.Name == "AsyncAction"); il.Emit(OpCodes.Callvirt, ModuleDefinition.ImportReference(asyncAction)); il.Emit(OpCodes.Ret); newType.Methods.Add(method); } else { ParametersArray args = new ParametersArray(this, il, paramTypes); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, obj); il.Emit(OpCodes.Ldc_I4, cmd); il.Emit(OpCodes.Ldtoken, irpc.ReturnType); var ptype = ModuleDefinition.ImportReference(GetMethodInfo.GetTypeofHandler()); il.Emit(OpCodes.Call, ptype); GenericArray <object> argsArr = new GenericArray <object>(this, il, ParamTypes(parameters.ToArray(), true).Length); for (int i = 0; i < parameters.Count; i++) { // args[i] = argi; if (!parameters[i].IsOut) { argsArr.BeginSet(i); args.Get(i); argsArr.EndSet(parameters[i].ParameterType); } } argsArr.Load(); var func = obj.FieldType.Resolve().Methods.First(p => p.Name == "Func"); il.Emit(OpCodes.Callvirt, ModuleDefinition.ImportReference(func)); var res = new VariableDefinition(irpc.ReturnType); method.Body.Variables.Add(res); Convert(il, ModuleDefinition.ImportReference(typeof(object)), irpc.ReturnType, false); il.Emit(OpCodes.Stloc, res); il.Emit(OpCodes.Ldloc, res); il.Emit(OpCodes.Ret); newType.Methods.Add(method); } }
private void AddMethodImpl(MethodInfo mi) { ParameterInfo[] parameters = mi.GetParameters(); Type[] paramTypes = ParamTypes(parameters, false); MethodBuilder mdb = _tb.DefineMethod(mi.Name, MethodAttributes.Public | MethodAttributes.Virtual, mi.ReturnType, paramTypes); if (mi.ContainsGenericParameters) { Type[] ts = mi.GetGenericArguments(); string[] ss = new string[ts.Length]; for (int i = 0; i < ts.Length; i++) { ss[i] = ts[i].Name; } GenericTypeParameterBuilder[] genericParameters = mdb.DefineGenericParameters(ss); for (int i = 0; i < genericParameters.Length; i++) { genericParameters[i].SetGenericParameterAttributes(ts[i].GetTypeInfo().GenericParameterAttributes); } } ILGenerator il = mdb.GetILGenerator(); ParametersArray args = new ParametersArray(il, paramTypes); // object[] args = new object[paramCount]; il.Emit(OpCodes.Nop); GenericArray <object> argsArr = new GenericArray <object>(il, ParamTypes(parameters, true).Length); for (int i = 0; i < parameters.Length; i++) { // args[i] = argi; if (!parameters[i].IsOut) { argsArr.BeginSet(i); args.Get(i); argsArr.EndSet(parameters[i].ParameterType); } } // object[] packed = new object[PackedArgs.PackedTypes.Length]; GenericArray <object> packedArr = new GenericArray <object>(il, PackedArgs.PackedTypes.Length); // packed[PackedArgs.DispatchProxyPosition] = this; packedArr.BeginSet(PackedArgs.DispatchProxyPosition); il.Emit(OpCodes.Ldarg_0); packedArr.EndSet(typeof(DispatchProxy)); // packed[PackedArgs.DeclaringTypePosition] = typeof(iface); MethodInfo Type_GetTypeFromHandle = typeof(Type).GetRuntimeMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) }); _assembly.GetTokenForMethod(mi, out Type declaringType, out int methodToken); packedArr.BeginSet(PackedArgs.DeclaringTypePosition); il.Emit(OpCodes.Ldtoken, declaringType); il.Emit(OpCodes.Call, Type_GetTypeFromHandle); packedArr.EndSet(typeof(object)); // packed[PackedArgs.MethodTokenPosition] = iface method token; packedArr.BeginSet(PackedArgs.MethodTokenPosition); il.Emit(OpCodes.Ldc_I4, methodToken); packedArr.EndSet(typeof(Int32)); // packed[PackedArgs.ArgsPosition] = args; packedArr.BeginSet(PackedArgs.ArgsPosition); argsArr.Load(); packedArr.EndSet(typeof(object[])); // packed[PackedArgs.GenericTypesPosition] = mi.GetGenericArguments(); if (mi.ContainsGenericParameters) { packedArr.BeginSet(PackedArgs.GenericTypesPosition); Type[] genericTypes = mi.GetGenericArguments(); GenericArray <Type> typeArr = new GenericArray <Type>(il, genericTypes.Length); for (int i = 0; i < genericTypes.Length; ++i) { typeArr.BeginSet(i); il.Emit(OpCodes.Ldtoken, genericTypes[i]); il.Emit(OpCodes.Call, Type_GetTypeFromHandle); typeArr.EndSet(typeof(Type)); } typeArr.Load(); packedArr.EndSet(typeof(Type[])); } // Call static DispatchProxyHelper.Invoke(object[]) il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, _fields[InvokeActionFieldAndCtorParameterIndex]); // delegate packedArr.Load(); il.Emit(OpCodes.Call, s_delegateInvoke); for (int i = 0; i < parameters.Length; i++) { if (parameters[i].ParameterType.IsByRef) { args.BeginSet(i); argsArr.Get(i); args.EndSet(i, typeof(object)); } } if (mi.ReturnType != typeof(void)) { packedArr.Get(PackedArgs.ReturnValuePosition); Convert(il, typeof(object), mi.ReturnType, false); } il.Emit(OpCodes.Ret); _tb.DefineMethodOverride(mdb, mi); }
void AddRpc(TypeDefinition newType, MethodDefinition irpc) { var tag = irpc.CustomAttributes.FirstOrDefault(x => x.AttributeType.Name == "TAG"); if (tag is null) { return; } var cmd = (int)tag.ConstructorArguments.First().Value; var method = new MethodDefinition(irpc.Name, MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final, irpc.ReturnType); var il = method.Body.GetILProcessor(); var parameters = irpc.Parameters; var paramTypes = ParamTypes(parameters.ToArray(), false); foreach (var param in paramTypes) { method.Parameters.Add(new ParameterDefinition(param)); } if (irpc.ContainsGenericParameter) { throw new Exception($"not have generic parameter{irpc.FullName}"); //var ts = irpc.GenericParameters; //for (int i = 0; i < ts.Count; i++) //{ // method.GenericParameters.Add(ts[i]); //} } ParametersArray args = new ParametersArray(this, il, paramTypes); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4, cmd); il.Emit(OpCodes.Ldtoken, irpc.ReturnType); var ptype = ModuleDefinition.ImportReference(GetMethodInfo.GetTypeofHandler()); il.Emit(OpCodes.Call, ModuleDefinition.ImportReference(ptype)); GenericArray <System.Object> argsArr = new GenericArray <System.Object>(this, il, ParamTypes(parameters.ToArray(), true).Length); for (int i = 0; i < parameters.Count; i++) { // args[i] = argi; if (!parameters[i].IsOut) { argsArr.BeginSet(i); args.Get(i); argsArr.EndSet(parameters[i].ParameterType); } } argsArr.Load(); il.Emit(OpCodes.Call, _methodcall); if (irpc.ReturnType.Name == "Void") { il.Emit(OpCodes.Pop); } else { var res = new VariableDefinition(irpc.ReturnType); method.Body.Variables.Add(res); Convert(il, ModuleDefinition.ImportReference(typeof(System.Object)), irpc.ReturnType, false); il.Emit(OpCodes.Stloc, res); il.Emit(OpCodes.Ldloc, res); } il.Emit(OpCodes.Ret); newType.Methods.Add(method); }