Add object store & json data manager/container
This commit is contained in:
33
Pilz/Data/Json/JsonDataContainer.cs
Normal file
33
Pilz/Data/Json/JsonDataContainer.cs
Normal 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();
|
||||||
|
}
|
||||||
39
Pilz/Data/Json/JsonDataManager.cs
Normal file
39
Pilz/Data/Json/JsonDataManager.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Pilz/Data/Json/JsonFileContainer.cs
Normal file
18
Pilz/Data/Json/JsonFileContainer.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
Pilz/Data/Json/JsonStreamContainer.cs
Normal file
19
Pilz/Data/Json/JsonStreamContainer.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Pilz/Data/Json/JsonVoidContainer.cs
Normal file
14
Pilz/Data/Json/JsonVoidContainer.cs
Normal 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
107
Pilz/Data/ObjectStore.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>annotations</Nullable>
|
<Nullable>annotations</Nullable>
|
||||||
<Version>2.3.6</Version>
|
<Version>2.4.0</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user