Exemple #1
0
        internal static void ComputeWriter(ILGenerator il, Type type, BoisComplexTypeInfo typeInfo)
        {
            switch (typeInfo.ComplexKnownType)
            {
            case EnComplexKnownType.Collection:
                EmitGenerator.WriteRootList(type, typeInfo, il);
                break;

            case EnComplexKnownType.Dictionary:
                EmitGenerator.WriteRootDictionary(type, typeInfo, il);
                break;

            case EnComplexKnownType.NameValueColl:
                EmitGenerator.WriteRootNameValueCol(type, typeInfo, il);
                return;

            case EnComplexKnownType.UnknownArray:
                EmitGenerator.WriteRootUnknownArray(type, typeInfo, il);
                break;

            case EnComplexKnownType.ISet:
                EmitGenerator.WriteRootISet(type, typeInfo, il);
                break;

            case EnComplexKnownType.Unknown:
            default:
                WriteRootObject(il, type, typeInfo);
                break;
            }
        }
Exemple #2
0
        private static void ReadRootObjectComplexMember(Type memberType, BoisComplexTypeInfo complexTypeInfo, PropertyInfo prop, FieldInfo field, Type containerType, ILGenerator il, SharedVariables variableCache)
        {
            switch (complexTypeInfo.ComplexKnownType)
            {
            case EnComplexKnownType.Collection:
            case EnComplexKnownType.ISet:
                EmitGenerator.ReadGenericCollection(prop, field, null, containerType, il, complexTypeInfo.IsNullable, variableCache);
                break;

            case EnComplexKnownType.Dictionary:
                EmitGenerator.ReadDictionary(prop, field, null, containerType, il, complexTypeInfo.IsNullable, variableCache);
                break;

            case EnComplexKnownType.UnknownArray:
                EmitGenerator.ReadUnknownArray(prop, field, null, containerType, il, complexTypeInfo.IsNullable, variableCache);
                break;

            case EnComplexKnownType.NameValueColl:
                EmitGenerator.ReadNameValueColl(prop, field, null, containerType, il, complexTypeInfo.IsNullable, variableCache);
                break;

            case EnComplexKnownType.Unknown:
            default:
                EmitGenerator.ReadUnknownComplexTypeCall(memberType, prop, field, containerType, il, complexTypeInfo);
                return;
            }
        }
Exemple #3
0
        /// <returns>The instance variable</returns>
        private static void ComputeReader(ILGenerator il, Type type, BoisComplexTypeInfo typeInfo)
        {
            switch (typeInfo.ComplexKnownType)
            {
            case EnComplexKnownType.Collection:
                EmitGenerator.ReadRootCollection(type, typeInfo, il);
                break;

            case EnComplexKnownType.Dictionary:
                EmitGenerator.ReadRootDictionary(type, typeInfo, il);
                break;

            case EnComplexKnownType.UnknownArray:
                EmitGenerator.ReadRootUnknownArray(type, typeInfo, il);
                break;

            case EnComplexKnownType.NameValueColl:
                EmitGenerator.ReadRootNameValueColl(type, typeInfo, il);
                break;

            case EnComplexKnownType.ISet:
                EmitGenerator.ReadRootISet(type, typeInfo, il);
                break;

            case EnComplexKnownType.Unknown:
            default:
                ReadRootObject(il, type, typeInfo);
                break;
            }
        }
Exemple #4
0
        private static void WriteRootObjectComplexMember(Type memberType, BoisComplexTypeInfo complexTypeInfo, PropertyInfo prop, FieldInfo field, Type containerType, ILGenerator il)
        {
            switch (complexTypeInfo.ComplexKnownType)
            {
            case EnComplexKnownType.Collection:
                EmitGenerator.WriteCollection(prop, field, null, containerType, il, complexTypeInfo.IsNullable);
                break;

            case EnComplexKnownType.Dictionary:
                EmitGenerator.WriteDictionary(prop, field, null, containerType, il, complexTypeInfo.IsNullable);
                break;

            case EnComplexKnownType.UnknownArray:
                EmitGenerator.WriteUnknownArray(prop, field, null, containerType, il, complexTypeInfo.IsNullable);
                break;

            case EnComplexKnownType.NameValueColl:
                EmitGenerator.WriteNameValueColl(prop, field, null, il, complexTypeInfo.IsNullable);
                break;

            case EnComplexKnownType.ISet:
                EmitGenerator.WriteISet(prop, field, null, containerType, il, complexTypeInfo.IsNullable);
                break;

            case EnComplexKnownType.Unknown:
            default:
                EmitGenerator.WriteUnknownComplexTypeCall(memberType, prop, field, il, containerType, complexTypeInfo);
                return;
            }
        }
Exemple #5
0
        public static ComputeResult ComputeReader(Type type, BoisComplexTypeInfo typeInfo, Action <DynamicMethod> beforeMehodBody = null, Module containerModule = null)
        {
            Module module = null;

            if (containerModule == null)
            {
                module = typeof(BoisSerializer).Module;
            }
            else
            {
                module = containerModule;
            }

            var ilMethod = new DynamicMethod(
                name: GetTypeMethodName(type, serialize: false),
                returnType: type,
                // Arg0: BinaryWriter, Arg1: Encoding
                parameterTypes: new[] { typeof(BinaryReader), typeof(Encoding) },
                m: module,
                skipVisibility: true);

#if NetFX || NETFRAMEWORK || NETSTANDARD
            ilMethod.DefineParameter(1, ParameterAttributes.None, "reader");
            ilMethod.DefineParameter(2, ParameterAttributes.None, "encoding");
#endif

            // this call is usefull for Recursive Methods
            beforeMehodBody?.Invoke(ilMethod);

            // the il generator
            var il = ilMethod.GetILGenerator();

            if (typeInfo.ComplexKnownType == EnComplexKnownType.Unknown)
            {
                var instanceVar = ComputeReaderTypeCreation(il, type);
                ComputeReader(il, type, typeInfo);

                // never forget
                il.LoadLocalValue(instanceVar);
                il.Emit(OpCodes.Ret);
            }
            else
            {
                // root object should return the instance variable
                ComputeReader(il, type, typeInfo);
            }

            var delegateType = typeof(DeserializeDelegate <>).MakeGenericType(type);

            // the serializer method is ready
            var readerDelegate = ilMethod.CreateDelegate(delegateType);
            return(new ComputeResult()
            {
                Method = ilMethod,
                Delegate = readerDelegate
            });
        }
Exemple #6
0
        private static void WriteRootObject(ILGenerator il, Type type, BoisComplexTypeInfo typeInfo)
        {
            if (typeInfo.Members == null || typeInfo.Members.Length == 0)
            {
                // no member
                return;
            }

            //TODO: check the impact of removing object count
            WriteRootObjectMembersCount(il, type, typeInfo);

            foreach (var member in typeInfo.Members)
            {
                WriteRootObjectMember(member, type, il);
            }
        }
Exemple #7
0
        private static void ReadRootObject(ILGenerator il, Type type, BoisComplexTypeInfo typeInfo)
        {
            if (typeInfo.Members == null || typeInfo.Members.Length == 0)
            {
                // no mmeber
                return;
            }

            var variableCache = new SharedVariables(il);

            ReadRootObjectMembersCount(il, type, variableCache);

            foreach (var member in typeInfo.Members)
            {
                ReadRootObjectMember(member, type, il, variableCache);
            }
        }
Exemple #8
0
        private static void WriteRootObjectMembersCount(ILGenerator il, Type type, BoisComplexTypeInfo typeInfo)
        {
            if (type.IsExplicitStruct())
            {
                // no null indicator and member count for structs
                return;
            }

            var labelWriteCount = il.DefineLabel();
            var labelEndOfCode  = il.DefineLabel();

            if (!type.IsValueType && !typeInfo.IsNullable)
            {
                il.LoadArgAuto(1, type);                 // instance
                il.Emit(OpCodes.Brtrue_S, labelWriteCount);

                // CODE-FOR: PrimitiveWriter.WriteNullValue(writer);
                il.Emit(OpCodes.Ldarg_0);                 // BinaryWriter
                il.Emit(OpCodes.Call,
                        typeof(PrimitiveWriter).GetMethod(nameof(PrimitiveWriter.WriteNullValue),
                                                          BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public));
                il.Emit(OpCodes.Nop);

                // CODE-FOR: return;
                il.Emit(OpCodes.Ret);

                // CODE-FOR: else
                il.Emit(OpCodes.Br_S, labelEndOfCode);
            }

            // CODE-FOR: writing member count
            il.MarkLabel(labelWriteCount);

            var memberCount = typeInfo.Members.Length;

            il.Emit(OpCodes.Ldarg_0);             // BinaryWriter
            il.Emit(OpCodes.Ldc_I4_S, memberCount);
            il.Emit(OpCodes.Call, meth: typeof(NumericSerializers).GetMethod(nameof(NumericSerializers.WriteUIntNullableMemberCount),
                                                                             BindingFlags.Static | BindingFlags.NonPublic, Type.DefaultBinder, new[] { typeof(BinaryWriter), typeof(uint) }, null));
            il.Emit(OpCodes.Nop);

            il.MarkLabel(labelEndOfCode);
        }
Exemple #9
0
        public static ComputeResult ComputeWriter(Type type, BoisComplexTypeInfo typeInfo, Action <DynamicMethod> beforeMehodBody = null, Module containerModule = null)
        {
            var module = containerModule ?? typeof(BoisSerializer).Module;

            var ilMethod = new DynamicMethod(
                name: GetTypeMethodName(type, serialize: true),
                returnType: null,
                // Arg0: BinaryWriter, Arg1: instance, Arg2: Encoding
                parameterTypes: new[] { typeof(BinaryWriter), type /*typeof(object)*/, typeof(Encoding) },
                m: module,
                skipVisibility: true);

#if NetFX || NETFRAMEWORK || NETSTANDARD
            ilMethod.DefineParameter(1, ParameterAttributes.None, "writer");
            ilMethod.DefineParameter(2, ParameterAttributes.None, "instance");
            ilMethod.DefineParameter(3, ParameterAttributes.None, "encoding");
#endif

            // this call is usefull for Recursive Methods
            beforeMehodBody?.Invoke(ilMethod);

            // the il generator
            var il = ilMethod.GetILGenerator();

            ComputeWriter(il, type, typeInfo);

            // never forget
            il.Emit(OpCodes.Ret);

            var delegateType = typeof(SerializeDelegate <>).MakeGenericType(type);

            // the serializer method is ready
            var writerDelegate = ilMethod.CreateDelegate(delegateType);

            return(new ComputeResult()
            {
                Delegate = writerDelegate,
                Method = ilMethod
            });
        }
Exemple #10
0
        public static ComputeResult ComputeReaderSaveAss(Type type, BoisComplexTypeInfo typeInfo, bool outputAssembly = true, Action <MethodInfo> beforeMehodBody = null)
        {
            var saveAssembly = _outReaderModule == null;

            if (_outReaderModule == null)
            {
                _readerAssemblyName = GetTypeMethodName(type, false) + ".exe";

                _outReaderAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
                    name: new AssemblyName(_readerAssemblyName),
                    access: AssemblyBuilderAccess.RunAndSave);

                var moduleBuilder = _outReaderAssemblyBuilder.DefineDynamicModule(_readerAssemblyName);

                _outReaderProgrammClass = moduleBuilder.DefineType("Program", TypeAttributes.Public);
                _outReaderModule        = _outReaderProgrammClass;

                var mainMethod = _outReaderProgrammClass.DefineMethod(name: "Main",
                                                                      attributes: MethodAttributes.Public | MethodAttributes.Static,
                                                                      returnType: null,
                                                                      parameterTypes: new Type[] { typeof(string[]) });

                var mailIl = mainMethod.GetILGenerator();
                mainMethod.InitLocals = true;
                mailIl.DeclareLocal(typeof(string));

                mailIl.Emit(OpCodes.Ldstr, "Hello World!");
                mailIl.Emit(OpCodes.Stloc_0);
                mailIl.Emit(OpCodes.Ldloc_0);
                mailIl.Emit(OpCodes.Call, (typeof(Console)).GetMethod("WriteLine", new Type[] { typeof(string) }));
                mailIl.Emit(OpCodes.Call, (typeof(Console)).GetMethod("ReadKey", new Type[0]));
                mailIl.Emit(OpCodes.Pop);
                mailIl.Emit(OpCodes.Ret);
            }
            else
            {
                _outReaderProgrammClass = _outReaderModule;
            }


            var ilMethod = _outReaderProgrammClass.DefineMethod(
                name: GetTypeMethodName(type, serialize: false),
                attributes: MethodAttributes.Public | MethodAttributes.Static,
                returnType: type,
                // Arg0: BinaryWriter, Arg1: Encoding
                parameterTypes: new[] { typeof(BinaryReader), typeof(Encoding) });

            ilMethod.DefineParameter(1, ParameterAttributes.None, "reader");
            ilMethod.DefineParameter(2, ParameterAttributes.None, "encoding");

            // this call is usefull for Recursive Methods
            beforeMehodBody?.Invoke(ilMethod);

            var il = ilMethod.GetILGenerator();

            if (typeInfo.ComplexKnownType == EnComplexKnownType.Unknown)
            {
                var instanceVar = ComputeReaderTypeCreation(il, type);
                ComputeReader(il, type, typeInfo);

                // never forget
                il.LoadLocalValue(instanceVar);
                il.Emit(OpCodes.Ret);
            }
            else
            {
                // root object should return the instance variable
                ComputeReader(il, type, typeInfo);
            }


            if (saveAssembly && outputAssembly)
            {
                var generatedType = SaveAssemblyOutput_Reader();

                var delegateType   = typeof(DeserializeDelegate <>).MakeGenericType(type);
                var readerDelegate = generatedType.GetMethod(ilMethod.Name).CreateDelegate(delegateType);

                return(new ComputeResult()
                {
                    Method = ilMethod,
                    Delegate = readerDelegate
                });
            }

            return(new ComputeResult()
            {
                Method = ilMethod,
                Delegate = null
            });
        }
Exemple #11
0
        internal static ComputeResult ComputeWriterSaveAss(Type type, BoisComplexTypeInfo typeInfo, bool outputAssembly = true, Action <MethodInfo> beforeMehodBody = null)
        {
            var saveAssembly = _outWriterModule == null;

            if (_outWriterModule == null)
            {
                _writerAssemblyName = GetTypeMethodName(type, true) + ".exe";

                var daCtor    = typeof(System.Diagnostics.DebuggableAttribute).GetConstructor(new Type[] { typeof(System.Diagnostics.DebuggableAttribute.DebuggingModes) });
                var daBuilder = new CustomAttributeBuilder(daCtor, new object[] {
                    System.Diagnostics.DebuggableAttribute.DebuggingModes.DisableOptimizations |
                    System.Diagnostics.DebuggableAttribute.DebuggingModes.Default
                });

                _outWriterAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
                    name: new AssemblyName(_writerAssemblyName),
                    access: AssemblyBuilderAccess.RunAndSave);

                _outWriterAssemblyBuilder.SetCustomAttribute(daBuilder);

                var moduleBuilder = _outWriterAssemblyBuilder.DefineDynamicModule(_writerAssemblyName);
                _outWriterProgrammClass = moduleBuilder.DefineType("Program", TypeAttributes.Public);

                _outWriterModule = _outWriterProgrammClass;

                var mainMethod = _outWriterProgrammClass.DefineMethod(name: "Main",
                                                                      attributes: MethodAttributes.Public | MethodAttributes.Static,
                                                                      returnType: null,
                                                                      parameterTypes: new Type[] { typeof(string[]) });

                var mailIl = mainMethod.GetILGenerator();
                mainMethod.InitLocals = true;
                mailIl.DeclareLocal(typeof(string));

                mailIl.Emit(OpCodes.Ldstr, "Hello World!");
                mailIl.Emit(OpCodes.Stloc_0);
                mailIl.Emit(OpCodes.Ldloc_0);
                mailIl.Emit(OpCodes.Call, (typeof(Console)).GetMethod("WriteLine", new Type[] { typeof(string) }));
                mailIl.Emit(OpCodes.Call, (typeof(Console)).GetMethod("ReadKey", new Type[0]));
                mailIl.Emit(OpCodes.Pop);
                mailIl.Emit(OpCodes.Ret);
            }
            else
            {
                _outWriterProgrammClass = _outWriterModule;
            }

            var ilMethod = _outWriterProgrammClass.DefineMethod(
                name: GetTypeMethodName(type, serialize: true),
                attributes: MethodAttributes.Public | MethodAttributes.Static,
                returnType: null,
                // Arg0: BinaryWriter, Arg1: instance, Arg2: Encoding
                parameterTypes: new[] { typeof(BinaryWriter), type /*typeof(object)*/, typeof(Encoding) });

            ilMethod.DefineParameter(1, ParameterAttributes.None, "writer");
            ilMethod.DefineParameter(2, ParameterAttributes.None, "instance");
            ilMethod.DefineParameter(3, ParameterAttributes.None, "encoding");

            // this call is usefull for Recursive Methods
            beforeMehodBody?.Invoke(ilMethod);

            var il = ilMethod.GetILGenerator();

            ComputeWriter(il, type, typeInfo);

            // never forget
            il.Emit(OpCodes.Ret);


            if (saveAssembly && outputAssembly)
            {
                var generatedType = SaveAssemblyOutput_Writer();

                var delegateType   = typeof(SerializeDelegate <>).MakeGenericType(type);
                var writerDelegate = generatedType.GetMethod(ilMethod.Name).CreateDelegate(delegateType);

                return(new ComputeResult()
                {
                    Method = ilMethod,
                    Delegate = writerDelegate
                });
            }


            return(new ComputeResult()
            {
                Method = ilMethod,
                Delegate = null
            });
        }
Exemple #12
0
        private static BoisComplexTypeInfo ReadComplexTypeMembers(Type type)
        {
            bool readFields = true, readProps = true;

            var objectAttr = type.GetCustomAttributes(typeof(BoisContractAttribute), false);

            if (objectAttr.Length > 0)
            {
                var boisContract = objectAttr[0] as BoisContractAttribute;
                if (boisContract != null)
                {
                    readFields = boisContract.Fields;

                    readProps = boisContract.Properties;
                }
            }
            var typeInfo = new BoisComplexTypeInfo
            {
                //MemberType = EnBoisMemberType.Object,
                //KnownType = EnBasicKnownType.Unknown,
                //IsContainerObject = true,
                ComplexKnownType = EnComplexKnownType.Unknown,
                BareType         = type,
                IsStruct         = type.IsValueType
            };

            var members = new List <MemberInfo>();

            if (readFields)
            {
                var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
                foreach (var f in fields)
                {
                    var index   = -1;
                    var memProp = f.GetCustomAttributes(typeof(BoisMemberAttribute), false);
                    BoisMemberAttribute boisMember;
                    if (memProp.Length > 0 && (boisMember = (memProp[0] as BoisMemberAttribute)) != null)
                    {
                        if (!boisMember.Included)
                        {
                            continue;
                        }
                        index = boisMember.Index;
                    }

                    if (index > -1)
                    {
                        members.Insert(index, f);
                    }
                    else
                    {
                        members.Add(f);
                    }
                }
            }

            if (readProps)
            {
                var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);

                foreach (var p in props)
                {
                    if (p.CanWrite)
                    {
                        var index   = -1;
                        var memProp = p.GetCustomAttributes(typeof(BoisMemberAttribute), false);
                        BoisMemberAttribute boisMember;
                        if (memProp.Length > 0 && (boisMember = (memProp[0] as BoisMemberAttribute)) != null)
                        {
                            if (!boisMember.Included)
                            {
                                continue;
                            }
                            index = boisMember.Index;
                        }

                        if (index > -1)
                        {
                            members.Insert(index, p);
                        }
                        else
                        {
                            members.Add(p);
                        }
                    }
                }
            }

            typeInfo.Members = members.ToArray();

            return(typeInfo);
        }
Exemple #13
0
        internal static BoisComputedTypeInfo GetRootTypeComputed(
            Type type,
            bool generateReader,
            bool generateWriter
#if EmitAssemblyOut
            , bool outputAssembly = true
#endif
            )
        {
            lock (_computedCache)
            {
                BoisComputedTypeInfo result;
                if (_computedCache.TryGetValue(type, out result))
                {
                    if ((!generateReader || result.ReaderMethod != null) &&
                        (!generateWriter || result.WriterMethod != null))
                    {
                        return(result);
                    }
                }
                else
                {
                    result = new BoisComputedTypeInfo();

                    _computedCache.TryAdd(type, result);
                }

                BoisComplexTypeInfo complexTypeInfo = null;

                if (generateWriter && result.WriterDelegate == null)
                {
                    complexTypeInfo = GetComplexTypeUnCached(type);
                    if (complexTypeInfo == null)
                    {
                        return(result);
                    }
#if EmitAssemblyOut && !NETCOREAPP
                    var computed = BoisTypeCompiler.ComputeWriterSaveAss(type, complexTypeInfo, outputAssembly,
                                                                         (dynamicMethod) =>
                    {
                        // this call is useful for Recursive Methods

                        result.WriterMethod = dynamicMethod;
                    });
#else
                    var computed = BoisTypeCompiler.ComputeWriter(type, complexTypeInfo,
                                                                  (dynamicMethod) =>
                    {
                        // this call is useful for Recursive Methods

                        result.WriterMethod = dynamicMethod;
                    });
#endif
                    result.WriterDelegate = computed.Delegate;
                    result.WriterMethod   = computed.Method;
                }

                if (generateReader && result.ReaderDelegate == null)
                {
                    if (complexTypeInfo == null)
                    {
                        complexTypeInfo = GetComplexTypeUnCached(type);
                        if (complexTypeInfo == null)
                        {
                            return(result);
                        }
                    }

#if EmitAssemblyOut && !NETCOREAPP
                    var computed = BoisTypeCompiler.ComputeReaderSaveAss(type, complexTypeInfo, outputAssembly,
                                                                         (dynamicMethod) =>
                    {
                        // this call is useful for Recursive Methods

                        result.ReaderMethod = dynamicMethod;
                    });
#else
                    var computed = BoisTypeCompiler.ComputeReader(type, complexTypeInfo,
                                                                  (dynamicMethod) =>
                    {
                        // this call is useful for Recursive Methods

                        result.ReaderMethod = dynamicMethod;
                    });
#endif
                    result.ReaderDelegate = computed.Delegate;
                    result.ReaderMethod   = computed.Method;
                }

                return(result);
            }
        }