Ejemplo n.º 1
0
        public ILSerialize <T> CompileILSerialize(BaseModule[] modules)
        {
            var dm = new DynamicMethod <ILSerialize <T> >(string.Empty,
                                                          typeof(object[]),
                                                          new[]
            {
                typeof(T)
            },
                                                          true);

            var il = dm.ILGenerator;

            // int objSize = 0;
            var objSize = il.DeclareLocal(typeof(int));

            il.EmitConstantInt(0);
            il.EmitSetLocalVariable(objSize);

            foreach (var i in GetILModules(modules))
            {
                i.GenerateEstimateSize(il, getEstimateSizeMethodContainer());
            }

            var objArray = il.DeclareLocal(typeof(object[]));
            var index    = il.DeclareLocal(typeof(int));

            // int i = 0;
            il.EmitConstantInt(0);
            il.EmitSetLocalVariable(index);

            // object[] objArray = new object[objSize];
            il.EmitLoadLocalVariable(objSize);
            il.EmitNewArray <object>();
            il.EmitSetLocalVariable(objArray);

            int c = 0;

            foreach (var i in GetILModules(modules))
            {
                i.GenerateSerialize(il, getSerializeMethodContainer());

                c++;
            }

            // return objArray;
            il.EmitLoadLocalVariable(objArray);
            il.EmitReturn();

            return(dm.CreateDelegate());

            void emitLoadSerializingItem() => il.EmitLoadArgument(0);

            ILEstimateSizeMethodContainer getEstimateSizeMethodContainer() => new ILEstimateSizeMethodContainer(
                loadCurrentObject: () =>
            {
                emitLoadSerializingItem();
            },
                addToSize: (load) =>
            {
                load();
                il.EmitLoadLocalVariable(objSize);
                il.EmitAdd();
                il.EmitSetLocalVariable(objSize);
            }
                );

            ILSerializeMethodContainer getSerializeMethodContainer() => new ILSerializeMethodContainer(
                index,
                loadMemberValue: () =>
            {
                MemberUtils.EmitILForGetMethod(il, modules[c].ModuleContainer.Member.GetMember, () =>
                {
                    emitLoadSerializingItem();
                });
            },
                setArrayValue: (emit) =>
            {
                il.EmitLoadLocalVariable(objArray);
                il.EmitLoadLocalVariable(index);
                emit();
                il.EmitSetArrayElement <object>();
            },
                addToIndex: (emit) =>
            {
                il.EmitLoadLocalVariable(index);
                emit();
                il.EmitAdd();
                il.EmitSetLocalVariable(index);
            }
                );
        }