Compare commits

...

11 Commits

  1. 6
      Example/SaveSystem/Scene/SaveSystem.tscn
  2. 116
      Example/SaveSystem/Script/ViewSaveSystem.cs
  3. 82
      Manual/API/SaveToolsInterface.md
  4. 130
      Manual/GenerateTools.md
  5. BIN
      Manual/Img/GenerateTools_001.JPG
  6. 34
      Manual/Img/GenerateTools_001.JPG.import
  7. BIN
      Manual/Img/GenerateTools_002.JPG
  8. 34
      Manual/Img/GenerateTools_002.JPG.import
  9. BIN
      Manual/Img/GenerateTools_003.JPG
  10. 34
      Manual/Img/GenerateTools_003.JPG.import
  11. BIN
      Manual/Img/GenerateTools_004.JPG
  12. 34
      Manual/Img/GenerateTools_004.JPG.import
  13. BIN
      Manual/Img/GenerateTools_005.JPG
  14. 34
      Manual/Img/GenerateTools_005.JPG.import
  15. BIN
      Manual/Img/GenerateTools_006.JPG
  16. 34
      Manual/Img/GenerateTools_006.JPG.import
  17. 188
      Manual/ProtocolTools.md
  18. 276
      Manual/SaveTools.md
  19. 99
      ReadMe.md
  20. 386
      addons/EGFramework/Manual/EGSave.md
  21. 12
      addons/EGFramework/Module/EGObjects.cs
  22. 2
      addons/EGFramework/Module/Extension/EGSqlExtension.cs
  23. 8
      addons/EGFramework/Module/GenerateTools/Templete/Godot/UI/EGodotMenu.cs
  24. 12
      addons/EGFramework/Module/GenerateTools/Templete/Variant/EGDataStruct.cs
  25. 3
      addons/EGFramework/Module/NodeExtension/EGGodotPath.cs
  26. 50
      addons/EGFramework/Module/SaveTools/Data/EGDapper.cs
  27. 47
      addons/EGFramework/Module/SaveTools/Object/EGByteSave.cs
  28. 2
      addons/EGFramework/Module/SaveTools/Object/EGJsonSave.cs
  29. 2
      addons/EGFramework/Module/SaveTools/Object/EGRedisSave.cs
  30. 2
      addons/EGFramework/Module/SaveTools/SaveToolsInterface.cs
  31. 1
      project.godot

6
Example/SaveSystem/Scene/SaveSystem.tscn

@ -28,3 +28,9 @@ anchor_right = 1.0 @@ -28,3 +28,9 @@ anchor_right = 1.0
anchor_bottom = 0.5
grow_horizontal = 2
grow_vertical = 2
[node name="Window" type="Window" parent="."]
mode = 3
initial_position = 3
current_screen = 1
visible = false

116
Example/SaveSystem/Script/ViewSaveSystem.cs

@ -16,7 +16,11 @@ namespace EGFramework.Examples.Test { @@ -16,7 +16,11 @@ namespace EGFramework.Examples.Test {
Container container{ set; get; }
public override void _Ready()
{
TestTree();
// TestTree();
// TestTable();
// TestJson();
// TestDialog();
// TestMySQL();
}
public override void _ExitTree()
@ -24,6 +28,49 @@ namespace EGFramework.Examples.Test { @@ -24,6 +28,49 @@ namespace EGFramework.Examples.Test {
}
public void TestMySQL()
{
EGDapper mysqlSave = this.EGSave().Load<EGMysqlSave>("server=" + "localhost" + ";port=" + "3306" + ";uid=" + "root" + ";pwd=" + "root" + ";database=" + "Test3" + ";");
bool isExist = mysqlSave.ContainsData("DataStudent", 3);
GD.Print(isExist);
// mysqlSave.CreateTable<DataStudent>("DataStudent");
// DataStudent stuData = new DataStudent("Bob", 12);
// stuData.Path = new EGPathSelect(){Path = "AA"};
// mysqlSave.AddData("DataStudent",stuData);
// DataStu stu1 = new DataStu("Anti", 20,"London");
// mysqlSave.AddData("DataStudent",stu1);
// DataStu stu2 = new DataStu("CC", 23,"NewYork"){Age = 19};
// DataStu stu3 = new DataStu("Rocket", 24,"Paris"){Age = 26};
// List<DataStu> stuList = new List<DataStu>();
// stuList.Add(stu2);
// stuList.Add(stu3);
// mysqlSave.AddData<DataStu>("DataStudent",stuList);
// mysqlSave.RemoveData("DataStudent",2);
// IEnumerable<DataStu> findStudent = mysqlSave.FindData<DataStu>("DataStudent", e => e.Name == "CC");
// IEnumerable<DataStu> findStudent = mysqlSave.FindData<DataStu>("DataStudent","Name","CC");
// GD.Print(findStudent.Count() +" data has been find!");
// int count = 0;
// foreach (DataStu stu in findStudent)
// {
// DataStu NewData = new DataStu("CC_" + count, stu.Age, stu.Path);
// mysqlSave.UpdateData("DataStudent", NewData, stu.ID);
// count++;
// }
}
public void TestDialog()
{
DataStudent dataStudent = new DataStudent();
dataStudent.EGenerateDictiontaryByObject();
this.ExecuteAfterSecond(() =>
{
this.EGEditDialog(new DataStudent().EGenerateDictiontaryByObject(), e =>
{
GD.Print("Name:" + e["Name"] + "Age:" + e["Age"]);
}, "Edit");
}, 0.2f);
}
public void TestJson()
{
string json = @"{
@ -40,19 +87,21 @@ namespace EGFramework.Examples.Test { @@ -40,19 +87,21 @@ namespace EGFramework.Examples.Test {
'Date': new Date(123456789)
}
}";
EGJsonSave jsonManage = this.EGSave().Read<EGJsonSave>("Example", json);
GD.Print(jsonManage.GetObject<string>("CPU"));
JsonTextReader reader = new JsonTextReader(new StringReader(json));
while (reader.Read())
{
if (reader.Value != null)
{
GD.Print("Token: {"+reader.TokenType+"}, Value: {"+ reader.Value+"}");
}
else
{
GD.Print("Token: {"+ reader.TokenType+"}");
}
}
// JsonTextReader reader = new JsonTextReader(new StringReader(json));
// while (reader.Read())
// {
// if (reader.Value != null)
// {
// GD.Print("Token: {"+reader.TokenType+"}, Value: {"+ reader.Value+"}");
// }
// else
// {
// GD.Print("Token: {"+ reader.TokenType+"}");
// }
// }
}
public void TestTree()
@ -85,31 +134,18 @@ namespace EGFramework.Examples.Test { @@ -85,31 +134,18 @@ namespace EGFramework.Examples.Test {
EGodotTable table = container.CreateNode<EGodotTable>("Default");
table.InitData<DataStudent>(dataStudents);
EGSqliteSave SqliteTest = this.EGSave().Load<EGSqliteSave>("SaveData/test.db");
// IEnumerable<string> dataBaseKey = SqliteTest.GetKeys();
// GD.Print(dataBaseKey);
// foreach (string data in dataBaseKey)
// {
// GD.Print(data);
// }
EGodotSaveTable PersonTable = container.CreateNode<EGodotSaveTable>("SQLite");
PersonTable.InitSaveData<EGSqliteSave>(SqliteTest);
PersonTable.InitData<DataPerson>("person");
// EGodotTableRowData rowData = container.CreateNode<EGodotTableRowData>("RowData");
// rowData.Init(new Dictionary<string, object>() { { "Name", "Tom" }, { "Age", 18 } });
// EGodotRowData rowData2 = container.CreateNode<EGodotRowData>("RowData2");
// rowData2.Init(new Dictionary<string, object>() { { "Name", "Z" }, { "Age", 1 } });
// EGodotEditParam editParam = container.CreateNode<EGodotEditParam>("editParam");
// editParam.Init(new KeyValuePair<string, object>("数量",1));
// EGSqliteSave SqliteTest = this.EGSave().Load<EGSqliteSave>("SaveData/test.db");
// EGodotSaveTable PersonTable = container.CreateNode<EGodotSaveTable>("SQLite");
// PersonTable.InitSaveData<EGSqliteSave>(SqliteTest);
// PersonTable.InitData<DataPerson>("person");
}
}
public struct DataStudent
{
public int ID;
public string Name { get; set; }
public int Age;
public int ID;
public EGPathSelect Path { set; get; }
public DataStudent(string name, int age)
{
@ -119,8 +155,24 @@ namespace EGFramework.Examples.Test { @@ -119,8 +155,24 @@ namespace EGFramework.Examples.Test {
Path = new EGPathSelect();
}
}
public struct DataStu
{
public int ID;
public string Name { get; set; }
public int Age { set; get; }
public string Path { set; get; }
public DataStu(string name, int age,string path)
{
Name = name;
Age = age;
ID = 0;
Path = path;
}
}
public struct DataPerson{
public struct DataPerson
{
public string id { get; set; }
public string namee { set; get; }
public string workPlace { set; get; }

82
Manual/API/SaveToolsInterface.md

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
# IEGSave 接口说明
---
只读&非只读数据说明:
只读数据不实现写数据功能,非只读需要实现写数据功能。
正常数据通过Path加载,只读数据则是通过string加载,无法对其中Path进行写入操作。
| 接口名称 | 接口简介 |
| --------------------- | ------------ |
| IEGSave | 读写数据加载 |
| IEGSaveReadOnly | 只读数据加载 |
| IEGSaveObjectReadOnly | 只读对象 |
| IEGSaveObject | 读写对象 |
| IEGSaveDataReadOnly | 只读数据 |
| IEGSaveData | 读写数据 |
## IEGSave
### 描述
通用的存储数据加载接口,通过Path加载文件的数据。
### 方法说明
### void InitSaveFile(string path)
> 通过文件路径加载存储文件
## IEGSaveReadOnly
只读文件的数据加载接口,通过字符串或者字节流加载成对应的数据对象。
### void InitReadOnly(string data);
> 通过字符串加载文件内容,需要先从文本文件中读取,请求服务或者其他方式获取内容。
### void InitReadOnly(byte[] data);
> 通过字节流加载文件内容,需要先从字节流文件中读取,请求服务或者其他方式获取内容。
## IEGSaveObjectReadOnly
只读对象文件的获取数据接口
### T GetObject<T>(string objectKey) where T: new();
> 通过键获取对应的对象,如果是单个对象文件的话,则传空字符串即可。
## IEGSaveObject : IEGSaveObjectReadOnly
对象文件的获取&写入数据接口
### void SetObject<T>(string objectKey,T obj);
> 将key值与key对应的对象写入到该文件下。
## IEGSaveDataReadOnly
只读数据文件的获取数据接口
### T GetData<T>(string dataKey,object id) where T : new();
> 用于获取指定条目的数据对象。
### IEnumerable<T> GetAll<T>(string dataKey) where T : new();
> 用于获取key值下的所有列表数据
### IEnumerable<T> FindData<T>(string dataKey,Expression<Func<T, bool>> expression) where T : new();
> 用于查找key值下的所有满足条件的列表数据
## IEGSaveData
数据文件的获取&写入数据接口
### void SetData<TData>(string dataKey,TData data,object id);
> 将key值与key对应的对象的写入到该文件对应的位置(id)下,如果存在数据则进行覆盖。

130
Manual/GenerateTools.md

@ -0,0 +1,130 @@ @@ -0,0 +1,130 @@
# GenerateTools使用手册
> GenerateTools旨在生成任何应用程序中的组件,变量,对象,以及用到的一些流程等等。同时依赖于Save Tools强大的本地文件加载能力,Generate Tools可以通过配置各种文件实现界面的简单生成,菜单的生成,可编辑表格,可编辑项。
>
> 再此之上,有些通用模板也会放在此工具下,方便扩展与生成。
```mermaid
mindmap
root((Generate-Tools))
Code
SVG
Dialog
Basic
Confirm
Edit
File
UI
EditParam
Table
Menu
Tree
Inteface
Variant
Tree
Range
Select
Path
ReadOnly
```
## 📈生成一个可编辑表格
定义数据类,以学生信息为例
```csharp
public struct DataStudent
{
public int ID;
public string Name { get; set; }
public int Age;
public EGPathSelect Path { set; get; }
public DataStudent(string name, int age)
{
Name = name;
Age = age;
ID = 0;
Path = new EGPathSelect();
}
}
```
实例化一组学生信息对象列表,然后通过EGodotTable来对该列表进行初始化
```csharp
public void TestTable()
{
container = this.GetNode<TabContainer>("TabContainer");
List<DataStudent> dataStudents = new List<DataStudent>();
for (int stu = 0; stu < 10; stu++)
{
dataStudents.Add(new DataStudent("stu" + stu, 18));
}
for (int stu = 0; stu < 11; stu++)
{
dataStudents.Add(new DataStudent("A" + stu, 20 + stu));
}
EGodotTable table = container.CreateNode<EGodotTable>("Default");
table.InitData<DataStudent>(dataStudents);
}
```
运行结果如下
![GenerateTools_001](Img/GenerateTools_001.JPG)
![GenerateTools_001](Img/GenerateTools_002.JPG)
## 🌲生成一个树
定义一个Json,使用EGodotTree来对该Json进行初始化
```csharp
public void TestTree()
{
string json = @"{
'CPU': 'Intel',
'PSU': '500W',
'My' : {
'AA':'BB',
'Date': 111
}
}";
container = this.GetNode<TabContainer>("TabContainer");
EGodotTree eGodotTree = container.CreateNode<EGodotTree>("TestTree");
eGodotTree.InitByJson(json);
}
```
![GenerateTools_001](Img/GenerateTools_003.JPG)
## 🚪生成一个可编辑弹窗并弹出
使用上述定义过的DataStudent,我们创建一个可编辑弹窗,并且在弹窗编辑完成后打印编辑后的内容。由于Godot子节点先加载,父节点后加载的机制,需要等待父节点实例化之后才能调用弹窗功能,我们使用一个延时方法(参考NodeExtension-EGThread部分),延时弹出该弹窗。
```csharp
public void TestDialog()
{
DataStudent dataStudent = new DataStudent();
dataStudent.EGenerateDictiontaryByObject();
this.ExecuteAfterSecond(() =>
{
this.EGEditDialog(new DataStudent().EGenerateDictiontaryByObject(), e =>
{
GD.Print("Name:" + e["Name"] + "Age:" + e["Age"]);
}, "Edit");
},0.2f);
}
```
调用该方法后会弹出空白弹窗
![GenerateTools_001](Img/GenerateTools_004.JPG)
输入内容
![GenerateTools_001](Img/GenerateTools_005.JPG)
点击确认,控制台输出姓名与年龄的信息,此时您可以使用SaveTools写入本地配置文件,或者是数据库,再或者向后台,上位机或下位机发送该信息。
![GenerateTools_001](Img/GenerateTools_006.JPG)

BIN
Manual/Img/GenerateTools_001.JPG

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

34
Manual/Img/GenerateTools_001.JPG.import

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b2tuqm72haaab"
path="res://.godot/imported/GenerateTools_001.JPG-fef7115ccd57135de62d4bd2954db1db.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Manual/Img/GenerateTools_001.JPG"
dest_files=["res://.godot/imported/GenerateTools_001.JPG-fef7115ccd57135de62d4bd2954db1db.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

BIN
Manual/Img/GenerateTools_002.JPG

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

34
Manual/Img/GenerateTools_002.JPG.import

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c4fu1phlhotka"
path="res://.godot/imported/GenerateTools_002.JPG-7bb9bdf7b55c6f9bc9f2bca6dee8a982.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Manual/Img/GenerateTools_002.JPG"
dest_files=["res://.godot/imported/GenerateTools_002.JPG-7bb9bdf7b55c6f9bc9f2bca6dee8a982.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

BIN
Manual/Img/GenerateTools_003.JPG

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

34
Manual/Img/GenerateTools_003.JPG.import

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://crtdss0o45blw"
path="res://.godot/imported/GenerateTools_003.JPG-f588ba68b13367797de19c266c495b79.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Manual/Img/GenerateTools_003.JPG"
dest_files=["res://.godot/imported/GenerateTools_003.JPG-f588ba68b13367797de19c266c495b79.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

BIN
Manual/Img/GenerateTools_004.JPG

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

34
Manual/Img/GenerateTools_004.JPG.import

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://1y1cdhnueqcp"
path="res://.godot/imported/GenerateTools_004.JPG-87913768d75b083efc5aece06f847991.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Manual/Img/GenerateTools_004.JPG"
dest_files=["res://.godot/imported/GenerateTools_004.JPG-87913768d75b083efc5aece06f847991.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

BIN
Manual/Img/GenerateTools_005.JPG

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

34
Manual/Img/GenerateTools_005.JPG.import

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bb7r4akyiehi8"
path="res://.godot/imported/GenerateTools_005.JPG-d203aa9f562e6d6e3ea80cdbaa8a92f9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Manual/Img/GenerateTools_005.JPG"
dest_files=["res://.godot/imported/GenerateTools_005.JPG-d203aa9f562e6d6e3ea80cdbaa8a92f9.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

BIN
Manual/Img/GenerateTools_006.JPG

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

34
Manual/Img/GenerateTools_006.JPG.import

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://gbr2uywo1eip"
path="res://.godot/imported/GenerateTools_006.JPG-e3f17b752a2788befdbb14fd67a4b7fe.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Manual/Img/GenerateTools_006.JPG"
dest_files=["res://.godot/imported/GenerateTools_006.JPG-e3f17b752a2788befdbb14fd67a4b7fe.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

188
addons/EGFramework/Manual/EGMessage.md → Manual/ProtocolTools.md

@ -8,6 +8,8 @@ Protocol Tools允许您在任何通讯物理层发送信息、接受服务器返 @@ -8,6 +8,8 @@ Protocol Tools允许您在任何通讯物理层发送信息、接受服务器返
目前工具以发布+订阅的方式处理消息,后续会增加问答的方式处理消息。
本指南中,您将学到以下内容
- 如何在互联网&串口通讯&文件读写&进程吞吐中,发送您的请求,获取您的响应消息。
@ -15,6 +17,33 @@ Protocol Tools允许您在任何通讯物理层发送信息、接受服务器返 @@ -15,6 +17,33 @@ Protocol Tools允许您在任何通讯物理层发送信息、接受服务器返
- 自定义插拔式的开启或关闭消息处理功能。
- Protocol Tools的消息解耦原理
Protocol Tools 的结构如下
```mermaid
mindmap
root((ProtocolTools))
EGMessage
ProtocolSchedule
Internet
TCPClient
TCPServer
UDP
MQTT
SSH
WebsocketClient
WebsocketServer - Only Godot
SerialPort
Other
FileStream
Process
Soft
CommandLine
```
---
# 目录
@ -222,3 +251,162 @@ public struct DataStudent{ @@ -222,3 +251,162 @@ public struct DataStudent{
}
```
# 补充一点私货
如果您对Protocol Tools的底层运行有兴趣,可以看看这部分。如有不足之处,欢迎提供相关改进建议。
## 7.关于运行原理
本部分内容可能比较抽象,比较难以用文字表达,故设计了下列若干图来展示具体的内容部分。
### 消息发送机制
对应函数EGSendMessage
---
注:
1. IProtocolSend表示实现了该发送消息接口的工具类。
2. RequestMsgEvent表示中途构建的消息结构体,结构体的发送内容必须包含:发送内容(实现IRequest,参考上述定义您的请求部分。)、发送对象、协议类型。
3. RequestCache为延时发送的队列,实现延时出队的功能。
4. OnRequest为EasyEvent<RequestMsgEvent>类型的消息结构体委托,用于推送给所有注册发送功能的具体通讯对象。
---
```mermaid
flowchart LR
1([开始])--IRequest,sender,ProtocolType-->EGSendMessage--
new ResponseMsgEvent-->OnRequest
IProtocolSend--EGRegisterSendAction-->OnRequest
OnRequest--定时触发-->I(IProtocolSend)-->发送消息-->2([结束])
```
消息结构体构建
```mermaid
block-beta
columns 6
doc["RequestMsgEvent"]:6
IRequest["IRequest"]:2
sender["sender"]:2
protocolType["protocolType"]:2
string["string"]:1
bytes["bytes"]:1
bytes space:2 tcp
tcp["tcp&udp"]:1
etc["..."]:1
```
消息发送序列图
```mermaid
sequenceDiagram
participant EGSendMessage
participant RequestCache
participant OnRequest
participant IProtocolSend
autonumber
IProtocolSend->>OnRequest:Regist(SendAction)
EGSendMessage->>OnRequest: (No Delay)RequestMsgEvent
OnRequest->>IProtocolSend: Invoke(RequestMsgEvent)
EGSendMessage->>+RequestCache: (Delay)Enqueue(RequestMsgEvent)
loop Every 0.1s
RequestCache->>RequestCache: TimerElapsed(delay--Default0.1s)
RequestCache->>-OnRequest: Dequeue(RequestMsgEvent)
end
OnRequest->>IProtocolSend: Invoke(RequestMsgEvent)
```
### 消息接收机制
对应EG(On&Off)Message,EGRegisterMessageEvent
```mermaid
flowchart TD
start([开始])-->SourceData
subgraph ExecuteResponse
SourceData--trysetData(string,bytes)-->IResponse
IResponse--Construct-->ResponseMsgEvent
end
ResponseMsgEvent-->OnResponse
EGRegisterMessageEvent-->OnResponse
OnResponse--Invoke-->MessageEvent-->over([结束])
IProtocolReceived--GetReceivedMsg-->EGProtocolSchedule
EGProtocolSchedule--CheckedProcess(Execute EveryFrame)-->SourceData
EGProtocolSchedule<-->EGProtocolScheduleGodot
```
消息结构体构建
ResponseMsgEvent
```mermaid
block-beta
columns 6
doc["ResponseMsgEvent"]:6
IResponse["IResponse"]:2
sender["sender"]:2
protocolType["protocolType"]:2
TrySetData["TrySetData(string,byte)"]:2
TrySetData space:2 tcp
tcp["tcp&udp"]:1
etc["..."]:1
```
ResponseMsg
```mermaid
block-beta
columns 6
doc["ResponseMsg"]:6
stringData["stringData"]:1
byteData["byteData"]:1
sender["sender"]:2
protocolType["protocolType"]:2
```
消息接收序列图
注:ReceiveResponse实际为EGOnMessage&EGOffMessage注册的委托
```mermaid
sequenceDiagram
participant IProtocolReceived
participant EGProtocolSchedule
participant EGOnMessage
participant OnDataReceived
participant ReceiveResponse
participant OnResponse
participant EGRegisterMessageEvent
autonumber
EGOnMessage->>+ReceiveResponse:Type
ReceiveResponse->>-OnDataReceived:Register
EGRegisterMessageEvent->>+OnResponse:Register
OnResponse->>-OnResponse:TypeCheck
loop Every frame
EGProtocolSchedule->>+IProtocolReceived:GetReceivedMsg(ResponseMsg)
IProtocolReceived-->>IProtocolReceived:DataReceiveProcess
IProtocolReceived->>-EGProtocolSchedule:ResponseMsg
end
EGProtocolSchedule->>OnDataReceived:ResponseMsg
OnDataReceived->>+ReceiveResponse:IResponse,sender,protocolType
ReceiveResponse->>ReceiveResponse:CheckIsSet
ReceiveResponse->>-OnResponse:if(Set)-Invoke(ResponseMsgEvent)
OnResponse->>EGRegisterMessageEvent:Execute
```

276
Manual/SaveTools.md

@ -0,0 +1,276 @@ @@ -0,0 +1,276 @@
# SaveTools使用手册
---
注:SaveTools 目前因为接口反复修改的关系,Load方法增加对象的返回值以提供更多的操作方法。下面Not Complete表示该部分功能并未开发完毕。
```mermaid
mindmap
root((SaveTools))
Data
CSV
LiteDB
Dapper
MySql
Sqlite
File
FTP
SFTP
LocalFileSystem
WebDav - Not Complete
Object
Json
Redis
Byte - Not Complete
```
## 支持的数据类型
- `Object` 对象类型的存储类型,通过key-value的方式获取对应的对象,常见的例子有Json,Redis等等。
- `Data` 数据类型的存储类型,同样通过key-Table的方式获取对应的数据表,通常为各种类型的数据库,比如MySql,Sqlite,LiteDB,CSV表格文件等等。
- `File` 文件类型的存储类型,提供对应的下载,上传接口以及各类文件系统管理接口,通常为各种文件共享服务,比如FTP,WebDav,本地文件系统等等。
## 加载存储管理对象(可读可写)
Load为可读写存储对象的加载,通常是用Path,或者数据库地址来进行实例化。
以SQLite数据库为例
```csharp
EGSqliteSave SqliteTest = this.EGSave().Load<EGSqliteSave>("SaveData/test.db");
```
具体使用方法详见API - IEGSaveData部分。
## 读取存储管理对象(只读)
Read为只读存储对象的加载,通常以字符&字节流的方式来获取,由于是只读数据,仅包含相关数据的搜索,获取功能。
以Json为例
```csharp
string json = @"{
'CPU': 'Intel',
'PSU': '500W',
'Drives': [
'DVD read/writer'
/*(broken)*/,
'500 gigabyte hard drive',
'200 gigabyte hard drive'
],
'My' : {
'AA':'BB',
'Date': new Date(123456789)
}
}";
EGJsonSave jsonManage = this.EGSave().Read<EGJsonSave>("Example", json);
GD.Print(jsonManage.GetObject<string>("CPU"));
```
## 数据库增删改查
针对Data型的存储类型,可以简单实现数据库的增删改查,同时可使用Database的建表操作完成数据库的初始化。
首先我们定义两个结构类型,其一是符合类型,带相关对象的:
```csharp
public struct DataStudent
{
public int ID;
public string Name { get; set; }
public int Age;
public EGPathSelect Path { set; get; }
public DataStudent(string name, int age)
{
Name = name;
Age = age;
ID = 0;
Path = new EGPathSelect();
}
}
```
其二是只包含原始类型(IsPrimitive)和string类型的结构,其中类结构里面的所有属性(除了主键ID自增外)皆为属性类型。
```csharp
public struct DataStu
{
public int ID;
public string Name { get; set; }
public int Age { set; get; }
public string Path { set; get; }
public DataStu(string name, int age,string path)
{
Name = name;
Age = age;
ID = 0;
Path = path;
}
}
```
后面我们会讲到两种类型兼容方面的差异,第一种仅支持单项操作,复数操作无法很好的兼容,第二种则支持复数操作(适用于数据批量导入,备份功能的定制)。
以MySQL为例:
### 数据库连接
```csharp
EGDapper mysqlSave = this.EGSave().Load<EGMysqlSave>("server=" + "localhost" + ";port=" + "3306" + ";uid=" + "root" + ";pwd=" + "root" + ";database=" + "Test3" + ";");
```
或者
```csharp
EGMysqlSave mysqlSave = this.EGSave().Load<EGMysqlSave>("server=" + "localhost" + ";port=" + "3306" + ";uid=" + "root" + ";pwd=" + "root" + ";database=" + "Test3" + ";");
```
### 查询表名是否存在
```csharp
bool isExist = mysqlSave.ContainsKey("DataStudent");
GD.Print(isExist);
```
### 查询对应ID的条目是否存在
```csharp
bool isExist = mysqlSave.ContainsData("DataStudent",3);
GD.Print(isExist);
```
### 初始化表
如果包含复合对象的,比如其它类对象的声明(例如上面的 EGPathSelect),此选项创建的字段为varchar(255),同String。
```csharp
mysqlSave.CreateTable<DataStudent>("DataStudent");
```
### 增加数据
关于Path属性,会根据该类的ToString()方法,插入到表格对应的Path字段中。
```csharp
DataStudent stuData = new DataStudent("Bob", 12);
stuData.Path = new EGPathSelect(){Path = "AA"};
mysqlSave.AddData("DataStudent",stuData);
```
或者
```csharp
DataStu stu1 = new DataStu("Anti", 20,"London");
mysqlSave.AddData("DataStudent",stu1);
```
### 批量增加数据
注意,批量增加数据时,需要保证对象结构必须包含表字段的所有非空属性(此框架提供的建表方法字段默认非空)。其中类结构里面的所有属性(除了主键ID自增外)皆为属性类型。
```csharp
DataStu stu2 = new DataStu("CC", 23,"NewYork"){Age = 19};
DataStu stu3 = new DataStu("Rocket", 24,"Paris"){Age = 26};
List<DataStu> stuList = new List<DataStu>();
stuList.Add(stu2);
stuList.Add(stu3);
mysqlSave.AddData<DataStu>("DataStudent",stuList);
```
### 删除数据(通过ID)
删除ID为2的一条数据(可配合FindData找到要删除的内容的ID,实现批量删除)
```csharp
mysqlSave.RemoveData("DataStudent",2);
```
### 查找数据(通过表达式)
查找Name为CC的数据
```csharp
IEnumerable<DataStu> findStudent = mysqlSave.FindData<DataStu>("DataStudent", e => e.Name == "CC");
GD.Print(findStudent.Count() +" data has been find!");
foreach (DataStu stu in findStudent)
{
GD.Print(stu.Path);
}
```
### 查找数据(通过关键词)
查找Name包含C的数据,注意:通过关键词查找的数据大小写不敏感,包含小写c也会被检索出来
```csharp
IEnumerable<DataStu> findStudent = mysqlSave.FindData<DataStu>("DataStudent","Name","C");
GD.Print(findStudent.Count() +" data has been find!");
foreach (DataStu stu in findStudent)
{
GD.Print(stu.Path);
}
```
### 修改数据
查找所有Name字段包含CC的数据,并给名称增加编号。
```csharp
IEnumerable<DataStu> findStudent = mysqlSave.FindData<DataStu>("DataStudent","Name","CC");
GD.Print(findStudent.Count() +" data has been find!");
int count = 0;
foreach (DataStu stu in findStudent)
{
DataStu NewData = new DataStu("CC_" + count, stu.Age, stu.Path);
mysqlSave.UpdateData("DataStudent", NewData, stu.ID);
count++;
}
```
## 开发计划(随版本更新)
Object:
- [x] Json
- [x] Redis
- [ ] Byte
- [ ] etc...
Data:
- [x] LiteDB
- [x] Dapper
- [x] Sqlite
- [x] MySql
- [x] Csv
- [ ] etc...
File:
- [x] LocalFile
- [x] Ftp
- [x] SFtp
- [ ] WebDav
- [ ] etc...
# 使用案例
## 配置文件写入与加载
## 简易背包
## 使用CQRS实现可追溯的文件操作

99
ReadMe.md

@ -13,16 +13,45 @@ @@ -13,16 +13,45 @@
>
> 目前该框架可能还有很多欠缺与不足,最终目的是做一个方便可靠好用的通讯&存储&资源生成&界面生成框架、用户无需过多学习、开箱即用。
# 关于Godot引擎(摘自[Godot Engine (4.x) 简体中文文档](https://docs.godotengine.org/zh-cn/4.x/about/introduction.html))
## 关于Godot引擎(摘自[Godot Engine (4.x) 简体中文文档](https://docs.godotengine.org/zh-cn/4.x/about/introduction.html))
> Godot 引擎是一款功能丰富的跨平台游戏引擎,可以通过统一的界面创建 2D 和 3D
> 游戏。它提供了一套全面的通用工具,因此用户可以专注于制作游戏,而无需重新发明轮子。游戏可以一键导出到多个平台,包括主流的桌面平台(Linux、macOS、Windows)、移动平台(Android、iOS)、基于
> Web 的平台以及主机平台。
>
> Web 的平台以及主机平台。
>
> Godot 在 [宽松的 MIT 许可证](https://docs.godotengine.org/zh-cn/4.x/about/complying_with_licenses.html#doc-complying-with-licenses) 下完全自由且开源,没有附加条件、没有抽成、什么都没有。用户的游戏乃至引擎的每一行代码,都归用户自己所有。Godot 的开发完全独立且由社区驱动,允许用户为满足需求重塑引擎。它受到不以盈利为目标的 [Godot 基金会](https://godot.foundation/)支持。
---
EGFramework - 功能一览
```mermaid
mindmap
root((EGFramework))
★Tools
SaveTools
GenerateTools
ProtocolTools
Extension
CRC
Convert
DateTime
Encoding
SQL
IP
CommandSequence
EGCQRS
IOCManage
EGObject
EventManage
EGEvent
EasyEvent
```
# 一、准备工作
@ -100,67 +129,11 @@ public partial class EGTest : Node,IEGFramework{ @@ -100,67 +129,11 @@ public partial class EGTest : Node,IEGFramework{
更多可参考Example。
## 2.2 发送与监听消息
## 2.3 使用本地存储
# 三、EGFramework-API
目前已有的EGFramework功能组件。标记是目前已编写完成,未标记是未编写完成或未测试。
- [x] ProtocolTools&ProtocolExtension
- [x] SaveTools
- [x] OtherTools
- [x] Extension
- [x] NodeExtension(仅Godot下可用)
- [ ] GenerateTools
- [ ] UITools
### 3.1 消息篇(EGMessage-ProtocolTools)
---
#### 通讯支持
- [x] TCPClient
- [x] TCPServer
- [x] UDP(Listen&Send)
- [x] SerialPort
- [x] Ssh
- [x] WebSocketClient
- [x] Bacnet
- [x] MQTT
- [ ] HttpClient
- [ ] HttpServer
#### 异步处理支持
- [x] FileStream
- [x] Process
### 3.2 存储篇(EGMessage-ProtocolTools)
#### 键值对象存储支持
- [x] Json
- [x] Redis
- [ ] Byte
# 三、目录
#### 数据存储支持
## [ProtocolTools](./Manual/ProtocolTools.md)
- [x] Csv
- [x] LiteDB
- [x] MySQL(Dapper)
- [x] Sqlite(Dapper)
- [x] Dapper
## [SaveTools](./Manual/SaveTools.md)
#### 文件存储支持
## [GenerateTools](./Manual/GenerateTools.md)
- [x] FTP
- [x] LocalFile
- [ ] Sftp
- [ ] WebDav

386
addons/EGFramework/Manual/EGSave.md

@ -1,386 +0,0 @@ @@ -1,386 +0,0 @@
# SaveTools(EGSave)模块使用说明
---
注:下述`数据`无特殊声明默认指代:对象的集合。
SaveTools使用了两种数据格式,一种是表式存储,一种是对象存储,统一使用key-value方式存储数据,通过唯一key值锁定对应的数据。如果是只读数据,则需指定唯一标识key,读写数据,这个key值则为文件路径(唯一)。
在使用该库时,一定要保证该数据被加载。可以重复读取数据文件,如果外部进行了修改,新读取的数据会覆盖掉原来的数据。使用流程:加载数据->读写数据或者其他操作
需要在对应Godot的Node类下实现接口 `IEGFramework`
下面演示一个打开Res文件夹的示例:
```csharp
public partial class EGSaveTest : Node,IEGFramework{
public override void _Ready()
{
base._Ready();
this.EGSave().OpenResPath();
}
}
```
数据工具类开发状态如下:
只读&非只读数据:
- [x] CSV
- [x] Json
- [ ] XML
- [ ] etc...
非只读数据:
- [x] LiteDB
- [x] Byte
- [ ] Sqlite
- [ ] Other DataBase
- [ ] etc...
# API参考
---
# EGSave 使用说明
## 属性
暂无
## 方法
| 方法名 | 简介 |
| -------------------------------------------------------------------------------------------------------- | ---------------- |
| void LoadDataFile<TSaveData>(string path) | 加载数据文件(需要路径) |
| void ReadData<TReadOnlyData>(string key,string data) | 读取数据(需获取字符串原始值) |
| void ReadData<TReadOnlyData>(string key,byte[] data) | 读取数据(需获取字节流原始值) |
| void LoadObjectFile<TSaveObject>(string path) | 加载对象文件(需要路径) |
| void ReadObject<TReadOnlyObject>(string key,string data) | 读取对象(需获取字符串原始值) |
| void ReadObject<TReadOnlyObject>(string key,byte[] data) | 读取对象(需获取字节流原始值) |
| void Unload(string keyOrPath) | 卸载数据 |
| List<string> GetKeys() | 获取所有加载过的key或者路径值 |
| void SetObject<TObject>(string path,string objectKey,TObject obj) | 设置对象(写入文件) |
| TObject GetObject<TObject>(string path,string key) | 获取对象(读取文件) |
| void SetData<TData>(string path,string dataKey,TData data,int id) | 设置数据(写入文件) |
| TData GetData<TData>(string keyOrPath,string key,int id) | 获取单个数据(读取文件) |
| IEnumerable<TData> GetAllData<TData>(string keyOrPath,string key) | 获取全部数据(读取文件) |
| IEnumerable<TData> FindData<TData>(string keyOrPath,string key,Expression<Func<TData, bool>> expression) | 查找符合条件的对应数据 |
| OpenResPath() | 打开Res文件目录 |
| OpenUserPath() | 打开User文件目录 |
## 扩展方法
| 方法名 | 简介 |
| ------------------------------------------- | -------------- |
| this.EGSave() | 使用存储模块 |
| [string].GetGodotResPath(this string path) | 转为res文件下的相对路径 |
| [string].GetGodotUserPath(this string path) | 转为User文件下的相对路径 |
## 属性说明
暂无
## 方法说明
### LoadDataFile<T>(string path)
从路径中加载数据文件,因为是可读写,所以必须指定对应的文件路径位置,如果不存在该文件则会新建对应数据文件。
- T:指代任何一个数据存储工具类
- Path:文件的相对路径&绝对路径
```csharp
string Path1 = "Data/Test1.csv".GetGodotResPath();
this.EGSave().LoadDataFile<EGCsvSave>(Path1);
```
### ReadData<T>(string key,string data)
### ReadData<T>(string key,byte[] data)
从文本数据中读取数据,并且赋予对应的key值方便索引到该数据位置上。由于是只读数据,不会创建文件,也不会存在路径信息。
- T:指代任何一个数据工具类
- key:数据的索引,用于定位数据内容。
- data:原始数据,字符串格式或者byte[]字节流。
```csharp
FileAccess testCsv = FileAccess.Open("res://TestCsv.csv", FileAccess.ModeFlags.Read);
this.EGSave().ReadData<EGCsvSave>("TestCsv",testCsv.GetAsText());
```
### LoadObjectFile<T>(string path)
从路径中加载对象文件,因为是可读写,所以必须指定对应的文件路径位置,如果不存在该文件则会新建对应数据文件。
- T:指代任何一个对象存储工具类
- Path:文件的相对路径&绝对路径
```csharp
string Path2 = "Data1.json".GetGodotResPath();
this.EGSave().LoadObjectFile<EGJsonSave>(Path2);
```
### ReadObject<T>(string key,string data)
### ReadObject<T>(string key,byte[] data)
从文本数据中读取对象,并且赋予对应的key值方便索引到该数据位置上。由于是只读对象,不会创建文件,也不会存在路径信息。
- T:指代任何一个对象工具类
- key:对象的索引,用于定位对象内容。
- data:原始数据,字符串格式或者byte[]字节流。
```csharp
FileAccess testJson = FileAccess.Open("res://TestJson.json", FileAccess.ModeFlags.Read);
this.EGSave().ReadObject<EGJsonSave>("TestJson",testJson.GetAsText());
```
### Unload(string keyOrPath)
卸载已读取或者加载的数据,并删除对应key值下的数据,此方法执行后,不再能获取对应的数据,也不能写入文件,需要重新加载。
- keyOrPath:key值或者路径值
```csharp
this.EGSave().Unload("TestCsv");
```
### List<string> GetKeys()
获取所有加载过的key值或者路径值。
```csharp
List<string> keys = this.EGSave().GetKeys();
```
### SetObject<T>(string path,string objectKey,TObject obj)
把对象写入文件中。需要先加载再写入。
- T:指代任何一个对象工具类
- path:对象文件的路径值
- objectKey:对象文件的key值
- obj:要写入的对象
```csharp
public class Customer
{
[CsvParam("ID")]
public int Id { get; set; }
[CsvParam("Name")]
public string Name { get; set; }
public string[] Phones { get; set; }
[CsvParam("是否启用")]
public bool IsActive { get; set; }
}
public partial class EGSaveTest : Node,IEGFramework{
public override void _Ready()
{
string Path2 = "Data1.json".GetGodotResPath();
this.EGSave().LoadObjectFile<EGJsonSave>(Path2);
        this.EGSave().SetObject(Path2,"Customer1",new Customer()
            { Name = "Andy" });
}
}
```
### TObject GetObject<T>(string path,string key)
从文件中获取对象,同样需要先加载再获取。
- TObject:要获取的对象类型。
- path:对象文件的路径值
- key:对象的key值
```csharp
string Path2 = "Data1.json".GetGodotResPath();
this.EGSave().LoadObjectFile<EGJsonSave>(Path2);
Customer customer = this.EGSave().
GetObject<Customer>("Data1.json","Customer1");
```
### SetData<T>(string path,string dataKey,TData data,int id)
把一条数据写入文件中的指定位置。特别注意,如果写入的位置超出了文件中的数据量,则会进行追加数据,否则覆盖对应位置的数据。
- T:指代任何一个数据工具类
- path:数据文件的路径值
- dataKey:数据文件的key值
- data:要写入的数据
- id:指代第x条数据
```csharp
string Path2 = "TestCsv.csv".GetGodotResPath();
this.EGSave().LoadObjectFile<EGJsonSave>(Path2);
this.EGSave().SetData(Path1,"Customer1",
    new Customer() { Name = "Andy" },9);
```
### T GetData<T>(string keyOrPath,string key,int id)
获取文件中特定key值的列表里,第x条数据。
- keyOrPath:文件的路径,或者读取后存储的key值。
- key:文件中的数据列表对应的key值。
- id:第【id】条
```csharp
string Path1 = "SaveData/TestCsv.csv".GetGodotResPath();
this.EGSave().LoadDataFile<EGCsvSave>(Path1);
Customer customer1 = this.EGSave().GetData<Customer>(Path1,"",0);
GD.Print(customer1.Id +"|" + customer1.Name);
```
### IEnumerable<T> GetAllData<T>(string keyOrPath,string key)
获取文件中特定key值的全部数据。
- keyOrPath:文件的路径,或者读取后存储的key值。
- key:文件中的数据列表对应的key值。
```csharp
string Path1 = "SaveData/TestCsv.csv".GetGodotResPath();
this.EGSave().LoadDataFile<EGCsvSave>(Path1);
IEnumerable<Customer> allResult = this.EGSave().GetAllData<Customer>(Path1,"");
foreach(Customer customer in allResult){
GD.Print(customer.Id +"|" + customer.Name);
}
```
### IEnumerable<T> FindData<T> (string keyOrPath,string key,Expression<Func<T, bool>> expression)
查找文件中特定key值的全部符合条件的数据。
- keyOrPath:文件的路径,或者读取后存储的key值。
- key:文件中的数据列表对应的key值。
- Expression : 查询条件
```csharp
string Path1 = "SaveData/TestCsv.csv".GetGodotResPath();
this.EGSave().LoadDataFile<EGCsvSave>(Path1);
IEnumerable<Customer> findResult = this.EGSave().FindData<Customer>(Path1,"",cus=>cus.Id==0);
foreach(Customer customer in findResult){
GD.Print(customer.Id +"|" + customer.Name);
}
```
### OpenResPath()
打开godot对应的res文件夹
### OpenUserPath()
打开godot对应的user文件夹
# IEGSave 接口说明与扩展建议
---
只读&非只读数据说明:
只读数据不实现写数据功能,非只读需要实现写数据功能。
正常数据通过Path加载,只读数据则是通过string加载,无法对其中Path进行写入操作。
| 接口名称 | 接口简介 |
| --------------------- | ------ |
| IEGSave | 读写数据加载 |
| IEGSaveReadOnly | 只读数据加载 |
| IEGSaveObjectReadOnly | 只读对象 |
| IEGSaveObject | 读写对象 |
| IEGSaveDataReadOnly | 只读数据 |
| IEGSaveData | 读写数据 |
## IEGSave
### 描述
通用的存储数据加载接口,通过Path加载文件的数据。
### 方法说明
### void InitSaveFile(string path)
> 通过文件路径加载存储文件
## IEGSaveReadOnly
只读文件的数据加载接口,通过字符串或者字节流加载成对应的数据对象。
### void InitReadOnly(string data);
> 通过字符串加载文件内容,需要先从文本文件中读取,请求服务或者其他方式获取内容。
### void InitReadOnly(byte[] data);
> 通过字节流加载文件内容,需要先从字节流文件中读取,请求服务或者其他方式获取内容。
## IEGSaveObjectReadOnly
只读对象文件的获取数据接口
### T GetObject<T>(string objectKey) where T: new();
> 通过键获取对应的对象,如果是单个对象文件的话,则传空字符串即可。
## IEGSaveObject : IEGSaveObjectReadOnly
对象文件的获取&写入数据接口
### void SetObject<T>(string objectKey,T obj);
> 将key值与key对应的对象写入到该文件下。
## IEGSaveDataReadOnly
只读数据文件的获取数据接口
### T GetData<T>(string dataKey,object id) where T : new();
> 用于获取指定条目的数据对象。
### IEnumerable<T> GetAll<T>(string dataKey) where T : new();
> 用于获取key值下的所有列表数据
### IEnumerable<T> FindData<T>(string dataKey,Expression<Func<T, bool>> expression) where T : new();
> 用于查找key值下的所有满足条件的列表数据
## IEGSaveData
数据文件的获取&写入数据接口
### void SetData<TData>(string dataKey,TData data,object id);
> 将key值与key对应的对象的写入到该文件对应的位置(id)下,如果存在数据则进行覆盖。

12
addons/EGFramework/Module/EGObjects.cs

@ -3,13 +3,13 @@ using System.Collections.Generic; @@ -3,13 +3,13 @@ using System.Collections.Generic;
namespace EGFramework
{
public interface IEGObject
public interface IEGObjects
{
void RegisterObject<T>(T object_);
T GetObject<T>() where T : class,new();
}
public class EGObject : EGModule,IEGObject
public class EGObjects : EGModule,IEGObjects
{
private IOCContainer ObjectContainer = new IOCContainer();
public override void Init()
@ -40,25 +40,25 @@ namespace EGFramework @@ -40,25 +40,25 @@ namespace EGFramework
{
public static T EGGetObject<T>(this IEGFramework self) where T : class,new()
{
return EGArchitectureImplement.Interface.GetModule<EGObject>().GetObject<T>();
return EGArchitectureImplement.Interface.GetModule<EGObjects>().GetObject<T>();
}
}
public static class CanRegisterObjectExtension
{
public static void EGRegisterObject<T>(this IArchitecture self,T object_) where T : class,new()
{
self.GetModule<EGObject>().RegisterObject(object_);
self.GetModule<EGObjects>().RegisterObject(object_);
}
public static void EGRegisterObject<T>(this IEGFramework self,T object_) where T : class,new()
{
EGArchitectureImplement.Interface.GetModule<EGObject>().RegisterObject(object_);
EGArchitectureImplement.Interface.GetModule<EGObjects>().RegisterObject(object_);
}
}
public static class CanContainsObjectExtension{
public static bool EGContainsObject<T>(this IEGFramework self)
{
return EGArchitectureImplement.Interface.GetModule<EGObject>().ContainsObject<T>();
return EGArchitectureImplement.Interface.GetModule<EGObjects>().ContainsObject<T>();
}
}

2
addons/EGFramework/Module/Extension/EGSqlExtension.cs

@ -123,7 +123,7 @@ namespace EGFramework @@ -123,7 +123,7 @@ namespace EGFramework
}
keySet = keySet.TrimEnd(',');
string createSql = @"CREATE TABLE " + tableName + " (" +
"`ID` INTEGER PRIMARY KEY AUTOINCREMENT, " + keySet
"`ID` INTEGER PRIMARY KEY AUTO_INCREMENT, " + keySet
+ ");";
return createSql;
}

8
addons/EGFramework/Module/GenerateTools/Templete/Godot/UI/EGodotMenu.cs

@ -7,7 +7,7 @@ namespace EGFramework.UI @@ -7,7 +7,7 @@ namespace EGFramework.UI
{
public Dictionary<string, Control> PageContainer { set; get; } = new Dictionary<string, Control>();
public void RegisterPage<T>(string name,T page) where T : Control
public void RegisterPage<T>(string name, T page) where T : Control
{
if (PageContainer.ContainsKey(name))
{
@ -15,15 +15,15 @@ namespace EGFramework.UI @@ -15,15 +15,15 @@ namespace EGFramework.UI
}
else
{
PageContainer.Add(name,page);
PageContainer.Add(name, page);
}
}
public void OpenPage<T>(string name,T page) where T : Control
public void OpenPage<T>(string name, T page) where T : Control
{
page.Visible = true;
}
}
}

12
addons/EGFramework/Module/GenerateTools/Templete/Variant/EGDataStruct.cs

@ -37,6 +37,18 @@ namespace EGFramework @@ -37,6 +37,18 @@ namespace EGFramework
{
return Path;
}
public EGPathSelect() { Path = ""; IsDir = false; }
public EGPathSelect(string path)
{
this.Path = path;
this.IsDir = false;
}
public EGPathSelect(string path, bool isDir)
{
this.Path = path;
this.IsDir = isDir;
}
}
public interface IEGReadOnlyString

3
addons/EGFramework/Module/NodeExtension/EGGodotPath.cs

@ -18,10 +18,9 @@ namespace EGFramework{ @@ -18,10 +18,9 @@ namespace EGFramework{
}
public IArchitecture GetArchitecture()
{
throw new System.NotImplementedException();
return EGArchitectureImplement.Interface;
}
}
public static class GodotPathExtension{

50
addons/EGFramework/Module/SaveTools/Data/EGDapper.cs

@ -78,19 +78,57 @@ namespace EGFramework @@ -78,19 +78,57 @@ namespace EGFramework
// throw new System.NotImplementedException();
Type DataType = typeof(TData);
var properties = DataType.GetProperties();
var fields = DataType.GetFields();
string keySet = "";
string keySetParam = "";
foreach (PropertyInfo key in properties)
{
keySet += key.Name + ",";
keySetParam += "@" + key.Name + ",";
if (key.Name == "ID" || key.Name == "Id" || key.Name == "id")
{
continue;
}
if (DataType.IsPrimitive)
{
keySet += key.Name + ",";
keySetParam += "@" + key.Name + ",";
}
else
{
keySet += key.Name + ",";
keySetParam += "'" + key.GetValue(data).ToString() + "',";
}
}
foreach (FieldInfo key in fields)
{
if (key.Name == "ID" || key.Name == "Id" || key.Name == "id")
{
continue;
}
if (DataType.IsPrimitive)
{
keySet += key.Name + ",";
keySetParam += "@" + key.Name + ",";
}
else
{
keySet += key.Name + ",";
keySetParam += "'" + key.GetValue(data).ToString() + "',";
}
}
keySet = keySet.TrimEnd(',');
keySetParam = keySetParam.TrimEnd(',');
int count = Connection.Execute(@"insert " + dataKey + "(" + keySet + ") values(" + keySetParam + ")", data);
//EG.Print("count:" + count);
}
/// <summary>
/// TData Must be all member to type of properties. such as 'public string Name { set; get; }'. Properties cannot be except string, primitive
/// </summary>
/// <param name="dataKey"></param>
/// <param name="data"></param>
/// <typeparam name="TData"></typeparam>
public void AddData<TData>(string dataKey, IEnumerable<TData> data)
{
Type DataType = typeof(TData);
@ -99,12 +137,18 @@ namespace EGFramework @@ -99,12 +137,18 @@ namespace EGFramework
string keySetParam = "";
foreach (PropertyInfo key in properties)
{
if (key.Name == "ID" || key.Name == "Id" || key.Name == "id")
{
continue;
}
keySet += key.Name + ",";
keySetParam += "@" + key.Name + ",";
}
keySet = keySet.TrimEnd(',');
keySetParam = keySetParam.TrimEnd(',');
string sql = @"insert " + dataKey + "(" + keySet + ") values(" + keySetParam + ")";
EG.Print("sql:" + sql);
int count = Connection.Execute(sql, data);
//EG.Print("count:" + count);
}

47
addons/EGFramework/Module/SaveTools/Object/EGByteSave.cs

@ -17,20 +17,21 @@ namespace EGFramework @@ -17,20 +17,21 @@ namespace EGFramework
void SetBytes(byte[] byteData);
}
[Obsolete("This class is not comlpete, please not use it!")]
public class EGByteObjectSave : IEGSave,IEGSaveObject
public class EGByteObjectSave : IEGSave, IEGSaveObject
{
public Encoding StringEncoding { set; get; } = Encoding.ASCII;
private string DefaultPath { set; get; }
private uint PointerLength { get; set; }
private uint[] Pointer { get; set; }
private Dictionary<uint,byte[]> Data { get; set; }
private Dictionary<uint, byte[]> Data { get; set; }
private byte[] _Data;
public void ReadDataBlock(string path){
public void ReadDataBlock(string path)
{
DefaultPath = path;
try
{
FileStream fileStream = new FileStream(path,FileMode.OpenOrCreate);
FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate);
byte[] buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, (int)fileStream.Length);
fileStream.Close();
@ -43,11 +44,12 @@ namespace EGFramework @@ -43,11 +44,12 @@ namespace EGFramework
throw;
}
}
public void WriteDataBlock(string path){
public void WriteDataBlock(string path)
{
try
{
FileStream fileStream = File.Create(path);
fileStream.Write(_Data,0,_Data.Length);
fileStream.Write(_Data, 0, _Data.Length);
fileStream.Close();
fileStream.Dispose();
}
@ -69,26 +71,20 @@ namespace EGFramework @@ -69,26 +71,20 @@ namespace EGFramework
/// <param name="objectKey"></param>
/// <param name="obj"></param>
/// <typeparam name="TObject"></typeparam>
public void SetObject<TObject>(string objectKey , TObject obj)
public void SetObject<TObject>(string objectKey, TObject obj)
{
if(typeof(TObject).GetInterfaces().Contains(typeof(IEGByteObject))){
if (typeof(TObject).GetInterfaces().Contains(typeof(IEGByteObject)))
{
_Data = ((IEGByteObject)obj).GetBytes();
}else{
}
else
{
throw new Exception("This byte class cannot be serialized! you should implement IRequest first!");
}
WriteDataBlock(DefaultPath);
}
public TObject GetObject<TObject>(string objectKey) where TObject : new()
{
if(typeof(TObject).GetInterfaces().Contains(typeof(IEGByteObject))){
TObject result = new TObject();
((IEGByteObject)result).SetBytes(_Data);
return result;
}else{
throw new Exception("This byte class cannot be serialized! you should implement IRequest first!");
}
}
public void RemoveObject<TObject>(string objectKey)
{
@ -114,6 +110,19 @@ namespace EGFramework @@ -114,6 +110,19 @@ namespace EGFramework
{
throw new NotImplementedException();
}
public TObject GetObject<TObject>(string objectKey)
{
throw new NotImplementedException();
// if(typeof(TObject).GetInterfaces().Contains(typeof(IEGByteObject))){
// TObject result = new TObject();
// ((IEGByteObject)result).SetBytes(_Data);
// return result;
// }else{
// throw new Exception("This byte class cannot be serialized! you should implement IRequest first!");
// }
}
}
public interface IEGByteInit{

2
addons/EGFramework/Module/SaveTools/Object/EGJsonSave.cs

@ -71,7 +71,7 @@ namespace EGFramework @@ -71,7 +71,7 @@ namespace EGFramework
/// <summary>
/// Get data from file, if your data is not in file, then throw an exception.
/// </summary>
public TObject GetObject<TObject>(string objectKey) where TObject : new()
public TObject GetObject<TObject>(string objectKey)
{
if(!SaveObject.ContainsKey(objectKey)){
throw new Exception("Key not found!");

2
addons/EGFramework/Module/SaveTools/Object/EGRedisSave.cs

@ -61,7 +61,7 @@ namespace EGFramework{ @@ -61,7 +61,7 @@ namespace EGFramework{
Database.SetAdd(objectKey, JsonConvert.SerializeObject(obj));
}
public TObject GetObject<TObject>(string objectKey) where TObject : new()
public TObject GetObject<TObject>(string objectKey)
{
try
{

2
addons/EGFramework/Module/SaveTools/SaveToolsInterface.cs

@ -45,7 +45,7 @@ namespace EGFramework @@ -45,7 +45,7 @@ namespace EGFramework
#region Object
public interface IEGSaveObjectReadOnly
{
TObject GetObject<TObject>(string objectKey) where TObject : new();
TObject GetObject<TObject>(string objectKey);
IEnumerable<string> GetKeys();
bool ContainsKey(string objectKey);
}

1
project.godot

@ -20,6 +20,7 @@ config/icon="res://EGFramework.svg" @@ -20,6 +20,7 @@ config/icon="res://EGFramework.svg"
window/size/viewport_width=1600
window/size/viewport_height=900
window/subwindows/embed_subwindows=false
[dotnet]

Loading…
Cancel
Save