private static void CompileToRender(ITag tag, CompileContext context, Type tagType, MethodInfo method) { var type = method.ReturnType; var isAsync = false; var taskType = typeof(System.Threading.Tasks.Task); MethodInfo taskAwaiterMethod = null; MethodInfo resultMethod = null; var mb = context.CreateRenderMethod(tagType.Name); var il = mb.GetILGenerator(); var exBlock = il.BeginExceptionBlock(); var lableThrow = il.DefineLabel(); var labelPass = il.DefineLabel(); var index = 0; if (DynamicHelpers.IsMatchType(type, taskType)) { isAsync = true; taskAwaiterMethod = DynamicHelpers.GetMethod(method.ReturnType, "GetAwaiter", Type.EmptyTypes); resultMethod = DynamicHelpers.GetMethod(taskAwaiterMethod.ReturnType, "GetResult", Type.EmptyTypes); type = resultMethod.ReturnType; } if (type.FullName != "System.Void") { il.DeclareLocal(type); index = 1; il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Call, method); if (isAsync) { il.DeclareLocal(taskAwaiterMethod.ReturnType); il.Emit(OpCodes.Callvirt, taskAwaiterMethod); il.Emit(OpCodes.Stloc, index); il.Emit(OpCodes.Ldloca, index); il.Emit(OpCodes.Call, resultMethod); index++; } il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldarg_1); MethodInfo writeMethod; switch (type.FullName) { case "System.Object": case "System.String": case "System.Decimal": case "System.Single": case "System.UInt64": case "System.Int64": case "System.UInt32": case "System.Int32": case "System.Boolean": case "System.Double": case "System.Char": il.Emit(OpCodes.Ldloc_0); writeMethod = typeof(TextWriter).GetMethod("Write", new Type[] { type }); break; default: if (type.IsValueType) { il.Emit(OpCodes.Ldloca_S, 0); il.Call(type, typeof(object).GetMethod("ToString", Type.EmptyTypes)); writeMethod = typeof(TextWriter).GetMethod("Write", new Type[] { typeof(string) }); } else { il.Emit(OpCodes.Ldloc_0); writeMethod = typeof(TextWriter).GetMethod("Write", new Type[] { typeof(object) }); } break; } il.Emit(OpCodes.Callvirt, writeMethod); } else { if (isAsync) { il.DeclareLocal(taskAwaiterMethod.ReturnType); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Call, method); il.Emit(OpCodes.Callvirt, taskAwaiterMethod); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloca, 0); il.Emit(OpCodes.Call, resultMethod); index = 1; } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Call, method); } } il.DeclareLocal(typeof(System.Exception)); il.DeclareLocal(typeof(bool)); il.BeginCatchBlock(typeof(System.Exception)); il.Emit(OpCodes.Stloc, index); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Callvirt, DynamicHelpers.GetPropertyGetMethod(typeof(Context), "ThrowExceptions")); il.Emit(OpCodes.Stloc, index + 1); il.Emit(OpCodes.Ldloc, index + 1); il.Emit(OpCodes.Brfalse, lableThrow); il.Emit(OpCodes.Ldloc, index); il.Emit(OpCodes.Throw); il.MarkLabel(lableThrow); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldloc, index); il.Emit(OpCodes.Callvirt, DynamicHelpers.GetMethod(typeof(TemplateContext), "AddError", new Type[] { typeof(System.Exception) })); //il.Emit(OpCodes.Leave_S, labelPass); il.EndExceptionBlock(); il.MarkLabel(labelPass); il.Emit(OpCodes.Ret); context.Generator.Emit(OpCodes.Ldarg_0); context.Generator.Emit(OpCodes.Ldarg_1); context.Generator.Emit(OpCodes.Ldarg_2); context.Generator.Emit(OpCodes.Call, mb.GetBaseDefinition()); }
private static void CompileToRender(this CompileContext context, ITag tag, Type tagType, MethodInfo method) { var type = method.ReturnType; var isAsync = false; var taskType = typeof(System.Threading.Tasks.Task); MethodInfo taskAwaiterMethod = null; MethodInfo resultMethod = null; var mb = context.CreateRenderMethod(tagType.Name); var il = mb.GetILGenerator(); var exBlock = il.BeginExceptionBlock(); //var lableThrow = il.DefineLabel(); var labelPass = il.DefineLabel(); if (type.IsMatchType(taskType)) { isAsync = true; taskAwaiterMethod = method.ReturnType.GetMethodInfo("GetAwaiter", Type.EmptyTypes); resultMethod = taskAwaiterMethod.ReturnType.GetMethodInfo("GetResult", Type.EmptyTypes); type = resultMethod.ReturnType; } if (type.FullName != "System.Void") { il.DeclareLocal(type); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Call, method); if (isAsync) { var returnVar = il.DeclareLocal(taskAwaiterMethod.ReturnType); il.Emit(OpCodes.Callvirt, taskAwaiterMethod); il.Emit(OpCodes.Stloc, returnVar.LocalIndex); il.Emit(OpCodes.Ldloca, returnVar.LocalIndex); il.Emit(OpCodes.Call, resultMethod); } il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldarg_1); MethodInfo writeMethod; switch (type.FullName) { case "System.Object": case "System.String": case "System.Decimal": case "System.Single": case "System.UInt64": case "System.Int64": case "System.UInt32": case "System.Int32": case "System.Boolean": case "System.Double": case "System.Char": il.Emit(OpCodes.Ldloc_0); writeMethod = typeof(TextWriter).GetMethod("Write", new Type[] { type }); break; default: if (type.IsValueType) { il.Emit(OpCodes.Ldloca_S, 0); il.Call(type, typeof(object).GetMethod("ToString", Type.EmptyTypes)); writeMethod = typeof(TextWriter).GetMethod("Write", new Type[] { typeof(string) }); } else { il.Emit(OpCodes.Ldloc_0); writeMethod = typeof(TextWriter).GetMethod("Write", new Type[] { typeof(object) }); } break; } il.Emit(OpCodes.Callvirt, writeMethod); } else { if (isAsync) { il.DeclareLocal(taskAwaiterMethod.ReturnType); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Call, method); il.Emit(OpCodes.Callvirt, taskAwaiterMethod); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloca, 0); il.Emit(OpCodes.Call, resultMethod); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Call, method); } } var exceptionVar = il.DeclareLocal(typeof(System.Exception)); //il.DeclareLocal(typeof(bool)); il.BeginCatchBlock(typeof(System.Exception)); il.Emit(OpCodes.Stloc, exceptionVar.LocalIndex); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldloc, exceptionVar.LocalIndex); il.Emit(OpCodes.Ldc_I4, tag.FirstToken?.BeginLine ?? 0); il.Emit(OpCodes.Ldc_I4, tag.FirstToken?.BeginColumn ?? 0); if (context.Debug) { il.Emit(OpCodes.Ldstr, tag.ToSource()); } else { il.Emit(OpCodes.Ldnull); } il.Emit(OpCodes.Call, typeof(CompilerResult).GetMethodInfo("ThrowException", null)); il.EndExceptionBlock(); il.MarkLabel(labelPass); il.Emit(OpCodes.Ret); context.Generator.Emit(OpCodes.Ldarg_0); context.Generator.Emit(OpCodes.Ldarg_1); context.Generator.Emit(OpCodes.Ldarg_2); context.Generator.Emit(OpCodes.Call, mb.GetBaseDefinition()); }