using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.ComponentModel; using System.Reflection; using System.Diagnostics; using SonicAudioLib.IO; namespace SonicAudioLib.CriMw.Serialization { public static class CriTableSerializer { public static byte[] Serialize(List objects, CriTableWriterSettings settings) { using (MemoryStream destination = new MemoryStream()) { Serialize(destination, objects, settings); return destination.ToArray(); } } public static void Serialize(string destinationFileName, List objects, CriTableWriterSettings settings) { using (Stream destination = File.Create(destinationFileName)) { Serialize(destination, objects, settings); } } public static void Serialize(Stream destination, List objects, CriTableWriterSettings settings) { Serialize(destination, typeof(T), objects, settings); } public static void Serialize(Stream destination, Type type, ICollection objects, CriTableWriterSettings settings) { ArrayList arrayList = null; if (objects != null) { arrayList = new ArrayList(objects); } CriTableWriter tableWriter = CriTableWriter.Create(destination, settings); string tableName = type.Name; CriSerializableAttribute serAttribute = type.GetCustomAttribute(); if (serAttribute != null && !string.IsNullOrEmpty(serAttribute.TableName)) { tableName = serAttribute.TableName; } tableWriter.WriteStartTable(tableName); SortedList sortedProperties = new SortedList(); foreach (PropertyInfo propertyInfo in type.GetProperties()) { // Add the properties in order CriIgnoreAttribute ignoreAttribute = propertyInfo.GetCustomAttribute(); if (ignoreAttribute != null) { continue; } // Also ignore the properties that are not supportable (except FileInfo and Stream) if (propertyInfo.PropertyType != typeof(FileInfo) && propertyInfo.PropertyType != typeof(Stream) && propertyInfo.PropertyType != typeof(bool) && !propertyInfo.PropertyType.IsEnum && !CriField.FieldTypes.Contains(propertyInfo.PropertyType)) { continue; } CriFieldAttribute fieldAttribute = propertyInfo.GetCustomAttribute(); int order = ushort.MaxValue; if (fieldAttribute != null) { order = fieldAttribute.Order; } while (sortedProperties.ContainsKey(order)) { order++; } sortedProperties.Add(order, propertyInfo); } tableWriter.WriteStartFieldCollection(); foreach (var keyValuePair in sortedProperties) { PropertyInfo propertyInfo = keyValuePair.Value; CriFieldAttribute fieldAttribute = propertyInfo.GetCustomAttribute(); string fieldName = propertyInfo.Name; Type fieldType = propertyInfo.PropertyType; object defaultValue = null; if (fieldType == typeof(FileInfo) || fieldType == typeof(Stream)) { fieldType = typeof(byte[]); } else if (fieldType == typeof(bool)) { fieldType = typeof(byte); } else if (fieldType.IsEnum) { fieldType = Enum.GetUnderlyingType(propertyInfo.PropertyType); } if (fieldAttribute != null) { if (!string.IsNullOrEmpty(fieldAttribute.FieldName)) { fieldName = fieldAttribute.FieldName; } } bool useDefaultValue = false; if (arrayList != null && arrayList.Count > 1) { useDefaultValue = true; defaultValue = propertyInfo.GetValue(arrayList[0]); for (int i = 1; i < arrayList.Count; i++) { object objectValue = propertyInfo.GetValue(arrayList[i]); if (defaultValue != null) { if (!defaultValue.Equals(objectValue)) { useDefaultValue = false; defaultValue = null; break; } } else if (objectValue != null) { useDefaultValue = false; defaultValue = null; break; } } } else if (arrayList == null || (arrayList != null && arrayList.Count == 0)) { useDefaultValue = true; defaultValue = null; } if (defaultValue is bool) { defaultValue = (bool)defaultValue == true ? 1 : 0; } else if (defaultValue is Enum) { defaultValue = Convert.ChangeType(defaultValue, fieldType); } if (useDefaultValue) { tableWriter.WriteField(fieldName, fieldType, defaultValue); } else { tableWriter.WriteField(fieldName, fieldType); } } tableWriter.WriteEndFieldCollection(); // Time for objects. if (arrayList != null) { foreach (object obj in arrayList) { tableWriter.WriteStartRow(); int index = 0; foreach (PropertyInfo propertyInfo in sortedProperties.Values) { object value = propertyInfo.GetValue(obj); Type propertyType = propertyInfo.PropertyType; if (value is bool) { value = (bool)value == true ? 1 : 0; } else if (value is Enum) { value = Convert.ChangeType(value, Enum.GetUnderlyingType(propertyType)); } tableWriter.WriteValue(index, value); index++; } tableWriter.WriteEndRow(); } } tableWriter.WriteEndTable(); tableWriter.Dispose(); } public static List Deserialize(byte[] sourceByteArray) { return Deserialize(sourceByteArray, typeof(T)).OfType().ToList(); } public static List Deserialize(string sourceFileName) { return Deserialize(sourceFileName, typeof(T)).OfType().ToList(); } public static List Deserialize(Stream source) { return Deserialize(source, typeof(T)).OfType().ToList(); } public static ArrayList Deserialize(byte[] sourceByteArray, Type type) { using (MemoryStream source = new MemoryStream(sourceByteArray)) { return Deserialize(source, type); } } public static ArrayList Deserialize(string sourceFileName, Type type) { using (Stream source = File.OpenRead(sourceFileName)) { return Deserialize(source, type); } } public static ArrayList Deserialize(Stream source, Type type) { ArrayList arrayList = new ArrayList(); using (CriTableReader tableReader = CriTableReader.Create(source, true)) { PropertyInfo[] propertyInfos = type.GetProperties(); while (tableReader.Read()) { object obj = Activator.CreateInstance(type); for (int i = 0; i < tableReader.NumberOfFields; i++) { string fieldName = tableReader.GetFieldName(i); foreach (PropertyInfo propertyInfo in propertyInfos) { string fieldNameMatch = propertyInfo.Name; CriFieldAttribute fieldAttribute = propertyInfo.GetCustomAttribute(); if (fieldAttribute != null && !string.IsNullOrEmpty(fieldAttribute.FieldName)) { fieldNameMatch = fieldAttribute.FieldName; } if (fieldName == fieldNameMatch) { object value = tableReader.GetValue(i); if (propertyInfo.PropertyType == typeof(byte[]) && value is Substream) { value = ((Substream)value).ToArray(); } if (propertyInfo.PropertyType == typeof(bool)) { value = (byte)value != 0; } else if (propertyInfo.PropertyType.IsEnum) { value = Enum.ToObject(propertyInfo.PropertyType, value); } propertyInfo.SetValue(obj, value); break; } } } arrayList.Add(obj); } } return arrayList; } } }