예제 #1
0
        static void GenerateConstructor(RecordTypeDescriptor rtd, TypeGen tg, Type parenttype)
        {
            // constructor logic
              {
            List<Type> paramtypes = new List<Type>();
            List<FieldDescriptor> allfields = new List<FieldDescriptor>(rtd.GetAllFields());

            int diff = allfields.Count - rtd.Fields.Length;

            foreach (FieldDescriptor var in allfields)
            {
              paramtypes.Add(var.Type);
            }

            List<Type> parenttypes = new List<Type>();

            for (int i = 0; i < diff; i++)
            {
              parenttypes.Add(typeof(object)); //TODO: fix this, it looks broken
            }

            if (paramtypes.Count < 9)
            {
              CodeGen cg = tg.DefineConstructor(paramtypes.ToArray());

              CodeGen mk = tg.DefineMethod(MethodAttributes.Public | MethodAttributes.Static, "make",
               tg.TypeBuilder, paramtypes.ToArray(), allfields.ConvertAll(x => x.Name).ToArray());

              for (int i = 0; i < allfields.Count; i++)
              {
            cg.DefineParameter(i + 1, ParameterAttributes.None, allfields[i].Name);
              }

              int fi = 0;

              cg.EmitThis();

              for (fi = 0; fi < diff; fi++)
              {
            cg.EmitArgGet(fi);
            mk.EmitArgGet(fi);
              }

              // improve get constructor to look for protected constructors too
              cg.Emit(OpCodes.Call, (rtd.Parent == null ? parenttype.GetConstructor(Type.EmptyTypes) : rtd.Parent.DefaultConstructor));

              foreach (FieldDescriptor fd in rtd.Fields)
              {
            cg.EmitThis();
            cg.EmitArgGet(fi);
            cg.EmitFieldSet(fd.field);

            mk.EmitArgGet(fi);

            fi++;
              }

              mk.EmitNew(cg.MethodBase as ConstructorInfo);
              mk.EmitReturn();

              cg.EmitReturn();

              rtd.cg = cg;
            }
            else
            {

              CodeGen cg = tg.DefineConstructor(paramtypes.ToArray());
              CodeGen mk = tg.DefineMethod(MethodAttributes.Public | MethodAttributes.Static, "make",
               tg.TypeBuilder, new Type[] { typeof(object[]) }, new string[] { "args" });

              for (int i = 0; i < allfields.Count; i++)
              {
            cg.DefineParameter(i + 1, ParameterAttributes.None, allfields[i].Name);
              }

              int fi = 0;

              cg.EmitThis();

              for (fi = 0; fi < diff; fi++)
              {
            cg.EmitArgGet(fi);

            mk.EmitArgGet(0);
            mk.EmitConstant(fi);
            mk.Emit(OpCodes.Ldelem, typeof(object));
              }

              cg.Emit(OpCodes.Call, (rtd.Parent == null ? typeof(object).GetConstructor(Type.EmptyTypes) : rtd.Parent.DefaultConstructor));

              foreach (FieldDescriptor fd in rtd.Fields)
              {
            cg.EmitThis();
            cg.EmitArgGet(fi);
            cg.EmitFieldSet(fd.field);

            mk.EmitArgGet(0);
            mk.EmitConstant(fi);
            mk.Emit(OpCodes.Ldelem, typeof(object));

            fi++;
              }

              mk.EmitNew(cg.MethodBase as ConstructorInfo);
              mk.EmitReturn();

              cg.EmitReturn();

              rtd.cg = cg;
            }
              }
        }
예제 #2
0
        static void GenerateConstructor(RecordTypeDescriptor rtd, TypeGen tg, Type parenttype)
        {
            // constructor logic
            {
                List <Type>            paramtypes = new List <Type>();
                List <FieldDescriptor> allfields  = new List <FieldDescriptor>(rtd.GetAllFields());

                int diff = allfields.Count - rtd.Fields.Length;

                foreach (FieldDescriptor var in allfields)
                {
                    paramtypes.Add(var.Type);
                }

                List <Type> parenttypes = new List <Type>();

                for (int i = 0; i < diff; i++)
                {
                    parenttypes.Add(typeof(object)); //TODO: fix this, it looks broken
                }

                if (paramtypes.Count < 9)
                {
                    CodeGen cg = tg.DefineConstructor(paramtypes.ToArray());

                    CodeGen mk = tg.DefineMethod(MethodAttributes.Public | MethodAttributes.Static, "make",
                                                 tg.TypeBuilder, paramtypes.ToArray(), allfields.ConvertAll(x => x.Name).ToArray());


                    for (int i = 0; i < allfields.Count; i++)
                    {
                        cg.DefineParameter(i + 1, ParameterAttributes.None, allfields[i].Name);
                    }

                    int fi = 0;

                    cg.EmitThis();


                    for (fi = 0; fi < diff; fi++)
                    {
                        cg.EmitArgGet(fi);
                        mk.EmitArgGet(fi);
                    }

                    cg.Emit(OpCodes.Call, (rtd.Parent == null ? parenttype.GetConstructor(Type.EmptyTypes) : rtd.Parent.DefaultConstructor));

                    foreach (FieldDescriptor fd in rtd.Fields)
                    {
                        cg.EmitThis();
                        cg.EmitArgGet(fi);
                        cg.EmitFieldSet(fd.field);

                        mk.EmitArgGet(fi);

                        fi++;
                    }

                    mk.EmitNew(cg.MethodBase as ConstructorInfo);
                    mk.EmitReturn();

                    cg.EmitReturn();

                    rtd.cg = cg;
                }
                else
                {
                    CodeGen cg = tg.DefineConstructor(paramtypes.ToArray());
                    CodeGen mk = tg.DefineMethod(MethodAttributes.Public | MethodAttributes.Static, "make",
                                                 tg.TypeBuilder, new Type[] { typeof(object[]) }, new string[] { "args" });


                    for (int i = 0; i < allfields.Count; i++)
                    {
                        cg.DefineParameter(i + 1, ParameterAttributes.None, allfields[i].Name);
                    }

                    int fi = 0;

                    cg.EmitThis();


                    for (fi = 0; fi < diff; fi++)
                    {
                        cg.EmitArgGet(fi);

                        mk.EmitArgGet(0);
                        mk.EmitConstant(fi);
                        mk.Emit(OpCodes.Ldelem, typeof(object));
                    }

                    cg.Emit(OpCodes.Call, (rtd.Parent == null ? typeof(object).GetConstructor(Type.EmptyTypes) : rtd.Parent.DefaultConstructor));

                    foreach (FieldDescriptor fd in rtd.Fields)
                    {
                        cg.EmitThis();
                        cg.EmitArgGet(fi);
                        cg.EmitFieldSet(fd.field);

                        mk.EmitArgGet(0);
                        mk.EmitConstant(fi);
                        mk.Emit(OpCodes.Ldelem, typeof(object));

                        fi++;
                    }

                    mk.EmitNew(cg.MethodBase as ConstructorInfo);
                    mk.EmitReturn();

                    cg.EmitReturn();

                    rtd.cg = cg;
                }
            }
        }
예제 #3
0
        static CodeGen MakeInitMethod(RecordTypeDescriptor rtd, TypeGen tg)
        {
            var initTypes = new List <Type>();

            initTypes.Add(tg.TypeBuilder);
            initTypes.AddRange(Array.ConvertAll(rtd.Fields, f => f.Type));

            var initNames = new List <string>();

            initNames.Add("$this");
            initNames.AddRange(Array.ConvertAll(rtd.Fields, f => f.Name));

            CodeGen init = null;

            if (rtd.Fields.Length == 0)
            {
                init = tg.DefineMethod(MethodAttributes.Public | MethodAttributes.Static, "$init", tg.TypeBuilder, initTypes.ToArray(), initNames.ToArray());
                init.EmitArgGet(0);
            }
            else if (initTypes.Count < 9)
            {
                init = tg.DefineMethod(MethodAttributes.Public | MethodAttributes.Static, "$init", tg.TypeBuilder, initTypes.ToArray(), initNames.ToArray());

                int ii = 1;

                foreach (FieldDescriptor fd in rtd.Fields)
                {
                    init.EmitArgGet(0);
                    init.EmitArgGet(ii);
                    init.EmitFieldSet(fd.field);
                    ii++;
                }

                init.EmitArgGet(0);
            }
            else
            {
                init = tg.DefineMethod(MethodAttributes.Public | MethodAttributes.Static, "$init", tg.TypeBuilder, new Type[] { typeof(object[]) }, new string[] { "args" });

                var local = init.DeclareLocal(tg.TypeBuilder);
                init.EmitArgGet(0);
                init.EmitConstant(0);
                init.Emit(OpCodes.Ldelem, typeof(object));
                init.Emit(OpCodes.Castclass, tg.TypeBuilder);
                init.Emit(OpCodes.Stloc, local);

                int ii = 1;

                foreach (FieldDescriptor fd in rtd.Fields)
                {
                    init.Emit(OpCodes.Ldloc, local);

                    init.EmitArgGet(0);
                    init.EmitConstant(ii);
                    init.Emit(OpCodes.Ldelem, typeof(object));

                    init.EmitFieldSet(fd.field);
                    ii++;
                }

                init.Emit(OpCodes.Ldloc, local);
            }

            init.EmitReturn();

            return(init);
        }