public byte[] ToGlbBytes(SerializerTypes serializer = SerializerTypes.UniJSON) { string json; if (serializer == SerializerTypes.UniJSON) { var c = new JsonSchemaValidationContext(this) { EnableDiagnosisForNotRequiredFields = true, }; json = JsonSchema.FromType(GetType()).Serialize(this, c); } else if (serializer == SerializerTypes.Generated) { var f = new JsonFormatter(); f.GenSerialize(this); json = f.ToString().ParseAsJson().ToString(" "); } else if (serializer == SerializerTypes.JsonSerializable) { // Obsolete json = ToJson(); } else { throw new Exception("[UniVRM Export Error] unknown serializer type"); } RemoveUnusedExtensions(json); return(Glb.ToBytes(json, buffers[0].GetBytes())); }
public static void Serialize(object instance, out string xmlContent, out string serializerType) { SerializerTypes serializerTypeValue = SerializerTypes.Primitive; xmlContent = string.Empty; Type instanceType = typeof(object); if (instance != null) { if (instanceType.IsPrimitive || instanceType == typeof(string)) { xmlContent = string.Format("<{0}>{1}</{0}>", instanceType.Name, instance); } else if (instanceType.GetCustomAttributes(typeof(SerializableAttribute), true).FirstOrDefault() != null) { serializerTypeValue = SerializerTypes.XmlSerializer; StringWriter sww = new StringWriter(); XmlWriter writer = XmlWriter.Create(sww); System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(instanceType); serializer.Serialize(sww, instanceType); xmlContent = sww.ToString(); } else { serializerTypeValue = SerializerTypes.XmlObjectSerializer; XmlObjectSerializer serializer = new XmlObjectSerializer(); xmlContent = serializer.Serialize(instance, instanceType).OuterXml; } } serializerType = string.Format(SerializerTypeFormat, serializerTypeValue, instanceType.AssemblyQualifiedName); }
/// <summary> /// Retrieves a setting from storage. /// </summary> /// <typeparam name="T">Type of the stored value.</typeparam> /// <param name="key">Unique key for the setting.</param> /// <param name="location">Location the setting should be retrieved from.</param> /// <param name="serializerType">How the setting should be serialized to storage.</param> /// <returns>Awaitable task is returned.</returns> public T LoadSetting <T>(string key, ApplicationDataContainer container, SerializerTypes serializerType = SerializerTypes.Default) { if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException(nameof(key)); } try { if (container.Values.ContainsKey(key)) { // Don't deserialize the value if its a primitive type if (TypeUtility.IsPrimitive(typeof(T))) { return((T)container.Values[key]); } else { return(Serializer.Deserialize <T>(container.Values[key].ToString(), serializerType)); } } else { return(default(T)); // Not found in the container return the default value. } } catch (Exception ex) { Platform.Current.Logger.LogError(ex, "Error retrieving key '{0}' from container '{1}' using '{2}' serializer.", key, container.Locality, serializerType); return(default(T)); } }
public static T Read(Stream stream, T instance, int version) { var minSupportedVersion = SerializerTypes.GetMinSupported(Type); if (version < minSupportedVersion) { throw new InvalidDataException($"Received version less than minimum supported ({ version } < { minSupportedVersion })"); } var boxedInstance = (object)instance; while (true) { var token = stream.ReadString(); if (token == SerializerTypes.TypeEndToken) { break; } if (!FieldsMap.TryGetValue(token, out BinField binField)) { continue; } var value = BinSerializer <object> .Deserialize(stream); binField.SetValue(boxedInstance, value); } return((T)boxedInstance); }
public static IImageSerializer Get(SerializerTypes serializerTypes) { switch (serializerTypes) { case SerializerTypes.BasicSerializer: return new BasicImageSerializer(); } return new DefaultImageSerializer(); }
public static IImageSerializer Get(SerializerTypes serializerTypes) { switch (serializerTypes) { case SerializerTypes.BasicSerializer: return(new BasicImageSerializer()); } return(new DefaultImageSerializer()); }
public void TestManual() { SerializerTypes.AddType( new BinTypeDescription(typeof(Manual), "Manual") , new BinTypeVersion(10, 0) , BinTypeProcess.Create <Manual>(Manual.Write, Manual.Read) ); var input = new Manual(); input.FieldOne = "asd"; input.FieldTwo = "lsd"; var output = SerializeDeserialize(input); Assert.AreEqual(input.FieldOne, output.FieldOne); Assert.AreEqual(input.FieldTwo, output.FieldTwo); }
public void CallbacksManualTest() { SerializerTypes.AddType( new BinTypeDescription(typeof(CallbacksTestManualType), "CallbacksTestManualType") , new BinTypeVersion(42, 0) , BinTypeProcess.Create <CallbacksTestManualType>(CallbacksTestManualType.Write, CallbacksTestManualType.Read) ); var instance = new CallbacksTestManualType(); instance.First = 10; var result = SerializeDeserialize(instance); Assert.AreEqual(result.First, 10); Assert.AreEqual(result.Second, 10); Assert.AreEqual(result.FromFirstAndSecond, 100); }
/// <summary> /// Deserializes a string back into an instance of an object. /// </summary> /// <typeparam name="T">Type of the object to be returned.</typeparam> /// <param name="data">String data to be deserialized.</param> /// <param name="serializerType">Use the default serializer or specific a particular serializer.</param> /// <returns>Object instance from the deserialized data string.</returns> public static T Deserialize <T>(string data, SerializerTypes serializerType = SerializerTypes.Default) { if (serializerType == SerializerTypes.Default) { serializerType = DefaultSerializerType; } switch (serializerType) { case SerializerTypes.Xml: return(DeserializeFromXml <T>(data)); case SerializerTypes.Json: return(DeserializeFromJson <T>(data)); default: throw new NotSupportedException("Unrecognized file type " + serializerType); } }
/// <summary> /// Serialize an object to string. /// </summary> /// <param name="obj">Object to serialize.</param> /// <param name="serializerType">Use the default serializer or specific a particular serializer.</param> /// <returns>String returned from the serializer.</returns> public static string Serialize(object obj, SerializerTypes serializerType = SerializerTypes.Default) { if (serializerType == SerializerTypes.Default) { serializerType = DefaultSerializerType; } switch (serializerType) { case SerializerTypes.Xml: return(SerializeToXml(obj)); case SerializerTypes.Json: return(SerializeToJson(obj)); default: throw new NotImplementedException("Unrecognized file type " + serializerType); } }
public void TestManualGeneric() { var write = typeof(SerializeTests).GetMethod("WriteManualGeneric", BindingFlags.Static | BindingFlags.Public); var read = typeof(SerializeTests).GetMethod("ReadManualGeneric", BindingFlags.Static | BindingFlags.Public); SerializerTypes.AddType( new BinTypeDescription(typeof(ManualGenericType <,>), "ManualGenericType") , new BinTypeVersion(10, 0) , BinTypeProcess.Create(write, read) ); var input = new ManualGenericType <string, string>(); input.FieldOne = "asd"; input.FieldTwo = "lsd"; var output = SerializeDeserialize(input); Assert.AreEqual(input.FieldOne, output.FieldOne); Assert.AreEqual(input.FieldTwo, output.FieldTwo); }
private static void GetSerializerDetails(string serializerType, out SerializerTypes serializerTypeValue, out Type serializedType) { serializerTypeValue = default(SerializerTypes); serializedType = default(Type); int index = serializerType.IndexOf("."); string serializerTypeValueString = serializerType.Substring(0, serializerType.IndexOf(".")); string serializedTypeName = serializerType.Substring(index + 1); if (SerializationHelper.PrimitiveTypes.Contains(serializedTypeName)) { serializedType = SerializationHelper.PrimitiveTypes[serializedTypeName]; serializerTypeValue = SerializerTypes.Primitive; return; } else if (serializedTypeName.IsAny(StringComparison.OrdinalIgnoreCase, "int", "string", "double", "float", "long")) { serializedType = Type.GetType(serializedTypeName); serializerTypeValue = (SerializerTypes)Enum.Parse(typeof(SerializerTypes), serializerTypeValueString); } }
/// <summary> /// Gets data from the specified URL. /// </summary> /// <typeparam name="T">Type for the strongly typed class representing data returned from the URL.</typeparam> /// <param name="url">URL to retrieve data from.</param> /// <param name="serializerType">Specifies how the data should be deserialized.</param> /// <param name="retryCount">Number of retry attempts if a call fails. Default is zero.</param> /// <returns>Instance of the type specified representing the data returned from the URL.</returns> /// <summary> protected async Task <T> GetAsync <T>(string url, CancellationToken?ct = null, SerializerTypes serializerType = SerializerTypes.Default) { if (string.IsNullOrEmpty(url)) { throw new ArgumentNullException(nameof(url)); } var response = await this.Client.GetAsync(new Uri(this.BaseUri, url)).AsTask(ct.HasValue ? ct.Value : CancellationToken.None); this.Log(response); response.EnsureSuccessStatusCode(); var data = await response.Content.ReadAsStringAsync(); return(Serializer.Deserialize <T>(data, serializerType)); }
private static void GetSerializerDetails(string serializerType, out SerializerTypes serializerTypeValue, out Type serializedType) { serializerTypeValue = default(SerializerTypes); serializedType = default(Type); int index = serializerType.IndexOf("."); string serializerTypeValueString = serializerType.Substring(0, serializerType.IndexOf(".")); string serializedTypeName = serializerType.Substring(index + 1); if (SerializationHelper.PrimitiveTypes.Contains(serializedTypeName)) { serializedType = SerializationHelper.PrimitiveTypes[serializedTypeName]; serializerTypeValue = SerializerTypes.Primitive; return; } else if (serializedTypeName.IsAny(StringComparison.OrdinalIgnoreCase, "int", "string", "double", "float", "long")) { serializedType = Type.GetType(serializedTypeName); serializerTypeValue = (SerializerTypes) Enum.Parse(typeof(SerializerTypes), serializerTypeValueString); } }
/// <summary> /// Saves a string to file in storage. /// </summary> /// <param name="path">Path and name of the file.</param> /// <param name="data">Data to write to file.</param> /// <param name="location">Location to store the file.</param> /// <returns>Awaitable task returning the final file path in storage.</returns> public async Task <StorageFile> SaveFileAsync(string path, object data, StorageFolder folder, SerializerTypes serializerType = SerializerTypes.Default) { if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentNullException(nameof(path)); } // Serialize the object to string string dataAsString = null; if (data is string) { dataAsString = data.ToString(); } else if (data != null) { dataAsString = Serializer.Serialize(data, serializerType); } if (string.IsNullOrEmpty(dataAsString)) { // Delete the file if null or empty string. await this.DeleteFileAsync(path, folder); return(null); } else { // Get to the requested folder destination in the path. StorageFolder destinationFolder = await this.GetToFolderFromPathAsync(path, folder, true); // Create the file StorageFile textFile = await destinationFolder.CreateFileAsync(Path.GetFileName(path), CreationCollisionOption.ReplaceExisting); // Write string data to file. using (IRandomAccessStream textStream = await textFile.OpenAsync(FileAccessMode.ReadWrite)) { using (DataWriter textWriter = new DataWriter(textStream)) { textWriter.WriteString(dataAsString); await textWriter.StoreAsync(); } } // Return handle to file return(textFile); } }
/// <summary> /// Loads a file from storage. /// </summary> /// <typeparam name="T">Type representing the data stored.</typeparam> /// <param name="path">Path and name of the file.</param> /// <param name="folder">Which storage location to retrieve the file from.</param> /// <returns>String contents from the file or null if it doesn't exists.</returns> /// <returns>Awaitable task of type specified.</returns> public async Task <T> LoadFileAsync <T>(string path, StorageFolder folder, SerializerTypes fileType = SerializerTypes.Default) { string data = await this.ReadFileAsStringAsync(path, folder); return(Serializer.Deserialize <T>(data, fileType)); }
/// <summary> /// Saves a setting to storage. /// </summary> /// <param name="key">Unique key for the setting.</param> /// <param name="obj">Value to store.</param> /// <param name="location">Location the setting should be stored to.</param> /// <param name="serializerType">How the setting should be deserialized from storage.</param> public void SaveSetting(string key, object obj, ApplicationDataContainer container, SerializerTypes serializerType = SerializerTypes.Default) { if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException(nameof(key)); } // Remove the value if null if (obj == null) { if (container.Values.ContainsKey(key)) { container.Values.Remove(key); } return; } // Don't serialize the object if its a primitive type. object value = null; if (TypeUtility.IsPrimitive(obj.GetType())) { value = obj; } else { value = Serializer.Serialize(obj, serializerType); } // Update or add the setting. if (container.Values.ContainsKey(key)) { container.Values[key] = value; } else { container.Values.Add(key, value); } }
/// <summary> /// Saves a setting to the LocalSettings container. /// </summary> /// <param name="key">Unique key for the setting.</param> /// <param name="obj">Object to store in the LocalSettings container.</param> /// <param name="serializerType">How the setting should be serialized to storage.</param> public void SaveSetting(string key, object obj, SerializerTypes serializerType = SerializerTypes.Default) { this.SaveSetting(key, obj, ApplicationData.Current.LocalSettings, serializerType); }
public SerializerTypeAttribute(string projectHomeUrl, SerializerTypes serializerTypeDescription) { ProjectHomeUrl = projectHomeUrl; SerializerTypeDescription = serializerTypeDescription; }
/// <summary> /// Loads a setting from storage. /// </summary> /// <typeparam name="T">Type of the object stored in settings.</typeparam> /// <param name="key">Unique key for the setting.</param> /// <param name="serializerType">How the setting should be serialized to storage.</param> /// <returns>Object instance of the type specified if found else null.</returns> public T LoadSetting <T>(string key, SerializerTypes serializerType = SerializerTypes.Default) { return(this.LoadSetting <T>(key, ApplicationData.Current.LocalSettings, serializerType)); }
private static void GenerateArrayWriter(ILGenerator il, TypeImpl type) { var elementType = type.TypeInfo.GetElementType(); var getRefId = typeof(RefWriterWatcher) .GetTypeInfo() .GetMethod(nameof(RefWriterWatcher.GetRefId), BindingFlags.Public | BindingFlags.Static); var getLowerBound = typeof(Array) .GetTypeInfo() .GetMethod(nameof(Array.GetLowerBound), BindingFlags.Instance | BindingFlags.Public); var serialize = typeof(BinSerializer <>) .MakeGenericType(elementType) .GetTypeInfo() .GetMethod(nameof(BinSerializer <object> .Serialize), BindingFlags.Static | BindingFlags.Public); il.DeclareLocal(typeof(int)); // Array length il.DeclareLocal(typeof(int)); // Array index il.DeclareLocal(typeof(bool)); // Ref id created flag var skipLabel = il.DefineLabel(); var zeroBased = il.DefineLabel(); var loopLabel = il.DefineLabel(); var exitLoopLabel = il.DefineLabel(); BSDebug.TraceStart(il, "Write " + type.TypeInfo.Name); // Write type il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldstr, SerializerTypes.GetTypeId(type)); il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamWriter(typeof(string))); // Write refId il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Ldarg_1); // Load obj il.Emit(OpCodes.Ldloca_S, (byte)2); // Load address of bool local il.Emit(OpCodes.Call, getRefId); // Obj => RefId il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamWriter(typeof(int))); // Check case when reference type already serialized. // If null be returned then created flag be zero too and serialization will be skipped. il.Emit(OpCodes.Ldloc_2); il.Emit(OpCodes.Brfalse, skipLabel); var dim = type.TypeInfo.GetArrayRank(); if (dim == 1) { // Dimension check il.Emit(OpCodes.Ldarg_1); // Load array il.Emit(OpCodes.Ldc_I4_0); // Load zero (0 dim) il.Emit(OpCodes.Callvirt, getLowerBound); // Get lower bound of 0 dim il.Emit(OpCodes.Brfalse, zeroBased); // If result 0 then jump to zeroBased // Throw exception if non zero based il.Emit(OpCodes.Ldstr, "Non zero based arrays not supported."); il.Emit(OpCodes.Newobj, typeof(InvalidOperationException).GetTypeInfo().GetConstructor(new[] { typeof(string) })); il.Emit(OpCodes.Throw); // Write array length il.MarkLabel(zeroBased); il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Ldarg_1); // Load array il.Emit(OpCodes.Ldlen); // Load array length il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamWriter(typeof(int))); // Set array length il.Emit(OpCodes.Ldarg_1); // Load array il.Emit(OpCodes.Ldlen); // Load array length il.Emit(OpCodes.Stloc_0); // Set to 0 local // Set array index to 0 il.Emit(OpCodes.Ldc_I4_0); // Load 0 il.Emit(OpCodes.Stloc_1); // Set to 1 local // Loop start il.MarkLabel(loopLabel); // Loop check il.Emit(OpCodes.Ldloc_0); // Load array length il.Emit(OpCodes.Ldloc_1); // Load current index il.Emit(OpCodes.Beq, exitLoopLabel); // If equals then exit // Write element to stream il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Ldarg_1); // Load array il.Emit(OpCodes.Ldloc_1); // Load current index il.Emit(OpCodes.Ldelem, elementType); // Load element il.Emit(OpCodes.Call, serialize); // Inrement il.Emit(OpCodes.Ldloc_1); // Load current index il.Emit(OpCodes.Ldc_I4_1); // Load 1 il.Emit(OpCodes.Add); // Add il.Emit(OpCodes.Stloc_1); // Set current index // Jump to loop start il.Emit(OpCodes.Br, loopLabel); } else { throw new NotSupportedException("Arrays with non single dimension not supported."); } // Skipped il.MarkLabel(skipLabel); il.MarkLabel(exitLoopLabel); BSDebug.TraceEnd(il, "Write " + type.TypeInfo.FullName); // End il.Emit(OpCodes.Ret); }
private static void GenerateObjectReader(ILGenerator il, TypeImpl type) { var addRef = typeof(RefReaderWatcher) .GetTypeInfo() .GetMethod(nameof(RefReaderWatcher.AddRef), BindingFlags.Public | BindingFlags.Static) .MakeGenericMethod(type.Type); var tryGetRef = typeof(RefReaderWatcher) .GetTypeInfo() .GetMethod(nameof(RefReaderWatcher.TryGetRef), BindingFlags.Public | BindingFlags.Static) .MakeGenericMethod(type.Type); var getTypeFromHandle = typeof(Type) .GetTypeInfo() .GetMethod(nameof(Type.GetTypeFromHandle), BindingFlags.Public | BindingFlags.Static); var defaultCtor = type.TypeInfo.GetConstructor(Type.EmptyTypes); var getUninitializedObject = typeof(FormatterServices) .GetTypeInfo() .GetMethod(nameof(FormatterServices.GetUninitializedObject), BindingFlags.Public | BindingFlags.Static); var dynamicObjectRead = typeof(DynamicObjectReader <>) .MakeGenericType(type.Type) .GetTypeInfo() .GetMethod(nameof(DynamicObjectReader <object> .Read), BindingFlags.Public | BindingFlags.Static); var stringEquals = typeof(string) .GetTypeInfo() .GetMethod(nameof(string.Equals), new[] { typeof(string), typeof(string), typeof(StringComparison) }); var onDeserialized = typeof(IBinSerializable).GetMethod(nameof(IBinSerializable.OnDeserialized)); il.DeclareLocal(typeof(int)); // ref if il.DeclareLocal(type.Type); // readed object il.DeclareLocal(typeof(string)); // last readed field id il.DeclareLocal(typeof(int)); // readed object version il.DeclareLocal(typeof(DeserializationInfo)); // info var resultLabel = il.DefineLabel(); var readFastLabel = il.DefineLabel(); // Process reference id if (!type.TypeInfo.IsValueType) { var tryLoadReferenceLabel = il.DefineLabel(); // Read reference id il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamReader(typeof(int))); // Read ref id il.Emit(OpCodes.Dup); // Duplicate ref id il.Emit(OpCodes.Stloc_0); // Set ref id to local // Check if result null il.Emit(OpCodes.Brtrue, tryLoadReferenceLabel); // Check if null was written // Null was written (return null) il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stloc_1); // Set result to null il.Emit(OpCodes.Br, resultLabel); // Jump to result // Try get readed reference il.MarkLabel(tryLoadReferenceLabel); il.Emit(OpCodes.Ldloc_0); // Load reference id il.Emit(OpCodes.Ldloca_S, (byte)1); // Load address of result il.Emit(OpCodes.Call, tryGetRef); il.Emit(OpCodes.Brtrue, resultLabel); // Jump to result if reference already exist } // Read version il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamReader(typeof(int))); // Read saved version il.Emit(OpCodes.Stloc_3); // Save version to local var reader = SerializerTypes.TryGetStreamReader(type); if (reader != null) { // Read il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Call, reader); il.Emit(OpCodes.Stloc_1); // Set result to local // Add reference to watcher if (!type.TypeInfo.IsValueType) { il.Emit(OpCodes.Ldloc_0); // Load reference id il.Emit(OpCodes.Ldloc_1); // Load result object reference il.Emit(OpCodes.Call, addRef); } } else { // Create if (!type.TypeInfo.IsValueType) { if (defaultCtor != null) { il.Emit(OpCodes.Newobj, defaultCtor); il.Emit(OpCodes.Stloc_1); // Set result to local } else { il.Emit(OpCodes.Ldtoken, type.Type); il.Emit(OpCodes.Call, getTypeFromHandle); il.Emit(OpCodes.Call, getUninitializedObject); il.Emit(OpCodes.Castclass, type.Type); il.Emit(OpCodes.Stloc_1); // Set result to local } } else { il.Emit(OpCodes.Ldloca_S, (byte)1); // Load result local address il.Emit(OpCodes.Initobj, type.Type); } // Add reference to watcher if (!type.TypeInfo.IsValueType) { il.Emit(OpCodes.Ldloc_0); // Load reference id il.Emit(OpCodes.Ldloc_1); // Load result object reference il.Emit(OpCodes.Call, addRef); } // Read code type version var version = SerializerTypes.GetVersion(type); il.Emit(OpCodes.Ldloc_3); // Load version il.Emit(OpCodes.Ldc_I4, version); // Load program type version il.Emit(OpCodes.Beq, readFastLabel); // Call dynamic read if versions not equal il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Ldloc_1); // Load obj instance il.Emit(OpCodes.Ldloc_3); // Load version il.Emit(OpCodes.Call, dynamicObjectRead); // Do dynamic read il.Emit(OpCodes.Stloc_1); // Set readed value to result local il.Emit(OpCodes.Br, resultLabel); // Jump to return code part il.MarkLabel(readFastLabel); // Read var typeReader = SerializerTypes.TryGetTypeReader(type); if (typeReader != null) { // Read type il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Ldloc_1); // Load obj instance il.Emit(OpCodes.Ldloc_3); // Load version il.Emit(OpCodes.Call, typeReader); il.Emit(OpCodes.Stloc_1); // Set result to local } else { // Read fields Label?nextFieldLabel = null; foreach (var binField in BinField.Get(type.Type)) { var markCurrent = nextFieldLabel != null; if (nextFieldLabel == null) { nextFieldLabel = il.DefineLabel(); } // Read field id il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamReader(typeof(string))); // Read field id il.Emit(OpCodes.Stloc_2); // Save last readed field id // Mark next field label only after field read if (markCurrent) { il.MarkLabel(nextFieldLabel.Value); nextFieldLabel = il.DefineLabel(); } // Compare field id with endToken il.Emit(OpCodes.Ldloc_2); // Load readed field id il.Emit(OpCodes.Ldstr, SerializerTypes.TypeEndToken); // Load endToken id il.Emit(OpCodes.Ldc_I4, (int)StringComparison.Ordinal); // Load comparsion type il.Emit(OpCodes.Call, stringEquals); // Compare il.Emit(OpCodes.Brtrue, resultLabel); // This is the end // Compare field ids, if it not equals then skip read il.Emit(OpCodes.Ldloc_2); // Load readed field id il.Emit(OpCodes.Ldstr, binField.Id); // Load field id il.Emit(OpCodes.Ldc_I4, (int)StringComparison.Ordinal); // Load comparsion type il.Emit(OpCodes.Call, stringEquals); // Compare il.Emit(OpCodes.Brfalse, nextFieldLabel.Value); // These aren't the field your looking for var deserialize = typeof(BinSerializer <>) .MakeGenericType(binField.Type) .GetTypeInfo() .GetMethod(nameof(BinSerializer <object> .Deserialize), BindingFlags.Static | BindingFlags.Public); // Prepeare stack to field set if (type.TypeInfo.IsValueType) { il.Emit(OpCodes.Ldloca_S, (byte)1); } else { il.Emit(OpCodes.Ldloc_1); } // Read field il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Call, deserialize); // Set field binField.EmitWrite(il); } // Mark jump (for last field) if (nextFieldLabel != null) { il.MarkLabel(nextFieldLabel.Value); } // Skip end il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamSkiper(typeof(string))); } } // Return result and invoke callback il.MarkLabel(resultLabel); // Invoke deserialzation callback if (typeof(IBinSerializable).IsAssignableFrom(type.Type)) { il.Emit(OpCodes.Ldloca_S, (byte)4); // Load result local address il.Emit(OpCodes.Ldloc_3); // Load version il.Emit(OpCodes.Call, typeof(DeserializationInfo).GetConstructor(new Type[] { typeof(int) })); il.Emit(OpCodes.Ldloc_1); // Load deserialized object il.Emit(OpCodes.Ldloc_S, (byte)4); // Load created DeserialzationInfo il.Emit(OpCodes.Callvirt, onDeserialized); // Call onDeserialized } // Return result il.Emit(OpCodes.Ldloc_1); BSDebug.TraceEnd(il, "Read " + type.TypeInfo.Name); il.Emit(OpCodes.Ret); }
private static void GenerateArrayReader(ILGenerator il, TypeImpl type) { var elementType = type.TypeInfo.GetElementType(); var addRef = typeof(RefReaderWatcher) .GetTypeInfo() .GetMethod(nameof(RefReaderWatcher.AddRef), BindingFlags.Public | BindingFlags.Static) .MakeGenericMethod(type.Type); var tryGetRef = typeof(RefReaderWatcher) .GetTypeInfo() .GetMethod(nameof(RefReaderWatcher.TryGetRef), BindingFlags.Public | BindingFlags.Static) .MakeGenericMethod(type.Type); var deserialize = typeof(BinSerializer <>) .MakeGenericType(elementType) .GetTypeInfo() .GetMethod(nameof(BinSerializer <object> .Deserialize), BindingFlags.Static | BindingFlags.Public); // array type id already was readed il.DeclareLocal(typeof(int)); // Ref id il.DeclareLocal(typeof(int)); // Array length il.DeclareLocal(typeof(int)); // Current index il.DeclareLocal(type.Type); // Result array var loopLabel = il.DefineLabel(); var resultLabel = il.DefineLabel(); var tryLoadReferenceLabel = il.DefineLabel(); // Read reference id il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamReader(typeof(int))); // Read ref id il.Emit(OpCodes.Dup); // Duplicate ref id il.Emit(OpCodes.Stloc_0); // Set ref id to local // Check if result null il.Emit(OpCodes.Brtrue, tryLoadReferenceLabel); // Check if null was written // Null was written (return null) il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stloc_3); // Set result to null il.Emit(OpCodes.Br, resultLabel); // Jump to result // Try get readed reference il.MarkLabel(tryLoadReferenceLabel); il.Emit(OpCodes.Ldloc_0); // Load reference id il.Emit(OpCodes.Ldloca_S, (byte)3); // Load address of result il.Emit(OpCodes.Call, tryGetRef); il.Emit(OpCodes.Brtrue, resultLabel); // Jump to result if reference already exist // Read array length il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamReader(typeof(int))); // Read length il.Emit(OpCodes.Stloc_1); // Set array length // Set current index il.Emit(OpCodes.Ldc_I4_0); // Load zero il.Emit(OpCodes.Stloc_2); // Set current index // Create array il.Emit(OpCodes.Ldloc_1); // Load array length il.Emit(OpCodes.Newarr, elementType); // Create array il.Emit(OpCodes.Stloc_3); // Set array to local // Set ref id il.Emit(OpCodes.Ldloc_0); // Load reference id il.Emit(OpCodes.Ldloc_3); // Load result object reference il.Emit(OpCodes.Call, addRef); // Loop il.MarkLabel(loopLabel); // Check array end il.Emit(OpCodes.Ldloc_1); // Load length il.Emit(OpCodes.Ldloc_2); // Load index il.Emit(OpCodes.Beq, resultLabel); // Prepare set element il.Emit(OpCodes.Ldloc_3); // Load array il.Emit(OpCodes.Ldloc_2); // Load index // Read value il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Call, deserialize); // Deserialize element // Set element il.Emit(OpCodes.Stelem, elementType); // Inrement index il.Emit(OpCodes.Ldloc_2); // Load index il.Emit(OpCodes.Ldc_I4_1); // Load one il.Emit(OpCodes.Add); // Sum il.Emit(OpCodes.Stloc_2); // Set index // Go to loop start il.Emit(OpCodes.Br, loopLabel); il.MarkLabel(resultLabel); il.Emit(OpCodes.Ldloc_3); // Load result array il.Emit(OpCodes.Ret); }
private static void GenerateObjectWriter(ILGenerator il, TypeImpl type) { var getRefId = typeof(RefWriterWatcher) .GetTypeInfo() .GetMethod(nameof(RefWriterWatcher.GetRefId), BindingFlags.Public | BindingFlags.Static); var onSerializing = typeof(IBinSerializable).GetMethod(nameof(IBinSerializable.OnSerializing)); il.DeclareLocal(typeof(bool)); il.DeclareLocal(typeof(SerializationInfo)); var skipTypeLabel = il.DefineLabel(); BSDebug.TraceStart(il, "Write " + type.TypeInfo.Name); // Invoke deserialzation callback if (typeof(IBinSerializable).IsAssignableFrom(type.Type)) { il.Emit(OpCodes.Ldloca_S, (byte)1); // Load result local address il.Emit(OpCodes.Initobj, typeof(SerializationInfo)); il.Emit(OpCodes.Ldarg_1); // Load serializing object il.Emit(OpCodes.Ldloc_1); // Load created SerializationInfo il.Emit(OpCodes.Callvirt, onSerializing); // Call onSerializing } // Write type il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldstr, SerializerTypes.GetTypeId(type)); il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamWriter(typeof(string))); if (!type.TypeInfo.IsValueType) { // Write refId il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Ldarg_1); // Load obj il.Emit(OpCodes.Ldloca_S, (byte)0); // Load address of bool local il.Emit(OpCodes.Call, getRefId); // Obj => RefId il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamWriter(typeof(int))); // Check case when reference type already serialized. // If null be returned then created flag be zero too and serialization will be skipped. il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Brfalse, skipTypeLabel); } // Write type version var version = SerializerTypes.GetVersion(type); il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Ldc_I4, version); // Load version il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamWriter(typeof(int))); // If writer exist then just write var writer = SerializerTypes.TryGetStreamWriter(type) ?? SerializerTypes.TryGetTypeWriter(type); if (writer != null) { il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Ldarg_1); // Load obj il.Emit(OpCodes.Call, writer); // Write to stream } else { foreach (var binField in BinField.Get(type.Type)) { var skipFieldLabel = il.DefineLabel(); // If field is null then skip it if (!binField.IsValueType) { il.Emit(OpCodes.Ldarg_1); // Load object binField.EmitRead(il); // Read field form object il.Emit(OpCodes.Brfalse, skipFieldLabel); // Skip if field is null } // Write field id il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Ldstr, binField.Id); // Load field id il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamWriter(typeof(string))); var serialize = typeof(BinSerializer <>) .MakeGenericType(binField.Type) .GetTypeInfo() .GetMethod(nameof(BinSerializer <object> .Serialize), BindingFlags.Static | BindingFlags.Public); // Write field il.Emit(OpCodes.Ldarg_0); // Load stream il.Emit(OpCodes.Ldarg_1); // Load object binField.EmitRead(il); // Read field from object il.Emit(OpCodes.Call, serialize); // Write field value // Skip field label il.MarkLabel(skipFieldLabel); } // Write end id il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldstr, SerializerTypes.TypeEndToken); il.Emit(OpCodes.Call, SerializerTypes.TryGetStreamWriter(typeof(string))); } // Skip type label il.MarkLabel(skipTypeLabel); BSDebug.TraceEnd(il, "Write " + type.TypeInfo.Name); // End il.Emit(OpCodes.Ret); }