添加自定义 Converter (#31)

* 添加DataTable Converter

* 修改DataSet Converter,支持多个Tables反序列化,此转换器也支持兼容DataTable

* 修改构造方法、工厂方法,添加常用类自定义转换器
This commit is contained in:
milimoe 2023-06-10 01:01:45 +08:00 committed by GitHub
parent 549055a0e8
commit d25dd8d2e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 820 additions and 468 deletions

View File

@ -1,7 +1,15 @@
namespace Milimoe.FunGame.Core.Api.Factory
{
internal class CharacterFactory
{
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Interface.Base;
namespace Milimoe.FunGame.Core.Api.Factory
{
internal class CharacterFactory : IFactory<Character>
{
public Type EntityType => typeof(Character);
public Character Create()
{
return new Character();
}
}
}

View File

@ -1,7 +1,15 @@
namespace Milimoe.FunGame.Core.Api.Factory
{
internal class InventoryFactory
{
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Interface.Base;
namespace Milimoe.FunGame.Core.Api.Factory
{
internal class InventoryFactory : IFactory<Inventory>
{
public Type EntityType => typeof(Inventory);
public Inventory Create()
{
return new Inventory();
}
}
}

View File

@ -1,22 +1,32 @@
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Interface.Base;
using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Api.Factory
{
internal class ItemFactory
internal class ItemFactory : IFactory<Item>
{
internal static Milimoe.FunGame.Core.Entity.Item? GetInstance(ItemType type, int id, string name)
public Type EntityType => _EntityType;
private Type _EntityType = typeof(Item);
public Item Create(ItemType type = ItemType.Passive)
{
Milimoe.FunGame.Core.Entity.Item? item = null;
switch (type)
{
case ItemType.Active:
item = new Milimoe.FunGame.Core.Entity.ActiveItem(id, name);
break;
case ItemType.Passive:
item = new Milimoe.FunGame.Core.Entity.PassiveItem(id, name);
break;
_EntityType = typeof(PassiveItem);
return new PassiveItem();
case ItemType.Active:
default:
_EntityType = typeof(ActiveItem);
return new ActiveItem();
}
return item;
}
public Item Create()
{
return Create(ItemType.Passive);
}
}
}

View File

@ -1,13 +1,21 @@
using System.Data;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Interface.Base;
using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Api.Factory
{
internal class RoomFactory
internal class RoomFactory : IFactory<Room>
{
internal static Room GetInstance(DataSet? DsRoom, DataSet? DsUser, int Index = 0)
public Type EntityType => typeof(Room);
public Room Create()
{
return new Room(DsRoom, DsUser, Index);
return RoomFactory.Create();
}
public static Room Create(long Id = 0, string Roomid = "-1", DateTime? CreateTime = null, User? RoomMaster = null, RoomType RoomType = RoomType.None, RoomState RoomState = RoomState.Created, string Password = "")
{
return new Room(Id, Roomid, CreateTime, RoomMaster, RoomType, RoomState, Password);
}
}
}

View File

@ -1,19 +1,32 @@
using System.Data;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Interface.Base;
using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Api.Factory
{
internal class SkillFactory
internal class SkillFactory : IFactory<Skill>
{
internal static Skill GetInstance(DataSet? DataSet, SkillType type = SkillType.Passive, int Index = 0)
public Type EntityType => _EntityType;
private Type _EntityType = typeof(Skill);
internal Skill Create(SkillType type = SkillType.Passive)
{
Skill skill = type switch
switch (type)
{
SkillType.Active => new ActiveSkill(DataSet, Index),
_ => new PassiveSkill(DataSet, Index)
};
return skill;
case SkillType.Passive:
_EntityType = typeof(PassiveSkill);
return new PassiveSkill();
case SkillType.Active:
default:
_EntityType = typeof(ActiveSkill);
return new ActiveSkill();
}
}
public Skill Create()
{
return Create(SkillType.Passive);
}
}
}

View File

@ -1,13 +1,15 @@
using System.Data;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Interface.Base;
namespace Milimoe.FunGame.Core.Api.Factory
{
internal class UserFactory
internal class UserFactory : IFactory<User>
{
internal static User GetInstance(DataSet? DataSet, int Index = 0)
public Type EntityType => typeof(User);
public User Create()
{
return new User(DataSet, Index);
return new User();
}
}
}

View File

@ -24,7 +24,7 @@ namespace Milimoe.FunGame.Core.Api.Transmittal
/// </summary>
/// <param name="Result">执行结果</param>
/// <returns>影响的行数</returns>
public abstract int Execute(out SQLResult Result);
public abstract int Execute();
/// <summary>
/// 执行一个指定的命令
@ -32,14 +32,14 @@ namespace Milimoe.FunGame.Core.Api.Transmittal
/// <param name="Script">命令</param>
/// <param name="Result">执行结果</param>
/// <returns>影响的行数</returns>
public abstract int Execute(string Script, out SQLResult Result);
public abstract int Execute(string Script);
/// <summary>
/// 查询DataSet
/// </summary>
/// <param name="Result">执行结果</param>
/// <returns>结果集</returns>
public abstract DataSet ExecuteDataSet(out SQLResult Result);
public abstract DataSet ExecuteDataSet();
/// <summary>
/// 执行指定的命令查询DataSet
@ -47,7 +47,7 @@ namespace Milimoe.FunGame.Core.Api.Transmittal
/// <param name="Script">命令</param>
/// <param name="Result">执行结果</param>
/// <returns>结果集</returns>
public abstract DataSet ExecuteDataSet(string Script, out SQLResult Result);
public abstract DataSet ExecuteDataSet(string Script);
/// <summary>
/// 关闭连接

View File

@ -1,5 +1,4 @@
using System.Data;
using Milimoe.FunGame.Core.Api.Factory;
using Milimoe.FunGame.Core.Api.Factory;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Constant;
@ -7,16 +6,73 @@ namespace Milimoe.FunGame.Core.Api.Utility
{
public class Factory
{
private readonly static CharacterFactory CharacterFactory = new();
private readonly static InventoryFactory InventoryFactory = new();
private readonly static ItemFactory ItemFactory = new();
private readonly static RoomFactory RoomFactory = new();
private readonly static SkillFactory SkillFactory = new();
private readonly static UserFactory UserFactory = new();
/// <summary>
/// 获取Room实例
/// 获取角色实例
/// </summary>
/// <param name="DsRoom">Room</param>
/// <param name="DsUser">User(RoomMaster)</param>
/// <param name="Index">取指定行</param>
/// <returns></returns>
public static Room GetRoom(DataSet? DsRoom, DataSet? DsUser, int Index = 0)
public static Character GetCharacter()
{
return RoomFactory.GetInstance(DsRoom, DsUser, Index);
return CharacterFactory.Create();
}
/// <summary>
/// 获取库存实例
/// </summary>
/// <returns></returns>
public static Inventory GetInventory()
{
return InventoryFactory.Create();
}
/// <summary>
/// 获取物品实例默认返回Passiveitem 被动物品 需要强制转换
/// </summary>
/// <param name="type">Item类型 主动 或 被动</param>
/// <returns></returns>
public static Item GetItem(ItemType type = ItemType.Passive)
{
return ItemFactory.Create(type);
}
/// <summary>
/// 获取主动物品实例
/// </summary>
/// <returns></returns>
public static ActiveItem GetActiveItem()
{
return (ActiveItem)ItemFactory.Create(ItemType.Active);
}
/// <summary>
/// 获取被动物品实例
/// </summary>
/// <returns></returns>
public static PassiveItem GetPassiveItem()
{
return (PassiveItem)ItemFactory.Create(ItemType.Passive);
}
/// <summary>
/// 获取房间实例
/// </summary>
/// <param name="Id">房间内部序列号</param>
/// <param name="Roomid">房间号</param>
/// <param name="CreateTime">创建时间</param>
/// <param name="RoomMaster">房主</param>
/// <param name="RoomType">房间类型</param>
/// <param name="RoomState">房间状态</param>
/// <param name="Password">房间密码</param>
/// <returns></returns>
public static Room GetRoom(long Id = 0, string Roomid = "-1", DateTime? CreateTime = null, User? RoomMaster = null, RoomType RoomType = RoomType.None, RoomState RoomState = RoomState.Created, string Password = "")
{
return RoomFactory.Create(Id, Roomid, CreateTime, RoomMaster, RoomType, RoomState, Password);
}
/// <summary>
@ -25,129 +81,44 @@ namespace Milimoe.FunGame.Core.Api.Utility
/// <returns></returns>
internal static Room GetHall()
{
return GetRoom(null, null);
return RoomFactory.Create();
}
/// <summary>
/// 获取Skill实例默认返回PassiveSkill
/// 获取技能实例默认返回PassiveSkill 被动技能 需要强制转换
/// </summary>
/// <param name="DataSet">SkillRow</param>
/// <param name="SkillType">Skill类型</param>
/// <param name="Index">取指定行</param>
/// <param name="type">Skill类型 主动 或 被动</param>
/// <returns></returns>
public static Skill GetSkill(DataSet? DataSet, SkillType SkillType = SkillType.Passive, int Index = 0)
public static Skill GetSkill(SkillType type = SkillType.Passive)
{
return SkillFactory.GetInstance(DataSet, SkillType, Index);
return SkillFactory.Create(type);
}
/// <summary>
/// 获取User实例
/// </summary>awaa
/// <param name="DataSet">UserRow</param>
/// <param name="Index">取指定行</param>
/// 获取主动技能实例
/// </summary>
/// <returns></returns>
public static User GetUser(DataSet? DataSet, int Index = 0)
public static ActiveSkill GetActiveSkill()
{
return UserFactory.GetInstance(DataSet, Index);
return (ActiveSkill)SkillFactory.Create(SkillType.Active);
}
/// <summary>
/// 获取一个不为NULL的实例
/// <para>Item默认返回PassiveItem</para>
/// <para>Skill默认返回PassiveSkill</para>
/// <para>若无法找到T返回唯一的空对象</para>
/// 获取被动技能实例
/// </summary>
/// <typeparam name="T">Entity类</typeparam>
/// <param name="DataSets">使用DataSets构造对象</param>
/// <returns>T</returns>
public static T GetInstance<T>(params DataSet?[] DataSets)
/// <returns></returns>
public static PassiveSkill GetPassiveSkill()
{
if (DataSets is null || DataSets.Length == 0) throw new GetInstanceException();
object instance = General.EntityInstance;
if (typeof(T) == typeof(User))
{
instance = GetUser(DataSets[0]);
}
else if (typeof(T) == typeof(Skill) || typeof(T) == typeof(PassiveSkill))
{
instance = GetSkill(DataSets[0]);
}
else if (typeof(T) == typeof(ActiveSkill))
{
instance = GetSkill(DataSets[0], SkillType.Active);
}
else if (typeof(T) == typeof(Room))
{
instance = GetRoom(DataSets[0], DataSets[1]);
}
return (T)instance;
return (PassiveSkill)SkillFactory.Create(SkillType.Passive);
}
/// <summary>
/// 获取T的数组
/// <para>Item默认返回PassiveItem数组</para>
/// <para>Skill默认返回PassiveSkill数组</para>
/// <para>若无法找到T返回空数组</para>
/// 获取用户实例
/// </summary>
/// <typeparam name="T">Entity类</typeparam>
/// <param name="DataSets">使用DataSet构造对象数组</param>
/// <returns>List T</returns>
public static List<T> GetList<T>(params DataSet?[] DataSets)
/// <returns></returns>
public static User GetUser()
{
List<T> list = new();
if (DataSets is null || DataSets.Length == 0) throw new GetInstanceException();
if (typeof(T) == typeof(User))
{
DataSet? ds = DataSets[0];
if (ds != null && ds.Tables[0].Rows.Count > 0)
{
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
object entity = GetUser(ds, i);
list.Add((T)entity);
}
}
}
else if (typeof(T) == typeof(Skill) || typeof(T) == typeof(PassiveSkill))
{
DataSet? ds = DataSets[0];
if (ds != null && ds.Tables[0].Rows.Count > 0)
{
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
object entity = GetSkill(ds, SkillType.Passive, i);
list.Add((T)entity);
}
}
}
else if (typeof(T) == typeof(ActiveSkill))
{
DataSet? ds = DataSets[0];
if (ds != null && ds.Tables[0].Rows.Count > 0)
{
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
object entity = GetSkill(ds, SkillType.Active, i);
list.Add((T)entity);
}
}
}
else if (typeof(T) == typeof(Room))
{
DataSet? DsRoom = DataSets[0];
DataSet? DsUser = DataSets[1];
object entity = General.HallInstance;
list.Add((T)entity);
if (DsRoom != null && DsRoom.Tables[0].Rows.Count > 0)
{
for (int i = 0; i < DsRoom.Tables[0].Rows.Count; i++)
{
entity = GetRoom(DsRoom, DsUser, i);
list.Add((T)entity);
}
}
}
return list;
return UserFactory.Create();
}
}
}

View File

@ -50,7 +50,12 @@ namespace Milimoe.FunGame.Core.Entity
public decimal CritRate { get; set; } = 0.05M; // 暴击率
public decimal CritDMG { get; set; } = 1.25M; // 暴击伤害
public decimal EvadeRate { get; set; } = 0.05M; // 闪避率
public Hashtable? Skills { get; set; } = new Hashtable();
public Hashtable? Items { get; set; } = new Hashtable();
public Hashtable Skills { get; set; } = new();
public Hashtable Items { get; set; } = new();
public Character()
{
}
}
}

View File

@ -1,6 +1,4 @@
using System.Data;
namespace Milimoe.FunGame.Core.Entity
namespace Milimoe.FunGame.Core.Entity
{
public class ActiveSkill : Skill
{
@ -17,7 +15,7 @@ namespace Milimoe.FunGame.Core.Entity
public decimal Reference9 { get; set; } = 0;
public decimal Reference10 { get; set; } = 0;
internal ActiveSkill(DataSet? DataSet, int Index = 0)
internal ActiveSkill()
{
Active = true;
}

View File

@ -1,6 +1,4 @@
using System.Data;
namespace Milimoe.FunGame.Core.Entity
namespace Milimoe.FunGame.Core.Entity
{
public class PassiveSkill : Skill
{
@ -15,7 +13,7 @@ namespace Milimoe.FunGame.Core.Entity
public decimal Reference9 { get; set; } = 0;
public decimal Reference10 { get; set; } = 0;
internal PassiveSkill(DataSet? DataSet, int Index = 0)
internal PassiveSkill()
{
Active = false;
}

View File

@ -1,7 +1,5 @@
using System.Data;
using Milimoe.FunGame.Core.Interface.Entity;
using Milimoe.FunGame.Core.Interface.Entity;
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Library.SQLScript.Entity;
namespace Milimoe.FunGame.Core.Entity
{
@ -18,29 +16,15 @@ namespace Milimoe.FunGame.Core.Entity
public string Password { get; set; } = "";
public GameStatistics? Statistics { get; set; } = null;
internal Room(DataSet? DsRoom, DataSet? DsUser, int Index = 0)
internal Room(long Id = 0, string Roomid = "-1", DateTime? CreateTime = null, User? RoomMaster = null, RoomType RoomType = RoomType.None, RoomState RoomState = RoomState.Created, string Password = "")
{
if (DsRoom != null && DsRoom.Tables[0].Rows.Count > 0)
{
DataRow DrRoom = DsRoom.Tables[0].Rows[Index];
Id = (long)DrRoom[RoomQuery.Column_ID];
Roomid = (string)DrRoom[RoomQuery.Column_RoomID];
CreateTime = (DateTime)DrRoom[RoomQuery.Column_CreateTime];
RoomMaster = Api.Utility.Factory.GetUser(DsUser, GetUserRowIndex(DsUser, (long)DrRoom[RoomQuery.Column_RoomMaster]));
RoomType = (RoomType)Convert.ToInt32(DrRoom[RoomQuery.Column_RoomType]);
RoomState = (RoomState)Convert.ToInt32(DrRoom[RoomQuery.Column_RoomState]);
Password = (string)DrRoom[RoomQuery.Column_Password];
}
else
{
Id = 0;
Roomid = "-1";
CreateTime = DateTime.MinValue;
RoomMaster = null;
RoomType = RoomType.None;
RoomState = RoomState.Created;
Password = "";
}
this.Id = Id;
this.Roomid = Roomid;
if (CreateTime != null) this.CreateTime = (DateTime)CreateTime;
if (RoomMaster != null) this.RoomMaster = RoomMaster;
this.RoomType = RoomType;
this.RoomState = RoomState;
this.Password = Password;
}
public bool Equals(Room other)
@ -52,20 +36,5 @@ namespace Milimoe.FunGame.Core.Entity
{
return other?.Id == Id;
}
private static int GetUserRowIndex(DataSet? DsUser, long UID)
{
if (DsUser != null)
{
for (int i = 0; i < DsUser.Tables[0].Rows.Count; i++)
{
if (DsUser.Tables[0].Rows[i][UserQuery.Column_UID].Equals(UID))
{
return i;
}
}
}
return 0;
}
}
}

View File

@ -21,7 +21,7 @@ namespace Milimoe.FunGame.Core.Entity
public decimal GameTime { get; set; } = 0;
public string AutoKey { get; set; } = "";
public UserStatistics? Statistics { get; set; } = null;
public Inventory? Stock { get; set; } = null;
public Inventory? Inventory { get; set; } = null;
internal User()
{

View File

@ -0,0 +1,8 @@
namespace Milimoe.FunGame.Core.Interface.Base
{
public interface IFactory<T>
{
public Type EntityType { get; }
public T Create();
}
}

View File

@ -10,12 +10,13 @@ namespace Milimoe.FunGame.Core.Interface.Base
public string Script { get; set; }
public CommandType CommandType { get; set; }
public SQLResult Result { get; }
public bool Success { get; }
public SQLServerInfo ServerInfo { get; }
public int UpdateRows { get; }
public DataSet DataSet { get; }
public int Execute(out SQLResult Result);
public DataSet ExecuteDataSet(out SQLResult Result);
public int Execute();
public DataSet ExecuteDataSet();
public void Close();
}
}

View File

@ -0,0 +1,154 @@
using System.Data;
using System.Text.Json;
using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
{
internal class ConverterUtility
{
internal static void ReadColumns(Utf8JsonReader reader, DataTable dataTable)
{
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray)
{
break;
}
if (reader.TokenType == JsonTokenType.StartObject)
{
DataColumn column = new();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
string propertyName = reader.GetString() ?? "";
switch (propertyName)
{
case "ColumnName":
reader.Read();
column.ColumnName = reader.GetString();
break;
case "DataType":
reader.Read();
Type dataType = Type.GetType(reader.GetString() ?? "") ?? typeof(object);
column.DataType = dataType;
break;
}
}
if (reader.TokenType == JsonTokenType.EndObject)
{
break;
}
}
dataTable.Columns.Add(column);
}
}
}
internal static void ReadRows(Utf8JsonReader reader, DataTable dataTable)
{
object[] values = new object[dataTable.Columns.Count];
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray)
{
break;
}
if (reader.TokenType == JsonTokenType.StartArray)
{
int index = 0;
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray)
{
break;
}
switch (dataTable.Columns[index].DataType.ToString())
{
case "System.Boolean":
values[index] = reader.GetBoolean();
break;
case "System.Byte":
values[index] = reader.GetByte();
break;
case "System.Char":
values[index] = (reader.GetString() ?? "")[0];
break;
case "System.DateTime":
string dateString = reader.GetString() ?? "";
if (DateTime.TryParseExact(dateString, General.GeneralDateTimeFormat, null, System.Globalization.DateTimeStyles.None, out DateTime result))
{
values[index] = result;
}
else values[index] = DateTime.MinValue;
break;
case "System.Decimal":
values[index] = reader.GetDecimal();
break;
case "System.Double":
values[index] = reader.GetDouble();
break;
case "System.Guid":
values[index] = Guid.Parse(reader.GetString() ?? Guid.Empty.ToString());
break;
case "System.Int16":
values[index] = reader.GetInt16();
break;
case "System.Int32":
values[index] = reader.GetInt32();
break;
case "System.Int64":
values[index] = reader.GetInt64();
break;
case "System.SByte":
values[index] = reader.GetSByte();
break;
case "System.Single":
values[index] = reader.GetSingle();
break;
case "System.String":
values[index] = reader.GetString() ?? "";
break;
case "System.UInt16":
values[index] = reader.GetUInt16();
break;
case "System.UInt32":
values[index] = reader.GetUInt32();
break;
case "System.UInt64":
values[index] = reader.GetUInt64();
break;
}
index++;
}
dataTable.Rows.Add(values);
}
}
}
}
}

View File

@ -2,7 +2,6 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Service;
namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
{
@ -30,17 +29,19 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
case "Columns":
reader.Read();
ReadColumns(reader, dt);
ConverterUtility.ReadColumns(reader, dt);
break;
case "Rows":
reader.Read();
ReadRows(reader, dt);
ConverterUtility.ReadRows(reader, dt);
break;
}
}
}
if (ds.Tables.Count == 0) ds.Tables.Add(new DataTable());
return ds;
}
@ -48,14 +49,19 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
{
writer.WriteStartObject();
if (value.Tables.Count == 0) value.Tables.Add(new DataTable());
writer.WritePropertyName("Tables");
writer.WriteStartArray();
writer.WriteString("TableName", value.Tables[0].TableName);
if (value.Tables.Count > 0) writer.WriteStartObject();
for (int count = 0; count < value.Tables.Count; count++)
{
writer.WriteString("TableName", value.Tables[count].TableName);
writer.WritePropertyName("Columns");
writer.WriteStartArray();
foreach (DataColumn column in value.Tables[0].Columns)
foreach (DataColumn column in value.Tables[count].Columns)
{
writer.WriteStartObject();
@ -70,15 +76,16 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
writer.WritePropertyName("Rows");
writer.WriteStartArray();
foreach (DataRow row in value.Tables[0].Rows)
foreach (DataRow row in value.Tables[count].Rows)
{
writer.WriteStartArray();
for (int i = 0; i < value.Tables[0].Columns.Count; i++)
for (int i = 0; i < value.Tables[count].Columns.Count; i++)
{
object? rowValue = row[i];
var rowValue = row[i];
switch (value.Tables[0].Columns[i].DataType.FullName)
switch (value.Tables[count].Columns[i].DataType.FullName)
{
case "System.Boolean":
writer.WriteBooleanValue((bool)rowValue);
@ -151,154 +158,17 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
writer.WriteEndArray();
if (count + 1 < value.Tables.Count)
{
writer.WriteEndObject();
writer.WriteStartObject();
}
else writer.WriteEndObject();
}
writer.WriteEndArray();
writer.WriteEndObject();
}
#pragma warning disable CA1822 // 不需要设为静态
private void ReadColumns(Utf8JsonReader reader, DataTable dataTable)
#pragma warning restore CA1822 // 不需要设为静态
{
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray)
{
break;
}
if (reader.TokenType == JsonTokenType.StartObject)
{
DataColumn column = new();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
string propertyName = reader.GetString() ?? "";
switch (propertyName)
{
case "ColumnName":
reader.Read();
column.ColumnName = reader.GetString();
break;
case "DataType":
reader.Read();
Type dataType = Type.GetType(reader.GetString() ?? "") ?? typeof(object);
column.DataType = dataType;
break;
}
}
if (reader.TokenType == JsonTokenType.EndObject)
{
break;
}
}
dataTable.Columns.Add(column);
}
}
}
private void ReadRows(Utf8JsonReader reader, DataTable dataTable)
{
object[] values = new object[dataTable.Columns.Count];
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray)
{
break;
}
if (reader.TokenType == JsonTokenType.StartArray)
{
int index = 0;
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray)
{
break;
}
switch (dataTable.Columns[index].DataType.ToString())
{
case "System.Boolean":
values[index] = reader.GetBoolean();
break;
case "System.Byte":
values[index] = reader.GetByte();
break;
case "System.Char":
values[index] = (reader.GetString() ?? "")[0];
break;
case "System.DateTime":
string dateString = reader.GetString() ?? "";
if (DateTime.TryParseExact(dateString, General.GeneralDateTimeFormat, null, System.Globalization.DateTimeStyles.None, out DateTime result))
{
values[index] = result;
}
values[index] = DateTime.MinValue;
break;
case "System.Decimal":
values[index] = reader.GetDecimal();
break;
case "System.Double":
values[index] = reader.GetDouble();
break;
case "System.Guid":
values[index] = Guid.Parse(reader.GetString() ?? Guid.Empty.ToString());
break;
case "System.Int16":
values[index] = reader.GetInt16();
break;
case "System.Int32":
values[index] = reader.GetInt32();
break;
case "System.Int64":
values[index] = reader.GetInt64();
break;
case "System.SByte":
values[index] = reader.GetSByte();
break;
case "System.Single":
values[index] = reader.GetSingle();
break;
case "System.String":
values[index] = reader.GetString() ?? "";
break;
case "System.UInt16":
values[index] = reader.GetUInt16();
break;
case "System.UInt32":
values[index] = reader.GetUInt32();
break;
case "System.UInt64":
values[index] = reader.GetUInt64();
break;
}
index++;
}
dataTable.Rows.Add(values);
}
}
}
}
}

View File

@ -0,0 +1,152 @@
using System.Data;
using System.Text.Json;
using System.Text.Json.Serialization;
using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
{
public class DataTableConverter : JsonConverter<DataTable>
{
public override DataTable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
DataTable dt = new();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
string property = reader.GetString() ?? "";
switch (property)
{
case "TableName":
reader.Read();
string tableName = reader.GetString() ?? "";
dt = new DataTable(tableName);
break;
case "Columns":
reader.Read();
ConverterUtility.ReadColumns(reader, dt);
break;
case "Rows":
reader.Read();
ConverterUtility.ReadRows(reader, dt);
break;
}
}
}
return dt;
}
public override void Write(Utf8JsonWriter writer, DataTable value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WriteString("TableName", value.TableName);
writer.WritePropertyName("Columns");
writer.WriteStartArray();
foreach (DataColumn column in value.Columns)
{
writer.WriteStartObject();
writer.WriteString("ColumnName", column.ColumnName);
writer.WriteString("DataType", column.DataType.FullName);
writer.WriteEndObject();
}
writer.WriteEndArray();
writer.WritePropertyName("Rows");
writer.WriteStartArray();
foreach (DataRow row in value.Rows)
{
writer.WriteStartArray();
for (int i = 0; i < value.Columns.Count; i++)
{
var rowValue = row[i];
switch (value.Columns[i].DataType.FullName)
{
case "System.Boolean":
writer.WriteBooleanValue((bool)rowValue);
break;
case "System.Byte":
writer.WriteNumberValue((byte)rowValue);
break;
case "System.Char":
writer.WriteStringValue(value.ToString());
break;
case "System.DateTime":
writer.WriteStringValue(((DateTime)rowValue).ToString(General.GeneralDateTimeFormat));
break;
case "System.Decimal":
writer.WriteNumberValue((decimal)rowValue);
break;
case "System.Double":
writer.WriteNumberValue((double)rowValue);
break;
case "System.Guid":
writer.WriteStringValue(value.ToString());
break;
case "System.Int16":
writer.WriteNumberValue((short)rowValue);
break;
case "System.Int32":
writer.WriteNumberValue((int)rowValue);
break;
case "System.Int64":
writer.WriteNumberValue((long)rowValue);
break;
case "System.SByte":
writer.WriteNumberValue((sbyte)rowValue);
break;
case "System.Single":
writer.WriteNumberValue((float)rowValue);
break;
case "System.String":
writer.WriteStringValue((string)rowValue);
break;
case "System.UInt16":
writer.WriteNumberValue((ushort)rowValue);
break;
case "System.UInt32":
writer.WriteNumberValue((uint)rowValue);
break;
case "System.UInt64":
writer.WriteNumberValue((ulong)rowValue);
break;
}
}
writer.WriteEndArray();
}
writer.WriteEndArray();
writer.WriteEndObject();
}
}
}

View File

@ -0,0 +1,84 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Library.SQLScript.Entity;
namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
{
public class RoomConverter : JsonConverter<Room>
{
public override Room Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
{
Room room = Factory.GetRoom();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
string property = reader.GetString() ?? "";
switch (property)
{
case RoomQuery.Column_ID:
reader.Read();
room.Id = reader.GetInt64();
break;
case RoomQuery.Column_RoomID:
reader.Read();
room.Roomid = reader.GetString() ?? "";
break;
case RoomQuery.Column_CreateTime:
reader.Read();
string dateString = reader.GetString() ?? "";
if (DateTime.TryParseExact(dateString, General.GeneralDateTimeFormat, null, System.Globalization.DateTimeStyles.None, out DateTime result))
{
room.CreateTime = result;
}
else room.CreateTime = DateTime.MinValue;
break;
case RoomQuery.Column_RoomMaster:
reader.Read();
string master = reader.GetString() ?? "";
room.RoomMaster = JsonSerializer.Deserialize<User>(master, options);
break;
case RoomQuery.Column_RoomType:
reader.Read();
room.RoomType = (RoomType)reader.GetInt64();
break;
case RoomQuery.Column_RoomState:
reader.Read();
room.RoomState = (RoomState)reader.GetInt64();
break;
case RoomQuery.Column_Password:
reader.Read();
room.Password = reader.GetString() ?? "";
break;
}
}
}
return room;
}
public override void Write(Utf8JsonWriter writer, Room value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WriteNumber(RoomQuery.Column_ID, value.Id);
writer.WriteString(RoomQuery.Column_RoomID, value.Roomid);
writer.WriteString(RoomQuery.Column_CreateTime, value.CreateTime.ToString(General.GeneralDateTimeFormat));
writer.WriteString(RoomQuery.Column_RoomMaster, JsonSerializer.Serialize(value.RoomMaster, typeof(User), options));
writer.WriteNumber(RoomQuery.Column_RoomType, (long)value.RoomType);
writer.WriteNumber(RoomQuery.Column_RoomState, (long)value.RoomState);
writer.WriteString(RoomQuery.Column_Password, value.Password);
writer.WriteEndObject();
}
}
}

View File

@ -0,0 +1,107 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Library.SQLScript.Entity;
namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
{
public class UserConverter : JsonConverter<User>
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(User);
}
public override User Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
User user = Factory.GetUser();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
string propertyName = reader.GetString() ?? "";
switch (propertyName)
{
case "Id":
user.Id = reader.GetInt64();
break;
case "Username":
user.Username = reader.GetString() ?? "";
break;
case "Password":
user.Password = reader.GetString() ?? "";
break;
case "RegTime":
string regTime = reader.GetString() ?? "";
if (DateTime.TryParseExact(regTime, General.GeneralDateTimeFormat, null, System.Globalization.DateTimeStyles.None, out DateTime RegTime))
{
user.RegTime = RegTime;
}
else user.RegTime = DateTime.MinValue;
break;
case "LastTime":
string lastTime = reader.GetString() ?? "";
if (DateTime.TryParseExact(lastTime, General.GeneralDateTimeFormat, null, System.Globalization.DateTimeStyles.None, out DateTime LastTime))
{
user.LastTime = LastTime;
}
else user.LastTime = DateTime.MinValue;
break;
case "Email":
user.Email = reader.GetString() ?? "";
break;
case "NickName":
user.NickName = reader.GetString() ?? "";
break;
case "IsAdmin":
user.IsAdmin = reader.GetBoolean();
break;
case "IsOperator":
user.IsOperator = reader.GetBoolean();
break;
case "IsEnable":
user.IsEnable = reader.GetBoolean();
break;
case "Credits":
user.Credits = reader.GetDecimal();
break;
case "Materials":
user.Materials = reader.GetDecimal();
break;
case "GameTime":
user.GameTime = reader.GetDecimal();
break;
case "AutoKey":
user.AutoKey = reader.GetString() ?? "";
break;
}
}
}
return user;
}
public override void Write(Utf8JsonWriter writer, User value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WriteNumber(UserQuery.Column_UID, value.Id);
writer.WriteString(UserQuery.Column_Username, value.Username);
writer.WriteString(UserQuery.Column_Password, value.Password);
writer.WriteString(UserQuery.Column_RegTime, value.RegTime.ToString(General.GeneralDateTimeFormat));
writer.WriteString(UserQuery.Column_LastTime, value.LastTime.ToString(General.GeneralDateTimeFormat));
writer.WriteString(UserQuery.Column_Email, value.Email);
writer.WriteString(UserQuery.Column_Nickname, value.NickName);
writer.WriteBoolean(UserQuery.Column_IsAdmin, value.IsAdmin);
writer.WriteBoolean(UserQuery.Column_IsOperator, value.IsOperator);
writer.WriteBoolean(UserQuery.Column_IsEnable, value.IsEnable);
writer.WriteNumber(UserQuery.Column_Credits, value.Credits);
writer.WriteNumber(UserQuery.Column_Materials, value.Materials);
writer.WriteNumber(UserQuery.Column_GameTime, value.GameTime);
writer.WriteString(UserQuery.Column_AutoKey, value.AutoKey);
writer.WriteEndObject();
}
}
}

View File

@ -8,9 +8,10 @@ namespace Milimoe.FunGame.Core.Library.Constant
// Static Variable
public static Empty EntityInstance { get; } = new();
public static User UnknownUserInstance { get; } = new();
public static Room HallInstance => Api.Utility.Factory.GetHall();
public static Room HallInstance { get; } = Api.Utility.Factory.GetHall();
public static Encoding DefaultEncoding => Encoding.Unicode;
public static string GeneralDateTimeFormat => "yyyy-MM-dd HH:mm:ss.fff";
public static DateTime DefaultTime { get; } = new(1970,1,1,8,0,0);
// Const
public const int MaxRetryTimes = 20;

View File

@ -7,38 +7,23 @@ namespace Milimoe.FunGame.Core.Service
{
internal class JsonManager
{
private static bool _IsFirst = true;
private readonly static JsonSerializerOptions _GeneralOptions = new()
/// <summary>
/// 默认的序列化选项
/// </summary>
private readonly static JsonSerializerOptions GeneralOptions = new()
{
WriteIndented = true,
ReferenceHandler = ReferenceHandler.IgnoreCycles
ReferenceHandler = ReferenceHandler.IgnoreCycles,
Converters = { new DateTimeConverter(), new DataTableConverter(), new DataSetConverter() }
};
/// <summary>
/// 默认的JsonSerializerOptions
/// </summary>
internal static JsonSerializerOptions GeneralOptions
{
get
{
if (_IsFirst)
{
// 首次使用时,向其添加自定义转换器
_IsFirst = false;
AddConverter(new DataSetConverter());
AddConverter(new DateTimeConverter());
}
return _GeneralOptions;
}
}
/// <summary>
/// 注册一个自定义转换器
/// </summary>
/// <param name="converter"></param>
internal static void AddConverter(JsonConverter converter)
{
_GeneralOptions.Converters.Add(converter);
GeneralOptions.Converters.Add(converter);
}
/// <summary>