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>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>annotations</Nullable>
|
||||
<Version>2.3.6</Version>
|
||||
<Version>2.4.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user