Ejemplo n.º 1
0
        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());
        }
Ejemplo n.º 2
0
        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());
        }