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; } }
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; } }
/// <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; } }
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; } }
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 }); }
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); } }
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); } }
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); }
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 }); }
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 }); }
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 }); }
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); }
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); } }