配置表接入和升级服务器框架到最新版

This commit is contained in:
2025-10-10 17:57:01 +08:00
parent 520d4f37bd
commit 8a302754d6
250 changed files with 6356 additions and 4135 deletions

View File

@@ -0,0 +1,85 @@
namespace Fantasy.ConfigTable;
public interface IConfigContext
{
// 定义非泛型接口
}
public class ConfigContext<T> : IConfigContext where T : IConfigTable
{
private static List<T> _cacheList = new List<T>();
#region Cache
public void Association(List<T> list)
{
if (list != null)
{
_cacheList = list;
}
}
#endregion
public int Count()
{
return _cacheList.Count;
}
public int Count(Func<T, bool> predicate)
{
return _cacheList.Count(predicate);
}
public T Get(uint key)
{
return First(key);
}
public T Fist()
{
return _cacheList.First();
}
public T Last()
{
return _cacheList.Last();
}
public T Fist(Predicate<T> match)
{
return Get(match);
}
public T Last(Predicate<T> match)
{
return _cacheList.FindLast(match);
}
public T Get(Predicate<T> match)
{
return _cacheList.Find(match);
}
public T GetRandom()
{
Random random = new Random();
// 随机从列表中取一个对象
return _cacheList[random.Next(_cacheList.Count)];
}
public List<T> GetList()
{
return _cacheList;
}
public List<T> GetList(Predicate<T> match)
{
return _cacheList.FindAll(match);
}
private T First(uint key)
{
return _cacheList.Find(t => t.Key == key);
}
}

View File

@@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Fantasy.Assembly;
using Fantasy.Helper;
using Fantasy.Platform.Net;
using Fantasy.Serialize;
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
using Newtonsoft.Json.Linq;
// ReSharper disable SuspiciousTypeConversion.Global
@@ -14,81 +17,178 @@ namespace Fantasy.ConfigTable
/// </summary>
public static class ConfigTableHelper
{
private static string _configTableBinaryDirectory;
private static readonly object Lock = new object();
// 配置表数据缓存字典
private static readonly Dictionary<string, ASerialize> ConfigDic = new ();
private static readonly Dictionary<Type, IConfigContext> _dictionary = new Dictionary<Type, IConfigContext>();
/// <summary>
/// 初始化ConfigTableHelper
/// </summary>
/// <param name="configTableBinaryDirectory"></param>
public static void Initialize(string configTableBinaryDirectory)
public static void Initialize(string json, params System.Reflection.Assembly[] assemblies)
{
_configTableBinaryDirectory = configTableBinaryDirectory;
}
/// <summary>
/// 加载配置表数据
/// </summary>
/// <typeparam name="T">配置表类型</typeparam>
/// <returns>配置表数据</returns>
public static T Load<T>() where T : ASerialize
{
lock (Lock)
var jsonObj = JObject.Parse(json);
Dictionary<string, JArray> tokens = new();
foreach (var item in jsonObj)
{
try
{
var dataConfig = typeof(T).Name;
if (ConfigDic.TryGetValue(dataConfig, out var aProto))
var name = item.Key;
var value = item.Value;
if (value is JArray jArray)
{
return (T)aProto;
tokens[name] = jArray;
}
var configFile = GetConfigPath(dataConfig);
var bytes = File.ReadAllBytes(configFile);
// Log.Debug($"dataConfig:{dataConfig} {bytes.Length}");
var data = SerializerManager.GetSerializer(FantasySerializerType.ProtoBuf).Deserialize<T>(bytes);
ConfigDic[dataConfig] = data;
return data;
}
catch (Exception ex)
catch (Exception e)
{
throw new Exception($"ConfigTableManage:{typeof(T).Name} 数据表加载之后反序列化时出错:{ex}");
Log.Error($"读表异常请检查name={item.Key} ex={e}");
}
}
foreach (var type in GetAllConfigTableTypes(assemblies))
{
var name = type.Name;
if (tokens.TryGetValue(name, out var jArray))
{
// 通过反射调用 ParseJson 方法
var parseMethod = type.GetMethod("ParseJson", BindingFlags.Public | BindingFlags.Static);
parseMethod?.Invoke(null, [jArray]);
}
}
var d = _dictionary;
}
public static ConfigContext<T> Table<T>() where T : IConfigTable
{
var type = typeof(T);
if (_dictionary.TryGetValue(type, out var context))
{
return context as ConfigContext<T>;
}
var jsonContext = new ConfigContext<T>();
_dictionary[type] = jsonContext;
return jsonContext;
}
public static List<T> ParseLine<T>(JArray arr) where T : IConfigTable, new()
{
List<T> list = new List<T>();
foreach (var jToken in arr)
{
T instance = jToken.ToObject<T>();
if (instance != null)
{
list.Add(instance);
}
}
var context = Table<T>();
context.Association(list);
return list;
}
/// <summary>
/// 获取配置表文件路径
/// 获取所有实现了 IConfigTable 接口的非抽象类
/// </summary>
/// <param name="name">配置表名称</param>
/// <returns>配置表文件路径</returns>
private static string GetConfigPath(string name)
/// <returns>所有非抽象的配置对象类</returns>
private static List<Type> GetAllConfigTableTypes(params System.Reflection.Assembly[] assemblies)
{
var configFile = Path.Combine(_configTableBinaryDirectory, $"{name}.bytes");
var types = new List<Type>();
var interfaceType = typeof(IConfigTable);
if (File.Exists(configFile))
// 遍历当前程序集中的所有类型
foreach (var assembly in assemblies)
{
return configFile;
}
throw new FileNotFoundException($"{name}.byte not found: {configFile}");
}
/// <summary>
/// 重新加载配置表数据
/// </summary>
public static void ReLoadConfigTable()
{
lock (Lock)
{
foreach (var (_, aProto) in ConfigDic)
foreach (var type in assembly.GetTypes())
{
((IDisposable) aProto).Dispose();
// 检查是否实现了 IConfigTable 接口,并且不是抽象类
if (interfaceType.IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface)
{
types.Add(type);
}
}
ConfigDic.Clear();
}
return types;
}
// private static string _configTableBinaryDirectory;
// private static readonly object Lock = new object();
// // 配置表数据缓存字典
// private static readonly Dictionary<string, ASerialize> ConfigDic = new ();
// /// <summary>
// /// 初始化ConfigTableHelper
// /// </summary>
// /// <param name="configTableBinaryDirectory"></param>
// public static void Initialize(string configTableBinaryDirectory)
// {
// _configTableBinaryDirectory = configTableBinaryDirectory;
// }
// /// <summary>
// /// 加载配置表数据
// /// </summary>
// /// <typeparam name="T">配置表类型</typeparam>
// /// <returns>配置表数据</returns>
// public static T Load<T>() where T : ASerialize
// {
// lock (Lock)
// {
// try
// {
// var dataConfig = typeof(T).Name;
//
// if (ConfigDic.TryGetValue(dataConfig, out var aProto))
// {
// return (T)aProto;
// }
//
// var configFile = GetConfigPath(dataConfig);
// var bytes = File.ReadAllBytes(configFile);
// // Log.Debug($"dataConfig:{dataConfig} {bytes.Length}");
// var data = SerializerManager.GetSerializer(FantasySerializerType.ProtoBuf).Deserialize<T>(bytes);
// ConfigDic[dataConfig] = data;
// return data;
// }
// catch (Exception ex)
// {
// throw new Exception($"ConfigTableManage:{typeof(T).Name} 数据表加载之后反序列化时出错:{ex}");
// }
// }
// }
//
// /// <summary>
// /// 获取配置表文件路径
// /// </summary>
// /// <param name="name">配置表名称</param>
// /// <returns>配置表文件路径</returns>
// private static string GetConfigPath(string name)
// {
// var configFile = Path.Combine(_configTableBinaryDirectory, $"{name}.bytes");
//
// if (File.Exists(configFile))
// {
// return configFile;
// }
//
// throw new FileNotFoundException($"{name}.byte not found: {configFile}");
// }
//
// /// <summary>
// /// 重新加载配置表数据
// /// </summary>
// public static void ReLoadConfigTable()
// {
// lock (Lock)
// {
// foreach (var (_, aProto) in ConfigDic)
// {
// ((IDisposable) aProto).Dispose();
// }
//
// ConfigDic.Clear();
// }
// }
}
}
}

View File

@@ -1,33 +0,0 @@
using System.Collections.Generic;
using ProtoBuf;
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
// ReSharper disable CheckNamespace
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
namespace Fantasy.ConfigTable
{
[ProtoContract]
public partial class IntDictionaryConfig
{
[ProtoMember(1)]
public Dictionary<int, int> Dic;
public int this[int key] => GetValue(key);
public bool TryGetValue(int key, out int value)
{
value = default;
if (!Dic.ContainsKey(key))
{
return false;
}
value = Dic[key];
return true;
}
private int GetValue(int key)
{
return Dic.TryGetValue(key, out var value) ? value : 0;
}
}
}

View File

@@ -1,35 +0,0 @@
using System.Collections.Generic;
using ProtoBuf;
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
// ReSharper disable CheckNamespace
// ReSharper disable CollectionNeverUpdated.Global
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
#pragma warning disable CS8603 // Possible null reference return.
namespace Fantasy.ConfigTable
{
[ProtoContract]
public sealed partial class StringDictionaryConfig
{
[ProtoMember(1)]
public Dictionary<int, string> Dic;
public string this[int key] => GetValue(key);
public bool TryGetValue(int key, out string value)
{
value = default;
if (!Dic.ContainsKey(key))
{
return false;
}
value = Dic[key];
return true;
}
private string GetValue(int key)
{
return Dic.TryGetValue(key, out var value) ? value : null;
}
}
}

View File

@@ -3,5 +3,8 @@ namespace Fantasy.ConfigTable
/// <summary>
/// 表示是一个配置文件
/// </summary>
public interface IConfigTable { }
public interface IConfigTable
{
public uint Key { get; }
}
}