cool
This commit is contained in:
@@ -1,12 +1,47 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using LiteDB;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Net.BITKit.Database
|
||||
{
|
||||
public class LiteDbDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDisposable where TKey : notnull
|
||||
{public static class LiteDbHelper
|
||||
{
|
||||
public static string GetReadableCollectionName<T>()
|
||||
{
|
||||
var type = typeof(T);
|
||||
return SanitizeTypeName(type);
|
||||
}
|
||||
|
||||
private static string SanitizeTypeName(Type type)
|
||||
{
|
||||
// 基础类型名
|
||||
string name = type.Name;
|
||||
|
||||
// 若为泛型,如 Dictionary<string, int> 变为 Dictionary_String_Int
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
name = type.Name.Substring(0, type.Name.IndexOf('`')) + "_" +
|
||||
string.Join("_", type.GetGenericArguments().Select(SanitizeTypeName));
|
||||
}
|
||||
|
||||
// 替换非法字符,保留 a-zA-Z0-9_$
|
||||
name = Regex.Replace(name, @"[^a-zA-Z0-9_$]", "_");
|
||||
|
||||
// 开头不能是数字
|
||||
if (!Regex.IsMatch(name, @"^[a-zA-Z$_]"))
|
||||
{
|
||||
name = "_" + name;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
public class LiteDbDictionary<TKey, TValue> : IDictionary<TKey, TValue>,IReadOnlyDictionary<TKey,TValue>, IDisposable where TKey : notnull
|
||||
{
|
||||
// 内部的 LiteDB 数据库实例
|
||||
private readonly LiteDatabase _db;
|
||||
@@ -15,18 +50,58 @@ namespace Net.BITKit.Database
|
||||
private readonly ILiteCollection<KeyValueItem> _collection;
|
||||
|
||||
// 内部使用的键值项(POCO类)
|
||||
private class KeyValueItem
|
||||
private record KeyValueItem
|
||||
{
|
||||
// LiteDB 将此字段作为文档的 _id(主键)
|
||||
[BsonId] public TKey Key { get; set; }
|
||||
public TValue Value { get; set; }
|
||||
}
|
||||
|
||||
public LiteDbDictionary()
|
||||
public LiteDbDictionary(ILogger<LiteDbDictionary<TKey,TValue>> logger=null)
|
||||
{
|
||||
/*
|
||||
_db = new LiteDatabase(":memory:");
|
||||
_collection = _db.GetCollection<KeyValueItem>(typeof(TValue).Name);
|
||||
_collection.EnsureIndex(x => x.Key);
|
||||
*/
|
||||
|
||||
|
||||
// 获取程序集名作为默认数据库名
|
||||
var asmName = Assembly.GetEntryAssembly()?.GetName().Name
|
||||
?? Assembly.GetExecutingAssembly().GetName().Name
|
||||
?? "LiteDb";
|
||||
|
||||
// 优先使用环境变量控制根目录
|
||||
var rootDir = Environment.GetEnvironmentVariable("DATA_DIR");
|
||||
|
||||
// 默认持久化目录(跨平台)
|
||||
|
||||
if (string.IsNullOrWhiteSpace(rootDir))
|
||||
{
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
rootDir = Path.Combine(UnityEngine.Application.persistentDataPath, asmName);
|
||||
#else
|
||||
if (OperatingSystem.IsWindows())
|
||||
rootDir =
|
||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), asmName);
|
||||
else
|
||||
rootDir =
|
||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), asmName);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
Directory.CreateDirectory(rootDir); // 确保目录存在
|
||||
|
||||
var dbFilePath = Path.Combine(rootDir, $"{asmName}.db");
|
||||
var connectionString = $"Filename={dbFilePath};Connection=shared";
|
||||
|
||||
logger?.LogInformation($"LiteDbDictionary<{typeof(TKey).Name},{typeof(TValue).Name}> 数据库文件: {dbFilePath}");
|
||||
|
||||
_db = new LiteDatabase(connectionString);
|
||||
_collection = _db.GetCollection<KeyValueItem>($"{LiteDbHelper.GetReadableCollectionName<TKey>()}_{LiteDbHelper.GetReadableCollectionName<TValue>()}");
|
||||
_collection.EnsureIndex(x => x.Key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -62,6 +137,10 @@ namespace Net.BITKit.Database
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => Keys;
|
||||
|
||||
IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values;
|
||||
|
||||
public ICollection<TKey> Keys => _collection.FindAll().Select(x => x.Key).ToList();
|
||||
public ICollection<TValue> Values => _collection.FindAll().Select(x => x.Value).ToList();
|
||||
public int Count => _collection.Count();
|
||||
@@ -76,7 +155,8 @@ namespace Net.BITKit.Database
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return _collection.Exists(x => x.Key.Equals(key));
|
||||
var bsonKey = _db.Mapper.Serialize(typeof(TKey), key);
|
||||
return _collection.FindById(bsonKey) != null; // ✅ 更安全
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
|
Reference in New Issue
Block a user