public static GTypeInfo Get(Type type) { foreach (GTypeInfo gType in list) { if (type == gType.Type) { return(gType); } } GTypeInfo gtype = new GTypeInfo(); //设置Type gtype.Type = type; //获取FullName gtype.FullName = type.FullName; //获取支持存储的Fields var orgFields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic); gtype.Fields = (from t in orgFields where !t.IsNotSerialized && !t.Name.Contains('<') && SqliteSerialize.GetDbType(t.FieldType) != SqliteSerialize.DBFieldType.NONE select t).ToArray(); //gtype.Fields = (from t in fields where !t.IsNotSerialized select t).ToArray(); //标识是否为集合 bool isCollection = typeof(IGCollectionBase).IsAssignableFrom(type); // bool isCollection = type.(typeof(IGCollectionBase)); //获取createTableSql gtype.CreateTableSql = string.Format( "CREATE TABLE '{0}' ({1})", gtype.FullName, string.Join(",", (from t in gtype.Fields select("'" + t.Name + "' " + SqliteSerialize.GetDbType(t.FieldType)))) + (isCollection ? ",innerList TEXT" : "") ); //获取InsertSql gtype.InsertSql = string.Format( "INSERT INTO '{0}' ({1}) VALUES ({2})", gtype.FullName, string.Join(",", (from t in gtype.Fields select $"'{t.Name}'")) + (isCollection ? ",innerList" : ""), string.Join(",", (from t in gtype.Fields select "@" + t.Name)) + (isCollection ? ",@innerList" : "") ); //获取UpdateSql gtype.UpdateSql = string.Format( "UPDATE '{0}' SET {1} WHERE gid = @gid", gtype.FullName, string.Join(",", (from t in gtype.Fields select($"'{t.Name}' = @{t.Name} "))) + (isCollection ? ",innerList=@innerList" : "") ); //获取DeleteSql gtype.DeleteSql = "DELETE FROM '" + gtype.FullName + "' WHERE gid = @gid"; list.Add(gtype); return(gtype); }
/// <summary> /// 从一条row反序列化gobj对象 /// </summary> /// <param name="gobj"></param> /// <param name="row"></param> void Deserialize(IGObject gobj, DataRow row) { var fields = GTypeInfo.Get(gobj.GetType()).Fields; var columns = row.Table.Columns; for (int columIndex = 0; columIndex < columns.Count; columIndex++) { if (row[columIndex] == DBNull.Value) { continue; } if (columIndex < fields.Length && columns[columIndex].ColumnName == fields[columIndex].Name) //根据columIndex快速匹配 { var field = fields[columIndex]; SetValue(gobj, field, row[columIndex]); } else { for (int fieldIndex = 0; fieldIndex < fields.Length; fieldIndex++) { if (fields[fieldIndex].Name == columns[columIndex].ColumnName) { var field = fields[fieldIndex]; SetValue(gobj, fields[fieldIndex], row[columIndex]); } } } } if (gobj is IGCollectionBase) { var collection = gobj as IGCollectionBase; var str = row["innerList"].ToString(); if (str.Length == 0) { return; } var arr = str.Split('|'); for (int i = 0; i < arr.Length; i++) { int id = Convert.ToInt32(arr[i]); foreach (IGObject obj in loadedObj) { if (obj.GID == id) { collection.InnerList.Add(obj); break; } } } } }
/// <summary> /// 序列化obj及其所有相关的可序列化对象到文件 /// </summary> /// <param name="obj"></param> public void Serialize(IGObject obj) { currentVisited++; //更新对象目标访问次数 sqliteHelper.BeginTransaction(); //开始事务 savedObj.Clear(); //清空保存的对象 InnerSerialize(obj); //序列化对象 var delObj = loadedObj.Except(savedObj); //获取需要删除的对象 foreach (IGObject o in delObj) { sqliteHelper.Execute(GTypeInfo.Get(o.GetType()).DeleteSql, new SQLiteParameter("@gid", o.GID)); } sqliteHelper.Commit(); //提交事务 loadedObj = savedObj; //更新以保存对象列表 var dirties = loadedObj.Where(m => m.GDirty).ToList(); isDirty = false; }
/// <summary> /// 从文件反序列化得到所有对象 /// </summary> /// <returns></returns> public IGObject[] Deserialize(Assembly assembly) { dataTables.Clear(); //获取所有表名称 using (DataSet ds = sqliteHelper.GetDs("SELECT name FROM sqlite_master WHERE type = 'table'")) { dataTables = ds.Tables[0].Rows.Cast <DataRow>() .Select(m => m[0].ToString()) .Where(m => assembly.GetType(m, false) != null) .ToList(); } //获取所有表内容 using (DataSet ds = sqliteHelper.GetDs(string.Join(";", (from t in dataTables select string.Format("SELECT * FROM '{0}'", t)).ToArray()))) { List <DataRow> rows = new List <DataRow>(); for (int i = 0; i < dataTables.Count; i++) { ds.Tables[i].TableName = dataTables[i]; foreach (DataRow row in ds.Tables[i].Rows) { rows.Add(row); } } //实例化所有对象 loadedObj = new List <IGObject>(rows.Count); loadedObj.AddRange((from t in rows select(IGObject) assembly.CreateInstance(t.Table.TableName)).ToArray()); for (int i = 0; i < rows.Count; i++) { int gid = Convert.ToInt32(rows[i]["gid"]); maxGID = gid > maxGID ? gid : maxGID; if (loadedObj[i] == null) { continue; } loadedObj[i].GID = gid; linkArr[gid] = loadedObj[i]; } for (int i = 0; i < rows.Count; i++) { Deserialize(loadedObj[i], rows[i]); loadedObj[i].GDirty = false; } //校验数据库字段是否一致,并修正 bool updateNeed = false; for (int i = 0; i < dataTables.Count; i++) { var columns = ds.Tables[dataTables[i]].Columns; Type type = assembly.GetType(dataTables[i]); foreach (FieldInfo field in GTypeInfo.Get(type).Fields) { if (!columns.Contains(field.Name)) { if (!updateNeed) { sqliteHelper.BeginTransaction(); updateNeed = true; } sqliteHelper.Execute(string.Format("ALTER TABLE '{0}' ADD COLUMN '{1}' {2}", dataTables[i], field.Name, GetDbType(field.FieldType))); } } } if (updateNeed) { sqliteHelper.Commit(); } } return(loadedObj.ToArray()); }
void InnerSerialize(IGObject obj) { if (obj.GVisitCount == currentVisited) { return; } obj.GVisitCount = currentVisited; savedObj.Add(obj); bool create = obj.GID == -1; if (create) { obj.GID = GetGID(); } var typeInfo = GTypeInfo.Get(obj.GetType()); //获取字段值 bool isCollection = obj is IGCollectionBase; SQLiteParameter[] pts = new SQLiteParameter[typeInfo.Fields.Length + (isCollection ? 1 : 0)]; //为每个字段值转换成数据库能接受的值 for (int i = 0; i < typeInfo.Fields.Length; i++) { var field = typeInfo.Fields[i]; var fieldType = field.FieldType; var fieldValue = field.GetValue(obj); object dbFieldValue = null; #region 值转换 if (fieldValue == null) { dbFieldValue = DBNull.Value; } else if (fieldType == typeof(UInt16)) { dbFieldValue = fieldValue; } else if (fieldType == typeof(UInt32)) { dbFieldValue = fieldValue; } else if (fieldType == typeof(UInt64)) { dbFieldValue = fieldValue; } else if (fieldType == typeof(Int16)) { dbFieldValue = fieldValue; } else if (fieldType == typeof(Int32)) { dbFieldValue = fieldValue; } else if (fieldType == typeof(Int64)) { dbFieldValue = fieldValue; } else if (fieldType == typeof(bool)) { dbFieldValue = fieldValue; } else if (fieldType.IsEnum) { dbFieldValue = fieldValue; } else if (typeof(IGObject).IsAssignableFrom(fieldType)) { var gitem = fieldValue as IGObject; if (gitem.GVisitCount < currentVisited) { InnerSerialize(gitem); } dbFieldValue = gitem.GID; } else if (fieldType == typeof(string)) { dbFieldValue = fieldValue; } else if (fieldType == typeof(Single) || fieldType == typeof(Double) || fieldType == typeof(Decimal)) { dbFieldValue = fieldValue; } else if (fieldType == typeof(Point)) { Point p = (Point)fieldValue; dbFieldValue = string.Format("{0},{1}", p.X, p.Y); } else if (fieldType == typeof(Size)) { Size s = (Size)fieldValue; dbFieldValue = string.Format("{0},{1}", s.Width, s.Height); } else if (fieldType == typeof(Rectangle)) { Rectangle r = (Rectangle)fieldValue; dbFieldValue = string.Format("{0},{1},{2},{3}", r.X, r.Y, r.Width, r.Height); } //else if (fieldValue is Image) //{ // MemoryStream ms = new MemoryStream(); // BinaryFormatter b = new BinaryFormatter(); // b.Serialize(ms, fieldValue); // dbFieldValue = ms.GetBuffer(); // ms.Close(); //} #endregion pts[i] = new SQLiteParameter("@" + typeInfo.Fields[i].Name, dbFieldValue); } //如果是集合则额外添加一个字段 if (isCollection) { IGCollectionBase collection = obj as IGCollectionBase; StringBuilder strBuilder = new StringBuilder(collection.InnerList.Count * 2); foreach (object item in collection.InnerList) { IGObject gitem = item as IGObject; if (gitem == null) { continue; } if (gitem.GVisitCount < currentVisited) { InnerSerialize(gitem); } strBuilder.Append(gitem.GID); strBuilder.Append('|'); } if (strBuilder.Length > 0) { strBuilder.Remove(strBuilder.Length - 1, 1); } pts[pts.Length - 1] = new SQLiteParameter("@innerList", strBuilder.ToString()); } //添加或者修改记录 if (create) { if (!dataTables.Contains(typeInfo.FullName)) { sqliteHelper.Execute(typeInfo.CreateTableSql); dataTables.Add(typeInfo.FullName); } sqliteHelper.Execute(typeInfo.InsertSql, pts); obj.GDirty = false; } else if (obj.GDirty) { sqliteHelper.Execute(typeInfo.UpdateSql, pts); obj.GDirty = false; } }