EasySharpFrame 1.18.12
dotnet add package EasySharpFrame --version 1.18.12
NuGet\Install-Package EasySharpFrame -Version 1.18.12
<PackageReference Include="EasySharpFrame" Version="1.18.12" />
paket add EasySharpFrame --version 1.18.12
#r "nuget: EasySharpFrame, 1.18.12"
// Install EasySharpFrame as a Cake Addin #addin nuget:?package=EasySharpFrame&version=1.18.12 // Install EasySharpFrame as a Cake Tool #tool nuget:?package=EasySharpFrame&version=1.18.12
ECSharp (原:EasySharpFrame)
Easy .NET Develop Frame.
这是一个基于.Net语言框架而设计的开发框架。集成了许多常规用到的开发功能,主要目的是利于基于此框架的服务器快捷开发!
快速使用
可以直接从NuGet库中搜索安装最新版本。
版本支持
版本 | .Net6.0 | .Net5.0 | .NetCore3.1 | .NetFramework4.6.2 | .NetStandard2.0 |
---|---|---|---|---|---|
1.17 | √ | √ | √ | √ | √ |
1.13 | √ | √ | √ | × | × |
1.11 | √ | √ | √ | √ | × |
更新历史 查看
目录介绍
目录 | 备注 |
---|---|
UnityESF | Unity框架支持 |
docs | 在线API文档 |
ES | 框架主工程 |
Sample | 框架测试样本工程 |
SampleDll | 框架热更模块测试样本工程 |
功能说明
1.HTTP服务
对TcpListener进行封装,支持ssl模式,可以完成高并发任务。以后可能会更新静态文件的访问,即网页访问。
/* 使用方法一 */
public void Http1()
{
// 先继承http异常接口,这里把测试的访问函数也写在一个类中,实际不需要
HttpHandle1 handle = new HttpHandle1();
// 建立http访问器,并载入异常接口类
HttpVisitor visitor = new HttpVisitor(handle);
// 建立http服务,填写地址并且赋予访问器
// X509Certificate2 certificate = new X509Certificate2("https.pfx", "8888");
// HttpService service = new HttpService("127.0.0.1", 8080, visitor, certificate);
HttpService service = new HttpService("127.0.0.1", 8080, visitor);
// 给访问器增加函数
visitor.Add("", handle.Index);
visitor.Add("Hello", handle.Hello);
// 启动服务
service.StartServer();
// 然后就可以通过浏览器或其他请求工具来访问了
// 访问地址: http://127.0.0.1:8080/Hello?text=World
Console.ReadLine();
}
class HttpHandle1 : IHttpVisitor
{
public void Index(HttpRequest request, HttpResponse response)
{
// 首页根访问
if (!request.GetParams.TryGetValue("text", out var text)) text = "text no content";
response.Write("Index:" + text);
}
public void Hello(HttpRequest request, HttpResponse response)
{
response.Write("Hello World:" + request.PostValue);
}
public void HttpVisitorException(HttpRequest request, Exception ex)
{
// http异常处理
}
}
/* 使用方法二 */
public void Http2()
{
// 先继承http异常接口,这里把测试的访问函数也写在一个类中,实际不需要
HttpHandle2 handle = new HttpHandle2();
// 建立http服务,填写地址
HttpService service = new HttpService("127.0.0.1", 8080, handle);
// 启动服务
service.StartServer();
// 然后就可以通过浏览器或其他请求工具来访问了
// 访问地址: http://127.0.0.1:8080/Hello?text=World
Console.ReadLine();
}
class HttpHandle2 : IHttp
{
public void HttpException(HttpRequest request, Exception exception)
{
// http异常处理
}
public void OnRequest(HttpRequest request, HttpResponse response)
{
// 这里是全部消息回调接口
// 所以如果需要高度自定义可以使用此方法
}
}
2.Websocket服务
使用Fleck库中的Websocket进行二次封装,支持ssl模式。
WebsocketService service = new WebsocketService("ws://127.0.0.1:8081", new WebsocketHandle());
class WebsocketHandle : IWebsocket
{
public void OnBinary(RemoteConnection conn)
{
// 数据使用byte流传输调用
}
public void OnClose(RemoteConnection conn)
{
// 关闭时调用
}
public void OnError(RemoteConnection conn, Exception exception)
{
// 出现异常调用
}
public void OnMessage(RemoteConnection conn)
{
// 数据使用文本时调用
}
public void OnOpen(RemoteConnection conn)
{
// 新连接产生调用
}
}
3.HyperSocket<自定义Socket服务>
该模块已经深度封装了原生Socket模块,实现了快捷连接,加密连接等比较便捷实用的功能,通过IOCP接口可以实现高并发收发。需要配合配套的客户端才能使用。
// 创建服务器
var config = new HyperSocketConfig() { UseSSL = true };
new HyperSocketServer("127.0.0.1", 8888, 500, new ServerListener(), config).StartServer();
// 服务器监听接口
class ServerListener : IHyperSocketServer
{
public void OnClose(RemoteHyperSocket socket)
{
// 客户端关闭
}
public void SocketError(RemoteHyperSocket socket, Exception ex)
{
// 连接异常
}
public void OnOpen(RemoteHyperSocket socket)
{
// 客户端新连接
}
public void OnTcpReceive(byte[] data, RemoteHyperSocket socket)
{
// Tcp模式接收
}
public void OnUdpReceive(byte[] data, RemoteHyperSocket socket)
{
// Udp模式接收
}
}
// 创建客户端
new HyperSocket("127.0.0.1", 8888, new ClientListener()).Connect();
// 客户端监听接口
class ClientListener : IHyperSocketClient
{
public void SocketError(HyperSocket socket, Exception ex)
{
// 客户端异常
}
public void OnOpen(HyperSocket socket)
{
// 客户端连接成功
}
public void OnTcpReceive(byte[] data, HyperSocket socket)
{
// Tcp模式接收
}
public void OnUdpReceive(byte[] data, HyperSocket socket)
{
// Udp模式接收
}
}
4.TimeFlow<时间流>
该模块深度封装了原生Thread模块,可以快捷给每个类增加一个时间更新,类似Unity中组件的Update功能,模块以固定周期的速度进行刷新,并且经过多个项目及测试,在周期时间内最终循环时间很精准。另外 TimeCaller 是支持快速定制一个Scheduler定时器的功能类;TimeClock是一种可自定义现实时间的闹钟定时器功能。
class TimeDemo : ITimeUpdate
{
TimeFlow tf;
public TimeDemo(){
// 时间流
tf = TimeFlow.Create(this);
tf.Start();
// 时间闹钟
TimeClock.Create(delegate(DateTime time) {
Log.Info($"Time Now Alarm Clock:{time}");
}, "00:00:00").Start(true);
// 时间执行器
TimeCaller.Create(static delegate {
Log.Info("Hello TimeCaller");
}, 2000, 1000, 3).Start();
}
// 可以从 TimeFlow.period 直接获取周期时间
// dt为消耗时间的差值 因为程序不可能每次都精准执行
// 所以update会不断调整时间执行时间 dt就是这个时间的差值
// 一般情况下不需要管理,因为在总时间循环中 几乎可以忽略 因为我们有自动修正
public void Update(int dt)
{
}
// 停止更新
public void UpdateEnd()
{
}
}
5.Sqlserver数据库助手
Sqlserver相关操作比较多,更多可直接查看Sample中书写的样例:查看链接
助手目前有以下几种功能:
- 数据库连接:简化连接操作步骤
- 数据库执行SQL和存储过程:书写SQL直接执行得到结果
- SQL语句构建器:函数化某些SQL关键字,通过函数连调实现执行SQL
- SQLServer基础配置加载器:可以通过映射关系加载数据库表中的配置,高并发读取
- Sqlserver数据缓存助理数据组:可以通过映射关系加载数据库表中的数据,高并发实现增删改查
- 非关系型存储:通过映射原理建立表中Key-Value模型的对象,实现高并发读写
// 数据库连接使用此函数即可简单创建 数据库的创建还提供更多重载方案,可以点入查看
SqlServerDbHelper dbHelper = new SqlServerDbHelper("127.0.0.1", "sa", "123456", "db_test");
// 增加异常监听器 需要一个继承 ISQLServerDBHelper 接口
dbHelper.SetExceptionListener(this);
// 检测数据库连接是否成功调用 成功返回true
if (dbHelper.CheckConnected())
{
Console.WriteLine("数据库已连接");
}
//获取数据库时间 如果获取不到默认获取程序本地时间
Log.Info("数据库时间:" + dbHelper.Now);
// 普通查询调用
var result = dbHelper.CommandSQL("SELECT * FROM tb_test");
// 查询条数判断
if (result.EffectNum > 0)
{
// 取出表一的相关数据
// 如果查询有多个select 可以通过result.dataSet取得
int id = (int)result.Collection[0]["id"];
Console.WriteLine($"id:{id}");
}
6.Mysql数据助手
Mysql数据助手和Sqlserver数据库助手使用操作差不多,可参考第5项。
// 数据库连接使用此函数即可简单创建 数据库的创建还提供更多重载方案,可以点入查看
MySqlDbHelper dbHelper = new MySqlDbHelper("127.0.0.1", "root", "123456");
// 增加异常监听器
dbHelper.SetExceptionListener(this);
// 检测数据库连接是否成功调用 成功返回true
if (dbHelper.CheckConnected())
{
Log.Info("数据库已连接");
}
//获取数据库时间 如果获取不到默认获取程序本地时间
Log.Info("数据库时间:" + dbHelper.Now);
7.Redis数据库助手
简化Redis连接复杂度,快速连接Redis并且对数据进行高并发读写操作,对订阅功能进行简化操作,使订阅更加易用。
// 继承 IRedisEvent 接口来用于监听回调
RedisHelper helper = new RedisHelper("127.0.0.1:6379");
// 增加事件监听用于检测连接状态
helper.AddEventListener(this);
// 设置一个值
helper.Set("test", 1);
// 取出值
var test = helper.Get<int>("test");
8.Log功能
日志功能就是解决服务器对各种记录数据的记录和输出,日志即可输出在控制窗口,也可以写入本地文件持久化储存,供后续查看。Log类中提供日志前置配置参数,可以对日志进行自定义配置,详见 LogConfig 类。
// 以下四个函数均为普通分级日志输出函数
Log.Debug("debug is this");
Log.Info("info is this");
Log.Warn("warn is this");
Log.Error("error is this");
// 此函数可以写在try catch中 用于打印异常问题
Log.Exception(new System.Exception(), "exception is this");
9.热更新功能
支持服务器运行中可以进行逻辑更新的功能。当然,热更的实现,在各个语言上都是通过运行时反射实现的,所以一旦利用反射原理的功能都会逊色于原生直接调用。经过多次测试在千万次的简单循环下,初次加载可能会存在总量30~100毫秒的延迟;随之以后的调用则影响很小,循环总量和直接调用总量为2:1,也就是说在正常情况下,直接调用耗时1ms的操作,移植到热更新层也仅仅花费2ms左右,所以非密集型计算,耗时偏差基本可以忽略不计。
/** 主工程项目 **/
class Test_Hotfix
{
public Test_Hotfix()
{
while (true)
{
// 普通测试
TestHotfix();
// 耗时测试
// ConsumeTime();
Console.WriteLine($"Is First Load:{HotfixMgr.IsFirstLoad}");
// 回车重载测试
Console.ReadLine();
Console.Clear();
}
}
// 测试只需要放入构造函数
// 热更测试
public void TestHotfix()
{
HotfixMgr.Load("SampleDll", "SampleDll.Main", new string[] { "Hello World" }, "Main_Test");
}
// 测试只需要放入构造函数
// 耗时测试
public void ConsumeTime()
{
HotfixMgr.Instance.Load("SampleDll", "SampleDll.Main", null, "Main_Test1");
Player player = new Player();
Stopwatch watch = new Stopwatch();
/* 性能测试 */
// 第一次直接调用
Console.WriteLine("第一次直接调用开始~");
watch.Reset();
watch.Start();
player.Test();
watch.Stop();
Console.WriteLine($"第一次直接调用耗时1:{watch.Elapsed.TotalMilliseconds}ms");
// 第一次实测热更调用
Console.WriteLine("\n\n热更调用开始~");
watch.Reset();
watch.Start();
player.GetDynamicAgent().Test();
watch.Stop();
Console.WriteLine($"第一次热更层耗时1:{watch.Elapsed.TotalMilliseconds}ms");
// 第二次直接调用
Console.WriteLine("\n\n第二次直接调用开始~");
watch.Reset();
watch.Start();
player.Test();
watch.Stop();
Console.WriteLine($"第二次直接调用耗时2:{watch.Elapsed.TotalMilliseconds}ms");
// 第二次实测热更调用
Console.WriteLine("\n\n热更调用开始~");
watch.Reset();
watch.Start();
player.GetDynamicAgent().Test();
watch.Stop();
Console.WriteLine($"第二次热更层耗时2:{watch.Elapsed.TotalMilliseconds}ms");
}
}
// 手动创建对应的代理
// 如果每次热更重载后不主动创建 则代理不会运作
// 也可以通过带参数构造函数来设定手动
// [NotCreateAgent]
public class Player : AgentData
{
public int count;
// 用于测试 实际上一般数据层不写逻辑
public void Test()
{
for (int i = 0; i < 10000000; i++) count++;
Console.WriteLine("直接调用计数:" + count);
}
}
// 自动创建代理
// 并且添加 KeepAgentValue 特性实现代理内变量保存
// 如果去除 KeepAgentValue 特性则变量不会在重载后保存
[KeepAgentValue]
public class Player1 : AgentData
{
public int count;
public string test;
public Player1()
{
test = "Hello World";
// 手动创建代理
CreateAgent();
}
}
/** 热更工程项目 **/
// 热更测试DLL入口
public class Main
{
static readonly Player player = AgentDataPivot.AddOrGetObject<Player>("player");
static Player1 player1;
static StructValue<int> test_1 = AgentDataPivot.AddOrGetStruct("test_1", 0);
static B b;
static C c;
public static void Main_Test(string[] args)
{
Console.WriteLine($"Input args:{args[0]}, test_1:{test_1.Value++}");
player1 = AgentDataPivot.AddOrGetObject<Player1>("player1");
b = new B();
c = new C();
Test2(b, c);
}
public static void Main_Test1(string[] args)
{
Stopwatch watch = new Stopwatch();
// 可以利用拓展特性来实现不每次都书写泛型实现代理
// player.GetAgent<PlayerAgent>().Test();
// player.GetAgent().Test();
watch.Reset();
watch.Start();
player.GetAgent().Test();
watch.Stop();
Console.WriteLine($"内部第一次热更层耗时3:{watch.Elapsed.TotalMilliseconds}ms\n");
watch.Reset();
watch.Start();
player.GetAgent().Test();
watch.Stop();
Console.WriteLine($"内部第二次热更层耗时3:{watch.Elapsed.TotalMilliseconds}ms\n\n");
}
public static void Test2(A obj1, A obj2)
{
obj1.GetAbstractAgent<A_Agent>().WriteHelloA();
obj2.GetAbstractAgent<A_Agent>().WriteHelloA();
obj1.GetAbstractAgent<A_Agent>().Hello();
obj2.GetAbstractAgent<A_Agent>().Hello();
obj1.GetAgent<B_Agent>().Hello();
obj2.GetAgent<C_Agent>().Hello();
}
}
// 如果觉得每次调用都需要使用GetAgent的泛型来处理
// 那么可以针对需要大量调用的代理,在热更层写一个静态拓展来实现不用再写代理泛型的重复工作
public static class AgentRegister
{
// PlayerAgent代理
// 这样只需要在这里写一次,以后就可以直接借助GetAgent()函数直接使用了
public static PlayerAgent GetAgent(this Player self) => self.GetAgent<PlayerAgent>();
}
// 如果需要时间流需要在热更层继承和使用
// 测试案例一
public class PlayerAgent : Agent<Player>, ITimeUpdate
{
public TimeFlow tf;
protected override void Initialize()
{
// tf = TimeFlow.Create(this);
// tf.Start();
}
public void Test()
{
// Console.WriteLine(self.name);
Stopwatch watch = new Stopwatch();
/* 性能测试 */
// 第一次直接调用
watch.Start();
for (int i = 0; i < 10000000; i++) { self.count++; }
watch.Stop();
Console.WriteLine($"热更层循环耗时:{watch.Elapsed.TotalMilliseconds}ms");
// for (int i = 0; i < 1000000; i++) self.count++;
Console.WriteLine("热更层计数:" + self.count);
}
int count = 0;
public void Update(int deltaTime)
{
if (count % 1000 == 0) Console.WriteLine($"player count:{self.count++},copyCount:{count}");
count += deltaTime;
}
public void UpdateEnd()
{
}
// 测试案例二 主动创建 且保留值
public class Player1Agent : Agent<Player1>, ITimeUpdate
{
public int copyCount = 0;
private readonly int seed = new Random().Next(9999);
protected override void Initialize()
{
// 两种相同作用
Console.WriteLine("IsFirstCreateAgent:" + self.IsFirstCreateAgent);
Console.WriteLine("IsFirstCreate:" + IsFirstCreate);
// 先处理代理数据构造函数,在处理代理构造
Console.WriteLine(self.test);
TimeFlow.Create(this).Start();
}
public void Update(int deltaTime)
{
if (copyCount % 1000 == 0) Console.WriteLine($"player1 count:{self.count++},copyCount:{copyCount},seed:{seed}");
copyCount += deltaTime;
}
public void UpdateEnd()
{
}
// 测试案例三 继承测试
// A抽象代理实现
public abstract class A_Agent : AbstractAgent, IAgent<A>
{
public A self => _self as A;
public void WriteHelloA()
{
self.test1 += 100;
self.test2 += " world A";
}
public abstract void Hello();
protected override void Initialize()
{
self.test1 += 1000;
}
}
// B抽象代理
public class B_Agent : A_Agent, IAgent<B>
{
public new B self => _self as B;
public override void Hello()
{
self.test1 += 20;
self.test3 += " world B";
Console.WriteLine(self.test1 + "," + self.test2 + "," + self.test3);
}
protected override void Initialize()
{
base.Initialize();
self.test1 += 20;
}
}
// C抽象代理
public class C_Agent : A_Agent, IAgent<C>
{
public new C self => _self as C;
public override void Hello()
{
self.test1 += 50;
self.test4 += " world C";
Console.WriteLine(self.test1 + "," + self.test2 + "," + self.test4);
}
protected override void Initialize()
{
base.Initialize();
self.test1 += 10;
}
}
10.可变变量
以空间换更方便的数值传递操作,可变变量可以满足所有基础类型的变量存储和读取,并且配备列表、字典容器来提供批量存储,同时可以很方便的获取存储后的原始字节数组或序列化的数据,当然也可以重新反序列化成新的对象。
Var a1 = (byte)1;
Var a2 = (sbyte)-2;
Var a3 = (ushort)3;
Var a4 = (short)-4;
Var a5 = 5U;
Var a6 = -6;
Var a7 = 7UL;
Var a8 = -8L;
Var a9 = 9.123456789F;
Var a10 = 9.123456789987654321D;
Var a11 = true;
Var a12 = "hello world";
Var a13 = TestEnum.B;
Var a14 = new Var(new object());
VarList list = new VarList();
list.Add(a1);
list.Add(a2);
list.Add(a3);
VarMap map = new VarMap();
map.Add("a1", a1);
map.Add("a2", a2);
map.Add("a3", a3);
map.Add("list", list);
Var a15 = list;
Var a16 = map;
Var b1 = a1 > a2;
Var b2 = a3 == a4;
Var b3 = a6 % a3;
Var b4 = a8 * a7;
Var b5 = a9.ToString();
Var b6 = a10.GetBytes();
11.事件与命令
本模块主要负责特定事件的函数触发,使用泛型自定义多种参数的事件或者命令,来在特定的场合和逻辑中触发相关函数调用。其中,命令模式支持同步等待功能,可以支持异步事件转同步执行。
// 新建事件
Event<int> event1 = new Event<int>();
// 添加事件
event1.Add(1, static () => { /* 执行事件回调 */ });
// 触发事件
event1.Call(1);
// 新建多级事件
MultiEvent<string, int> event2 = new MultiEvent<string, int>();
// 添加事件
event2.Add("test", 1, static () => { /* 执行事件回调 */ });
// 触发事件
event2.Call("test", 1);
// 新建命令
Command<string, string> command = new Command<string, string>();
// 添加命令
command.Add("test1", static (object obj) => { return ""; });
command.Add("test2", static (object obj) => { return "Hello World"; });
// 触发事件
command.Call("test1");
// 创建等待id
int waitId = command.AutoWaitID;
// 异步触发事件
command.Call("test2", waitId);
// 添加等待命令 此处执行被阻塞 可以在其他线程中被触发后继续执行
string str = command.WaitCall("test2", waitId);
12.其他
其他小功能不再过多介绍,可以在使用的过程中慢慢查询API来获取使用细节。
// 读取配置 默认和读取程序名一样配置文件 比如此程序生成为Sample.exe那么读取对应的是Sample.exe.config
// 一般来说使用vs2019开发 只需要在新建一个和程序集名称一模一样的.config配置文件即可
// 注意此函数不支持读取其他文件 此demo已经创建了配置文件详见项目 Sample.config
// 本类设计初只能读取两层 具体结构可以参照样例
// 此处读取第一层配置数据
string test = AppConfig.Read("test");
int test1 = AppConfig.Read<int>("test1");
bool test2 = AppConfig.Read<bool>("test2");
// 此处读取第二层配置数据
string test2 = AppConfig.Read("testgroup", "test2");
float tests3 = AppConfig.Read<float>("testgroup", "test3");
// 通过ini文件读取配置
Ini.LoadParser("config.ini", true);
Log.Info($"config filename name:{Ini.Current.GetValue("filename")}");
// 获取有效字节
// 此判定依据是在某索引位为0开始 往后4位皆为0 则认为后续数据无效实现
// 所以这里的设定还是要看具体情况来 不一定适用所有情况
// ByteHelper.GetValidLength 则是直接获取长度大小 而非返回数据
byte[] bytes = ByteHelper.GetValidByte(new byte[] { 1, 2, 3, 4, 0, 0, 0 });
// 随机生成指定位数的字符串
// 字符串将有数字与大小写字母组成
string code = RandomCode.Generate(32);
// md5的封装
string md5Str = MD5.Encrypt("helloworld");
// 获取此框架的版本信息
string versionStr = ES.Utils.SystemInfo.FrameVersion;
// 逻辑线程数
int processorCount = ES.Utils.SystemInfo.ProcessorCount;
引用声明
本框架所有引用第三方外部工具均为MIT协议且均采用NuGet库自动安装
- statianzo/Fleck 支持WebSocket连接库
- KumoKyaku/KCP UDP高速传输算法协议
- JamesNK/Newtonsoft.Json 通用强大的Json格式化工具
- StackExchange/StackExchange.Redis Redis数据库支持工具
- dotnet/corefx 微软官方支持的SqlServer支持库
- mysql-net/MySqlConnector 高性能的MySql数据库连接支持库
关于框架
ECSharp是为了解决服务器与服务器,服务器与客户端之间交互问题而设计的,减少了大量前期开发准备工作,可以更加快速的进入业务逻辑开发阶段。主要包含了数据库连接(Sqlserver,Mysql,Redis)功能,网络(Http,Socket,Websocket)功能,时间执行功能,事件命令功能,日志功能,加密(Aes,Rsa,Md5)功能,服务器级代码逻辑热更新功能,可变结构体变量功能以及其他各种辅助开发的工具类。
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp3.1 is compatible. |
.NET Framework | net462 is compatible. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
-
.NETCoreApp 3.1
- Fleck (>= 1.2.0)
- Kcp (>= 2.6.1)
- MySqlConnector (>= 2.2.5)
- Newtonsoft.Json (>= 13.0.3)
- StackExchange.Redis (>= 2.6.96)
- System.Data.SqlClient (>= 4.8.5)
-
.NETFramework 4.6.2
- Fleck (>= 1.2.0)
- Kcp (>= 2.6.1)
- MySqlConnector (>= 2.2.5)
- Newtonsoft.Json (>= 13.0.3)
- StackExchange.Redis (>= 2.6.96)
- System.Data.SqlClient (>= 4.8.5)
-
net6.0
- Fleck (>= 1.2.0)
- Kcp (>= 2.6.1)
- MySqlConnector (>= 2.2.5)
- Newtonsoft.Json (>= 13.0.3)
- StackExchange.Redis (>= 2.6.96)
- System.Data.SqlClient (>= 4.8.5)
-
net7.0
- Fleck (>= 1.2.0)
- Kcp (>= 2.6.1)
- MySqlConnector (>= 2.2.5)
- Newtonsoft.Json (>= 13.0.3)
- StackExchange.Redis (>= 2.6.96)
- System.Data.SqlClient (>= 4.8.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated | |
---|---|---|---|
1.18.12 | 351 | 4/24/2023 | |
1.18.11 | 299 | 3/21/2023 | |
1.18.8 | 278 | 3/20/2023 | |
1.18.7 | 421 | 3/13/2023 | |
1.18.6 | 303 | 2/22/2023 | |
1.18.5 | 427 | 11/20/2022 | |
1.18.4 | 380 | 11/16/2022 | |
1.18.3 | 454 | 8/31/2022 | |
1.18.2 | 455 | 8/24/2022 | |
1.18.1 | 441 | 8/21/2022 | |
1.17.5 | 503 | 6/23/2022 | |
1.17.4 | 483 | 6/10/2022 | |
1.17.3 | 484 | 6/6/2022 | |
1.17.2 | 494 | 5/6/2022 | |
1.17.1 | 479 | 5/2/2022 | |
1.17.0 | 476 | 5/1/2022 | |
1.16.8 | 453 | 4/27/2022 | |
1.16.7 | 477 | 4/20/2022 | |
1.16.6 | 485 | 4/18/2022 | |
1.16.5 | 489 | 4/17/2022 | |
1.16.4 | 491 | 4/17/2022 | |
1.16.3 | 492 | 4/16/2022 | |
1.16.2 | 491 | 4/15/2022 | |
1.16.1 | 499 | 4/5/2022 | |
1.16.0 | 497 | 4/1/2022 | |
1.15.17 | 490 | 3/13/2022 | |
1.15.16 | 498 | 3/12/2022 | |
1.15.15 | 486 | 3/10/2022 | |
1.15.14 | 469 | 3/7/2022 | |
1.15.13 | 465 | 3/6/2022 | |
1.15.12 | 483 | 3/5/2022 | |
1.15.11 | 501 | 3/5/2022 | |
1.15.10 | 478 | 3/5/2022 | |
1.15.9 | 489 | 3/4/2022 | |
1.15.8 | 484 | 3/4/2022 | |
1.15.7 | 486 | 3/3/2022 | |
1.15.6 | 482 | 3/3/2022 | |
1.15.5 | 508 | 3/2/2022 | |
1.15.4 | 482 | 2/27/2022 | |
1.15.3 | 496 | 2/22/2022 | |
1.15.2 | 477 | 2/19/2022 | |
1.15.1 | 497 | 2/15/2022 | |
1.15.0 | 462 | 2/15/2022 | |
1.14.10 | 521 | 1/16/2022 | |
1.14.9 | 329 | 1/5/2022 | |
1.14.8 | 343 | 1/3/2022 | |
1.14.7 | 341 | 1/1/2022 | |
1.14.6 | 328 | 12/31/2021 | |
1.14.5 | 340 | 12/16/2021 | |
1.14.4 | 358 | 12/16/2021 | |
1.14.3 | 478 | 12/14/2021 | |
1.14.2 | 350 | 12/10/2021 | |
1.14.1 | 324 | 12/10/2021 | |
1.14.0 | 361 | 12/9/2021 | |
1.13.18 | 381 | 9/24/2021 | |
1.13.17 | 428 | 8/22/2021 | |
1.13.16 | 417 | 8/10/2021 | |
1.13.15 | 389 | 8/8/2021 | |
1.13.14 | 387 | 8/6/2021 | |
1.13.13 | 636 | 8/6/2021 | |
1.13.12 | 690 | 8/3/2021 | |
1.13.11 | 756 | 7/30/2021 | |
1.13.10 | 731 | 7/29/2021 | |
1.13.9 | 712 | 7/27/2021 | |
1.13.8 | 641 | 7/25/2021 | |
1.13.7 | 686 | 7/20/2021 | |
1.13.6 | 677 | 7/16/2021 | |
1.13.5 | 729 | 7/13/2021 | |
1.13.4 | 721 | 7/8/2021 | |
1.13.3 | 702 | 7/7/2021 | |
1.13.2 | 703 | 7/4/2021 | |
1.13.1 | 679 | 7/2/2021 | |
1.13.0 | 672 | 6/30/2021 | |
1.12.0 | 527 | 5/21/2021 | |
1.11.7 | 750 | 3/30/2021 | |
1.11.6 | 687 | 3/30/2021 | |
1.11.5 | 741 | 3/18/2021 | |
1.11.4 | 864 | 3/18/2021 | |
1.11.3 | 980 | 3/18/2021 | |
1.11.2 | 773 | 3/14/2021 | |
1.11.0 | 814 | 1/22/2021 | |
1.10.8.535 | 757 | 1/4/2021 | |
1.10.7.533 | 806 | 12/10/2020 | |
1.10.7.532 | 870 | 11/30/2020 | |
1.10.6.530 | 846 | 10/26/2020 | |
1.10.6.527 | 834 | 10/25/2020 | |
1.10.5.526 | 836 | 10/22/2020 | |
1.10.4.514 | 879 | 10/18/2020 | |
1.10.3.509 | 846 | 10/14/2020 | |
1.10.2.504 | 829 | 10/9/2020 | |
1.10.2.503 | 849 | 10/8/2020 | |
1.9.1.381 | 882 | 8/20/2020 | |
1.9.0.380 | 953 | 8/16/2020 | |
1.8.5.376 | 925 | 8/11/2020 | |
1.8.3.374 | 905 | 8/10/2020 | |
1.8.3.373 | 894 | 8/9/2020 | |
1.8.2.372 | 950 | 8/9/2020 | |
1.8.1.370 | 879 | 8/6/2020 | |
1.8.1.369 | 864 | 8/5/2020 | |
1.8.0.368 | 927 | 8/5/2020 | |
1.7.17.367 | 1,098 | 8/4/2020 | |
1.7.15.365 | 962 | 8/3/2020 | |
1.7.14.364 | 990 | 8/2/2020 | |
1.7.13.363 | 984 | 8/2/2020 | |
1.7.12.362 | 977 | 8/1/2020 |