Ejemplo n.º 1
0
        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;
            }
        }