Example #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="c"></param>
        /// <param name="sourceType"></param>
        /// <returns></returns>
        public static MethodInfo EnumerableForeachCompile(CompileContext c, ForeachTag tag, Type sourceType)
        {
            var getVariableScope = DynamicHelpers.GetPropertyGetMethod(typeof(TemplateContext), "TempData");
            var getVariableValue = typeof(VariableScope).GetMethod("get_Item", new[] { typeof(string) });

            var  stringBuilderType = typeof(StringBuilder);
            var  t    = tag;
            var  type = c.GuessType(t);
            var  variableScopeType   = typeof(VariableScope);
            var  templateContextType = typeof(TemplateContext);
            var  childType           = TypeGuesser.InferChildType(sourceType);
            var  enumerableType      = sourceType.GetInterface("IEnumerable`1");// typeof(System.Collections.IEnumerable);
            Type enumeratorType;
            bool mustTo = false;

            if (enumerableType == null)
            {
                enumerableType = typeof(System.Collections.IEnumerable);
                enumeratorType = typeof(System.Collections.IEnumerator);
                mustTo         = true;
            }
            else
            {
                enumeratorType = typeof(IEnumerator <>).MakeGenericType(childType);
            }
            if (childType.Length != 1)
            {
                throw new CompileException("[ForeachTag]:source error.");
            }
            var old   = c.Data;
            var scope = new VariableScope(old);

            c.Data = scope;
            c.Set(t.Name, childType[0]);
            c.Set("foreachIndex", typeof(int));
            var   mb         = c.CreateReutrnMethod <ForeachTag>(type);
            var   il         = mb.GetILGenerator();
            Label labelEnd   = il.DefineLabel();
            Label labelNext  = il.DefineLabel();
            Label labelStart = il.DefineLabel();

            il.DeclareLocal(stringBuilderType);
            il.DeclareLocal(enumerableType);
            il.DeclareLocal(templateContextType);
            il.DeclareLocal(typeof(bool));
            il.DeclareLocal(enumeratorType);
            il.DeclareLocal(typeof(Int32));
            il.DeclareLocal(childType[0]);
            il.DeclareLocal(typeof(bool));
            il.DeclareLocal(typeof(string));
            var types = new Type[t.Children.Count];

            for (var i = 0; i < t.Children.Count; i++)
            {
                types[i] = c.GuessType(t.Children[i]);
                if (t.Children[i] is SetTag setTag)
                {
                    c.Set(setTag.Name, c.GuessType(setTag.Value));
                }
                if (types[i].FullName == "System.Void" || t.Children[i] is TextTag)
                {
                    continue;
                }
            }
            il.Emit(OpCodes.Nop);
            il.Emit(OpCodes.Newobj, stringBuilderType.GetConstructor(Type.EmptyTypes));
            il.Emit(OpCodes.Stloc_0);
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            var method = c.CompileTag(t.Source);

            il.Emit(OpCodes.Call, method);
            il.Emit(OpCodes.Stloc_1);
            il.Emit(OpCodes.Ldloc_1);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Cgt_Un);
            il.Emit(OpCodes.Stloc_3);
            il.Emit(OpCodes.Ldloc_3);
            il.Emit(OpCodes.Brfalse, labelEnd);
            il.Emit(OpCodes.Nop);
            il.Emit(OpCodes.Ldloc_1);
            il.Emit(OpCodes.Callvirt, DynamicHelpers.GetMethod(enumerableType, "GetEnumerator", Type.EmptyTypes));
            il.Emit(OpCodes.Stloc_S, 4);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Call, DynamicHelpers.GetMethod(templateContextType, "CreateContext", new Type[] { templateContextType }));
            il.Emit(OpCodes.Stloc_2);
            il.Emit(OpCodes.Ldc_I4, 0);
            il.Emit(OpCodes.Stloc_S, 5);
            il.Emit(OpCodes.Br, labelNext);
            il.MarkLabel(labelStart);
            il.Emit(OpCodes.Nop);
            il.Emit(OpCodes.Ldloc_S, 5);
            il.Emit(OpCodes.Ldc_I4, 1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc_S, 5);
            il.Emit(OpCodes.Ldloc_S, 4);
            il.Emit(OpCodes.Callvirt, DynamicHelpers.GetPropertyGetMethod(enumeratorType, "Current"));
            if (mustTo)
            {
                if (childType[0].IsValueType)
                {
                    il.Emit(OpCodes.Unbox_Any, childType[0]);
                }
                else
                {
                    il.Emit(OpCodes.Isinst, childType[0]);
                }
            }
            il.Emit(OpCodes.Stloc_S, 6);
            il.Emit(OpCodes.Ldloc, 2);
            il.Emit(OpCodes.Callvirt, getVariableScope);
            il.Emit(OpCodes.Ldstr, t.Name);
            il.Emit(OpCodes.Ldloc_S, 6);
            il.Emit(OpCodes.Callvirt, DynamicHelpers.GetGenericMethod(variableScopeType, childType, "Set", new Type[] { typeof(string), childType[0] }));

            il.Emit(OpCodes.Nop);
            il.Emit(OpCodes.Ldloc, 2);
            il.Emit(OpCodes.Callvirt, getVariableScope);
            il.Emit(OpCodes.Ldstr, "foreachIndex");
            il.Emit(OpCodes.Ldloc_S, 5);
            il.Emit(OpCodes.Callvirt, DynamicHelpers.GetGenericMethod(variableScopeType, new Type[] { typeof(int) }, "Set", new Type[] { typeof(string), typeof(int) }));
            il.Emit(OpCodes.Nop);

            il.StringAppend(c, t.Children, 0, 2);

            il.Emit(OpCodes.Nop);
            il.MarkLabel(labelNext);
            il.Emit(OpCodes.Ldloc_S, 4);
            if (!mustTo)
            {
                il.Emit(OpCodes.Callvirt, DynamicHelpers.GetMethod(typeof(System.Collections.IEnumerator), "MoveNext", Type.EmptyTypes));
            }
            else
            {
                il.Emit(OpCodes.Callvirt, DynamicHelpers.GetMethod(enumeratorType, "MoveNext", Type.EmptyTypes));
            }
            il.Emit(OpCodes.Stloc_S, 7);
            il.Emit(OpCodes.Ldloc_S, 7);
            il.Emit(OpCodes.Brtrue, labelStart);
            il.MarkLabel(labelEnd);
            il.Emit(OpCodes.Ldloc_0);
            il.Call(stringBuilderType, DynamicHelpers.GetMethod(typeof(object), "ToString", Type.EmptyTypes));
            il.Emit(OpCodes.Stloc_S, 8);
            il.Emit(OpCodes.Ldloc_S, 8);
            il.Emit(OpCodes.Ret);
            c.Data = old;
            return(mb.GetBaseDefinition());
        }
Example #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="c"></param>
        /// <param name="sourceType"></param>
        /// <returns></returns>
        public static MethodInfo ArrayForeachCompile(CompileContext c, ForeachTag tag, Type sourceType)
        {
            var getVariableScope = DynamicHelpers.GetPropertyGetMethod(typeof(TemplateContext), "TempData");
            var getVariableValue = typeof(VariableScope).GetMethod("get_Item", new[] { typeof(string) });

            var stringBuilderType = typeof(StringBuilder);
            var t                   = tag;
            var type                = c.GuessType(t);
            var childType           = TypeGuesser.InferChildType(sourceType);
            var templateContextType = typeof(TemplateContext);
            var variableScopeType   = typeof(VariableScope);

            if (childType.Length != 1)
            {
                throw new CompileException("[ForeachTag]:source error.");
            }

            var old   = c.Data;
            var scope = new VariableScope(old);

            c.Data = scope;
            c.Set(t.Name, childType[0]);
            c.Set("foreachIndex", typeof(int));

            var mb         = c.CreateReutrnMethod <ForeachTag>(type);
            var il         = mb.GetILGenerator();
            var labelNext  = il.DefineLabel();
            var labelStart = il.DefineLabel();
            var labelEnd   = il.DefineLabel();

            il.DeclareLocal(stringBuilderType);
            il.DeclareLocal(sourceType);
            il.DeclareLocal(typeof(bool));
            il.DeclareLocal(templateContextType);
            il.DeclareLocal(typeof(int));
            il.DeclareLocal(sourceType);
            il.DeclareLocal(typeof(int));
            il.DeclareLocal(childType[0]);
            il.DeclareLocal(typeof(string));

            var types = new Type[t.Children.Count];

            for (var i = 0; i < t.Children.Count; i++)
            {
                types[i] = c.GuessType(t.Children[i]);
                if (t.Children[i] is SetTag setTag)
                {
                    c.Set(setTag.Name, c.GuessType(setTag.Value));
                }
                if (types[i].FullName == "System.Void" || t.Children[i] is TextTag)
                {
                    continue;
                }
                il.DeclareLocal(types[i]);
            }


            il.Emit(OpCodes.Newobj, stringBuilderType.GetConstructor(Type.EmptyTypes));
            il.Emit(OpCodes.Stloc, 0);

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            var method = c.CompileTag(t.Source);

            il.Emit(OpCodes.Call, method);

            il.Emit(OpCodes.Stloc_1);
            il.Emit(OpCodes.Ldloc_1);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Cgt_Un);
            il.Emit(OpCodes.Stloc_2);
            il.Emit(OpCodes.Ldloc_2);
            il.Emit(OpCodes.Brfalse, labelEnd);


            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Call, DynamicHelpers.GetMethod(templateContextType, "CreateContext", new Type[] { templateContextType }));
            il.Emit(OpCodes.Stloc_3);
            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Stloc, 4);
            il.Emit(OpCodes.Ldloc_1);
            il.Emit(OpCodes.Stloc, 5);
            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Stloc, 6);
            il.Emit(OpCodes.Br, labelStart);

            // loop start
            il.MarkLabel(labelNext);
            il.Emit(OpCodes.Ldloc, 5);
            il.Emit(OpCodes.Ldloc, 6);
            il.Ldelem(childType[0]);
            il.Emit(OpCodes.Stloc, 7);
            il.Emit(OpCodes.Ldloc, 4);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc, 4);
            il.Emit(OpCodes.Ldloc, 3);
            il.Emit(OpCodes.Callvirt, getVariableScope);
            il.Emit(OpCodes.Ldstr, t.Name);
            il.Emit(OpCodes.Ldloc, 7);
            il.Emit(OpCodes.Callvirt, DynamicHelpers.GetGenericMethod(variableScopeType, childType, "Set", new Type[] { typeof(string), childType[0] }));
            il.Emit(OpCodes.Ldloc, 3);
            il.Emit(OpCodes.Callvirt, getVariableScope);
            il.Emit(OpCodes.Ldstr, "foreachIndex");
            il.Emit(OpCodes.Ldloc, 4);
            il.Emit(OpCodes.Callvirt, DynamicHelpers.GetGenericMethod(variableScopeType, new Type[] { typeof(int) }, "Set", new Type[] { typeof(string), typeof(int) }));

            il.StringAppend(c, t.Children, 0, 3);

            il.Emit(OpCodes.Ldloc, 6);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc, 6);
            il.MarkLabel(labelStart);
            il.Emit(OpCodes.Ldloc, 6);
            il.Emit(OpCodes.Ldloc, 5);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Blt, labelNext);
            // end loop

            il.MarkLabel(labelEnd);
            il.Emit(OpCodes.Ldloc_0);
            il.Call(stringBuilderType, DynamicHelpers.GetMethod(typeof(object), "ToString", Type.EmptyTypes));
            il.Emit(OpCodes.Stloc, 8);
            il.Emit(OpCodes.Ldloc, 8);
            il.Emit(OpCodes.Ret);

            return(mb.GetBaseDefinition());
        }