SimpleKeyValueStore.cs
using System.Collections.Concurrent; using System.Text.Json; namespace MiniRedis { public class SimpleKeyValueStore : IDisposable { private readonly ConcurrentDictionary<string, object> data; private readonly string filePath; private readonly object fileLock = new object(); private readonly JsonSerializerOptions jsonOptions; public SimpleKeyValueStore(string filePath = "data.json") { this.filePath = filePath; data = new ConcurrentDictionary<string, object>(); // 配置 JSON 序列化选项 jsonOptions = new JsonSerializerOptions { WriteIndented = true, PropertyNameCaseInsensitive = true, Converters = { new JsonElementConverter() } // 添加自定义转换器 }; // 从磁盘加载现有数据 LoadFromDisk(); } // 设置键值对 public void Set<T>(string key, T value) { data[key] = value; PersistToDisk(); // 立即持久化到磁盘 } // 获取值 public T Get<T>(string key) { if (data.TryGetValue(key, out object value)) { // 如果值是 JsonElement,需要转换为目标类型 if (value is JsonElement jsonElement) { return jsonElement.Deserialize<T>(jsonOptions); } return (T)value; } return default(T); } // 检查键是否存在 public bool ContainsKey(string key) { return data.ContainsKey(key); } // 删除键 public bool Remove(string key) { var result = data.TryRemove(key, out _); if (result) PersistToDisk(); // 如果删除成功,立即持久化到磁盘 return result; } // 获取所有键 public ICollection<string> Keys() { return data.Keys; } // 从磁盘加载数据 private void LoadFromDisk() { if (!File.Exists(filePath)) return; try { lock (fileLock) { var json = File.ReadAllText(filePath); var deserialized = JsonSerializer.Deserialize<ConcurrentDictionary<string, object>>(json, jsonOptions); if (deserialized != null) { foreach (var kvp in deserialized) { data[kvp.Key] = kvp.Value; } } } } catch (Exception ex) { Console.WriteLine($"Error loading data from disk: {ex.Message}"); } } // 持久化到磁盘 private void PersistToDisk() { try { lock (fileLock) { var json = JsonSerializer.Serialize(data, jsonOptions); // 先写入临时文件,然后替换原文件,确保数据一致性 var tempPath = filePath + ".tmp"; File.WriteAllText(tempPath, json); // 替换文件 if (File.Exists(filePath)) File.Replace(tempPath, filePath, null); else File.Move(tempPath, filePath); } } catch (Exception ex) { Console.WriteLine($"Error persisting data to disk: {ex.Message}"); } } // 清理资源 public void Dispose() { // 确保所有更改都已保存 PersistToDisk(); } } // 自定义 JSON 转换器,处理 JsonElement 到具体类型的转换 public class JsonElementConverter : System.Text.Json.Serialization.JsonConverter<object> { public override object Read( ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using (JsonDocument document = JsonDocument.ParseValue(ref reader)) { return ConvertJsonElement(document.RootElement); } } private object ConvertJsonElement(JsonElement element) { switch (element.ValueKind) { case JsonValueKind.String: return element.GetString(); case JsonValueKind.Number: if (element.TryGetInt32(out int intValue)) return intValue; if (element.TryGetInt64(out long longValue)) return longValue; return element.GetDouble(); case JsonValueKind.True: return true; case JsonValueKind.False: return false; case JsonValueKind.Array: var array = new object[element.GetArrayLength()]; int index = 0; foreach (JsonElement arrayElement in element.EnumerateArray()) { array[index++] = ConvertJsonElement(arrayElement); } return array; case JsonValueKind.Object: var dict = new System.Collections.Generic.Dictionary<string, object>(); foreach (var property in element.EnumerateObject()) { dict[property.Name] = ConvertJsonElement(property.Value); } return dict; default: return null; } } public override void Write( Utf8JsonWriter writer, object value, JsonSerializerOptions options) { JsonSerializer.Serialize(writer, value, value.GetType(), options); } } }
Program.cs
namespace MiniRedis { class Program { static void Main(string[] args) { // 创建存储实例 using var store = new SimpleKeyValueStore("mydata.json"); Console.WriteLine($"Name:{store.Get<string>("name")}"); // 存储数据 store.Set("name", "John Doe"); store.Set("age", 30); store.Set("scores", new[] { 90, 85, 95 }); // 检索数据 var name = store.Get<string>("name"); var age = store.Get<int>("age"); var scores = store.Get<int[]>("scores"); Console.WriteLine($"Name: {name}"); Console.WriteLine($"Age: {age}"); Console.WriteLine($"Scores: {string.Join(", ", scores)}"); // 检查键是否存在 if (store.ContainsKey("name")) Console.WriteLine("Key 'name' exists"); // 删除键 store.Remove("age"); // 获取所有键 var keys = store.Keys(); Console.WriteLine($"All keys: {string.Join(", ", keys)}"); } } }