|
@@ -2,6 +2,8 @@
|
|
|
using System.Collections;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Data;
|
|
|
+using System.Drawing;
|
|
|
+using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Linq.Expressions;
|
|
|
using System.Reflection;
|
|
@@ -19,6 +21,13 @@ namespace InABox.Core
|
|
|
{
|
|
|
DataType = typeof(object);
|
|
|
}
|
|
|
+ public CoreColumn(string columnName) : this(typeof(object), columnName) { }
|
|
|
+
|
|
|
+ public CoreColumn(Type dataType, string columnName)
|
|
|
+ {
|
|
|
+ DataType = dataType;
|
|
|
+ ColumnName = columnName;
|
|
|
+ }
|
|
|
|
|
|
public Type DataType { get; set; }
|
|
|
|
|
@@ -28,6 +37,7 @@ namespace InABox.Core
|
|
|
{
|
|
|
return string.Format("{0} ({1})", ColumnName, DataType.EntityName().Split('.').Last());
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
|
|
|
[Serializable]
|
|
@@ -254,6 +264,7 @@ namespace InABox.Core
|
|
|
_columnindexes[columnname] = -1;
|
|
|
return -1;
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
|
|
|
public class CoreFieldMap<T1, T2>
|
|
@@ -283,7 +294,7 @@ namespace InABox.Core
|
|
|
}
|
|
|
|
|
|
[Serializable]
|
|
|
- public class CoreTable : ICoreTable //: IEnumerable, INotifyCollectionChanged
|
|
|
+ public class CoreTable : ICoreTable, ISerializeBinary //: IEnumerable, INotifyCollectionChanged
|
|
|
{
|
|
|
|
|
|
#region Fields
|
|
@@ -714,7 +725,233 @@ namespace InABox.Core
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+ #region Serialize Binary
|
|
|
+
|
|
|
+ private static void WriteValue(BinaryWriter writer, Type type, object? value)
|
|
|
+ {
|
|
|
+ value ??= CoreUtils.GetDefault(type);
|
|
|
+ if (type == typeof(byte[]) && value is byte[] bArray)
|
|
|
+ {
|
|
|
+ writer.Write(bArray.Length);
|
|
|
+ writer.Write(bArray);
|
|
|
+ }
|
|
|
+ else if (type == typeof(byte[]) && value is null)
|
|
|
+ {
|
|
|
+ writer.Write(0);
|
|
|
+ }
|
|
|
+ else if (type.IsArray && value is Array array)
|
|
|
+ {
|
|
|
+ var elementType = type.GetElementType();
|
|
|
+ writer.Write(array.Length);
|
|
|
+ foreach (var val1 in array)
|
|
|
+ {
|
|
|
+ WriteValue(writer, elementType, val1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (type.IsArray && value is null)
|
|
|
+ {
|
|
|
+ writer.Write(0);
|
|
|
+ }
|
|
|
+ else if (type.IsEnum && value is Enum e)
|
|
|
+ {
|
|
|
+ var underlyingType = type.GetEnumUnderlyingType();
|
|
|
+ WriteValue(writer, underlyingType, Convert.ChangeType(e, underlyingType));
|
|
|
+ }
|
|
|
+ else if (type == typeof(bool) && value is bool b)
|
|
|
+ {
|
|
|
+ writer.Write(b);
|
|
|
+ }
|
|
|
+ else if (type == typeof(string) && value is string str)
|
|
|
+ {
|
|
|
+ writer.Write(str);
|
|
|
+ }
|
|
|
+ else if (type == typeof(string) && value is null)
|
|
|
+ {
|
|
|
+ writer.Write("");
|
|
|
+ }
|
|
|
+ else if (type == typeof(Guid) && value is Guid guid)
|
|
|
+ {
|
|
|
+ writer.Write(guid.ToByteArray());
|
|
|
+ }
|
|
|
+ else if (type == typeof(byte) && value is byte i8)
|
|
|
+ {
|
|
|
+ writer.Write(i8);
|
|
|
+ }
|
|
|
+ else if (type == typeof(Int16) && value is Int16 i16)
|
|
|
+ {
|
|
|
+ writer.Write(i16);
|
|
|
+ }
|
|
|
+ else if (type == typeof(Int32) && value is Int32 i32)
|
|
|
+ {
|
|
|
+ writer.Write(i32);
|
|
|
+ }
|
|
|
+ else if (type == typeof(Int64) && value is Int64 i64)
|
|
|
+ {
|
|
|
+ writer.Write(i64);
|
|
|
+ }
|
|
|
+ else if (type == typeof(float) && value is float f32)
|
|
|
+ {
|
|
|
+ writer.Write(f32);
|
|
|
+ }
|
|
|
+ else if (type == typeof(double) && value is double f64)
|
|
|
+ {
|
|
|
+ writer.Write(f64);
|
|
|
+ }
|
|
|
+ else if (type == typeof(DateTime) && value is DateTime date)
|
|
|
+ {
|
|
|
+ writer.Write(date.Ticks);
|
|
|
+ }
|
|
|
+ else if (type == typeof(TimeSpan) && value is TimeSpan time)
|
|
|
+ {
|
|
|
+ writer.Write(time.Ticks);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ throw new Exception($"Invalid type; Target DataType is {type} and value DataType is {value?.GetType().ToString() ?? "null"}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void WriteBinary(BinaryWriter writer, bool includeColumns)
|
|
|
+ {
|
|
|
+ writer.Write(TableName);
|
|
|
+
|
|
|
+ if (includeColumns)
|
|
|
+ {
|
|
|
+ foreach (var column in Columns)
|
|
|
+ {
|
|
|
+ writer.Write(true);
|
|
|
+ writer.Write(column.ColumnName);
|
|
|
+ writer.Write(column.DataType.EntityName());
|
|
|
+ }
|
|
|
+ writer.Write(false);
|
|
|
+ }
|
|
|
+
|
|
|
+ writer.Write(Rows.Count);
|
|
|
+ foreach (var row in Rows)
|
|
|
+ {
|
|
|
+ foreach (var col in Columns)
|
|
|
+ {
|
|
|
+ var val = row[col.ColumnName];
|
|
|
+ WriteValue(writer, col.DataType, val);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void SerializeBinary(BinaryWriter writer) => WriteBinary(writer, true);
|
|
|
+
|
|
|
+ private static object? ReadValue(BinaryReader reader, Type type)
|
|
|
+ {
|
|
|
+ if (type == typeof(byte[]))
|
|
|
+ {
|
|
|
+ var length = reader.ReadInt32();
|
|
|
+ return reader.ReadBytes(length);
|
|
|
+ }
|
|
|
+ else if (type.IsArray)
|
|
|
+ {
|
|
|
+ var length = reader.ReadInt32();
|
|
|
+ var elementType = type.GetElementType();
|
|
|
+
|
|
|
+ var array = Array.CreateInstance(elementType, length);
|
|
|
+ for (int i = 0; i < array.Length; ++i)
|
|
|
+ {
|
|
|
+ array.SetValue(ReadValue(reader, elementType), i);
|
|
|
+ }
|
|
|
+ return array;
|
|
|
+ }
|
|
|
+ else if (type.IsEnum)
|
|
|
+ {
|
|
|
+ var val = ReadValue(reader, type.GetEnumUnderlyingType());
|
|
|
+ return Enum.ToObject(type, val);
|
|
|
+ }
|
|
|
+ else if (type == typeof(bool))
|
|
|
+ {
|
|
|
+ return reader.ReadBoolean();
|
|
|
+ }
|
|
|
+ else if (type == typeof(string))
|
|
|
+ {
|
|
|
+ return reader.ReadString();
|
|
|
+ }
|
|
|
+ else if (type == typeof(Guid))
|
|
|
+ {
|
|
|
+ return new Guid(reader.ReadBytes(16));
|
|
|
+ }
|
|
|
+ else if (type == typeof(byte))
|
|
|
+ {
|
|
|
+ return reader.ReadByte();
|
|
|
+ }
|
|
|
+ else if (type == typeof(Int16))
|
|
|
+ {
|
|
|
+ return reader.ReadInt16();
|
|
|
+ }
|
|
|
+ else if (type == typeof(Int32))
|
|
|
+ {
|
|
|
+ return reader.ReadInt32();
|
|
|
+ }
|
|
|
+ else if (type == typeof(Int64))
|
|
|
+ {
|
|
|
+ return reader.ReadInt64();
|
|
|
+ }
|
|
|
+ else if (type == typeof(float))
|
|
|
+ {
|
|
|
+ return reader.ReadSingle();
|
|
|
+ }
|
|
|
+ else if (type == typeof(double))
|
|
|
+ {
|
|
|
+ return reader.ReadDouble();
|
|
|
+ }
|
|
|
+ else if (type == typeof(DateTime))
|
|
|
+ {
|
|
|
+ return new DateTime(reader.ReadInt64());
|
|
|
+ }
|
|
|
+ else if (type == typeof(TimeSpan))
|
|
|
+ {
|
|
|
+ return new TimeSpan(reader.ReadInt64());
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ throw new Exception($"Invalid type; Target DataType is {type}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void ReadBinary(BinaryReader reader, IList<CoreColumn>? columns)
|
|
|
+ {
|
|
|
+ TableName = reader.ReadString();
|
|
|
+
|
|
|
+ Columns.Clear();
|
|
|
+ if (columns is null)
|
|
|
+ {
|
|
|
+ while (reader.ReadBoolean())
|
|
|
+ {
|
|
|
+ var columnName = reader.ReadString();
|
|
|
+ var dataType = CoreUtils.GetEntity(reader.ReadString());
|
|
|
+ Columns.Add(new CoreColumn(dataType, columnName));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ foreach (var column in columns)
|
|
|
+ {
|
|
|
+ Columns.Add(column);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Rows.Clear();
|
|
|
+ var nRows = reader.ReadInt32();
|
|
|
+ for (int i = 0; i < nRows; ++i)
|
|
|
+ {
|
|
|
+ var row = NewRow();
|
|
|
+ foreach (var column in Columns)
|
|
|
+ {
|
|
|
+ var value = ReadValue(reader, column.DataType);
|
|
|
+ row.Values.Add(value);
|
|
|
+ }
|
|
|
+ Rows.Add(row);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void DeserializeBinary(BinaryReader reader) => ReadBinary(reader, null);
|
|
|
+
|
|
|
+ #endregion
|
|
|
}
|
|
|
|
|
|
public class CoreTableAdapter<T> : IEnumerable<T> where T : BaseObject, new()
|