Add object store & json data manager/container

This commit is contained in:
Pilzinsel64
2025-07-29 07:05:13 +02:00
parent 05e5427144
commit 8acd7c8925
7 changed files with 231 additions and 1 deletions

View File

@@ -0,0 +1,33 @@
using Newtonsoft.Json;
namespace Pilz.Data.Json;
public abstract class JsonDataContainer
{
[JsonProperty("Sets")]
protected readonly HashSet<object> sets = [];
public virtual HashSet<T>? Set<T>(bool allowCreate) where T : class, IDataObject
{
var list = sets.OfType<HashSet<T>>().FirstOrDefault();
if (list == null && allowCreate)
{
list = [];
sets.Add(list);
}
return list;
}
protected virtual JsonSerializer GetSerializer()
{
var serializer = JsonSerializer.CreateDefault();
serializer.TypeNameHandling = TypeNameHandling.Auto;
return serializer;
}
public abstract void Read();
public abstract void Flush();
}

View File

@@ -0,0 +1,39 @@
namespace Pilz.Data.Json;
public class JsonDataManager(JsonDataContainer container) : DataManager
{
public bool AutoFlush { get; set; }
protected override T? FindEntity<T>(int id) where T : class
{
return container.Set<T>(false)?.FirstOrDefault(n => n.Id.Equals(id));
}
protected override IQueryable<T> GetEntitySet<T>()
{
return container.Set<T>(false).AsQueryable();
}
protected override void RemoveEntity<T>(T obj)
{
container.Set<T>(false)?.Remove(obj);
}
protected override void UpdateEntity<T>(T obj)
{
var set = container.Set<T>(true);
if (!set.Contains(obj))
set.Add(obj);
}
protected override void SaveChanges()
{
if (AutoFlush)
Flush();
}
public virtual void Flush()
{
container.Flush();
}
}

View File

@@ -0,0 +1,18 @@
using System.IO;
namespace Pilz.Data.Json;
public class JsonFileContainer(string filePath) : JsonDataContainer
{
public override void Read()
{
using var sw = new StreamReader(filePath);
GetSerializer().Populate(sw, this);
}
public override void Flush()
{
using var sw = new StreamWriter(filePath, false);
GetSerializer().Serialize(sw, this);
}
}

View File

@@ -0,0 +1,19 @@
namespace Pilz.Data.Json;
public class JsonStreamContainer(Stream stream) : JsonDataContainer
{
public override void Read()
{
using var sw = new StreamReader(stream);
stream.Position = 0;
GetSerializer().Populate(sw, this);
}
public override void Flush()
{
using var sw = new StreamWriter(stream);
stream.Position = 0;
GetSerializer().Serialize(sw, this);
stream.SetLength(stream.Position);
}
}

View File

@@ -0,0 +1,14 @@
namespace Pilz.Data.Json;
public class JsonVoidContainer : JsonDataContainer
{
public override void Read()
{
// Nothing todo here.
}
public override void Flush()
{
// Nothing todo here.
}
}

107
Pilz/Data/ObjectStore.cs Normal file
View File

@@ -0,0 +1,107 @@
using Newtonsoft.Json;
namespace Pilz.Data;
/// <summary>
/// An object store using keys to identifiy the objects. Can be used for caching.
/// </summary>
public class ObjectStore
{
[JsonProperty("Objects")]
private readonly Dictionary<string, object> objects = [];
/// <summary>
/// Gets an object by the given ID and type identifier. It will be created if it doesn't exist yet.
/// </summary>
/// <typeparam name="T">The type identifier of the object to return or create.</typeparam>
/// <param name="key">The key to identify the object.</param>
/// <param name="allowCreate">Allow creation of the object if it doesn't exist yet.</param>
/// <returns></returns>
public virtual T Get<T>(string key, bool allowCreate)
{
if (!objects.TryGetValue(key, out var cache))
{
cache = Activator.CreateInstance<T>();
if (cache != null)
objects.Add(key, cache);
}
if (cache is not T cacheT)
throw new NullReferenceException("Cache could not be initialized.");
return cacheT;
}
/// <summary>
/// Gets an object by the given ID and type identifier.
/// </summary>
/// <typeparam name="T">The type identifier of the object to return.</typeparam>
/// <param name="key">The key to identify the object.</param>
/// <returns></returns>
public virtual T Get<T>(string key)
{
return Get<T>(key, false);
}
/// <summary>
/// Gets an object by the type identifier.
/// </summary>
/// <remarks>
/// This method can be potentially unsafe if the same type is available multiple times in the store. If unsure, use the key identifier to identify the object as a safer way.
/// </remarks>
/// <typeparam name="T">The type identifier of the object to return.</typeparam>
/// <returns></returns>
public virtual T Get<T>()
{
return objects.Values.OfType<T>().FirstOrDefault();
}
/// <summary>
/// Gets an object by the given ID and type identifier. It will be created if it doesn't exist yet.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key">The key to identify the object.</param>
/// <returns></returns>
public virtual object? Get(string key)
{
if (!objects.TryGetValue(key, out var cache))
cache = null;
return cache;
}
/// <summary>
/// Removes an object by its key.
/// </summary>
/// <param name="key">The key to identify the object.</param>
public virtual void Remove(string key)
{
objects.Remove(key);
}
/// <summary>
/// Removes an object from the store by its key.
/// </summary>
/// <param name="value">The object to remove.</param>
public virtual void Remove(object value)
{
var kvp = objects.FirstOrDefault(kvp => kvp.Value == value);
if (kvp.Key != null)
objects.Remove(kvp.Key);
}
/// <summary>
/// Removes an object from the store by its key.
/// </summary>
/// <remarks>
/// This method can be potentially unsafe if the same type is available multiple times in the store. If unsure, use the key identifier to identify the object as a safer way.
/// </remarks>
/// <param name="value">The object to remove.</param>
public virtual void Remove<T>(T value)
{
var kvp = objects.FirstOrDefault(kvp => kvp.Value is T valueT && valueT.Equals(value));
if (kvp.Key != null)
objects.Remove(kvp.Key);
}
}

View File

@@ -5,7 +5,7 @@
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>annotations</Nullable>
<Version>2.3.6</Version>
<Version>2.4.0</Version>
</PropertyGroup>
<ItemGroup>