Improve data handling #25 #27

Merged
SimonG96 merged 47 commits from ImproveDataHandling_#25 into master 5 years ago
  1. 4
      .idea/.idea.GBase/.idea/encodings.xml
  2. 1
      GBase.sln.DotSettings
  3. 5
      GBase/Attributes/GBaseTableAttribute.cs
  4. 8
      GBase/DataHandling/Cache/XmlDataHandlerCache.cs
  5. 17
      GBase/DataHandling/Exceptions/InvalidXmlFileException.cs
  6. 13
      GBase/DataHandling/Factories/IDataHandlerFactory.cs
  7. 3
      GBase/DataHandling/Factories/IXmlDataReaderFactory.cs
  8. 4
      GBase/DataHandling/Factories/IXmlDataWriterFactory.cs
  9. 13
      GBase/DataHandling/Factories/Pool/IPoolItemFactory.cs
  10. 13
      GBase/DataHandling/Factories/Pool/IPoolRequestFactory.cs
  11. 14
      GBase/DataHandling/Factories/Pool/PoolItemFactory.cs
  12. 101
      GBase/DataHandling/Pool/DataHandlerPool.cs
  13. 19
      GBase/DataHandling/Pool/PoolItem.cs
  14. 18
      GBase/DataHandling/Pool/PoolRequest.cs
  15. 81
      GBase/DataHandling/XmlDataHandler.cs
  16. 65
      GBase/DataHandling/XmlDataReader.cs
  17. 126
      GBase/DataHandling/XmlDataWriter.cs
  18. 27
      GBase/Exceptions/InvalidTableTypeException.cs
  19. 23
      GBase/Exceptions/MissingTableException.cs
  20. 45
      GBase/Factories/GBaseTableFactory.cs
  21. 2
      GBase/Factories/IGBaseColumnFactory.cs
  22. 3
      GBase/Factories/IGBaseTableFactory.cs
  23. 17
      GBase/FileHandling/Exceptions/FileNotExistingException.cs
  24. 112
      GBase/FileHandling/FileHandler.cs
  25. 32
      GBase/FileHandling/GBaseFile.cs
  26. 59
      GBase/GBase.cs
  27. 409
      GBase/GBase.xml
  28. 6
      GBase/GBaseColumn.cs
  29. 47
      GBase/GBaseObject.cs
  30. 86
      GBase/GBaseTable.cs
  31. 17
      GBase/Installers/DataHandlingInstaller.cs
  32. 3
      GBase/Installers/GBaseInstaller.cs
  33. 6
      GBase/Interfaces/DataHandling/Cache/IDataHandlerCache.cs
  34. 26
      GBase/Interfaces/DataHandling/IDataHandler.cs
  35. 14
      GBase/Interfaces/DataHandling/IDataReader.cs
  36. 28
      GBase/Interfaces/DataHandling/IDataWriter.cs
  37. 15
      GBase/Interfaces/DataHandling/Pool/IDataHandlerPool.cs
  38. 12
      GBase/Interfaces/DataHandling/Pool/IPoolItem.cs
  39. 14
      GBase/Interfaces/DataHandling/Pool/IPoolRequest.cs
  40. 39
      GBase/Interfaces/FileHandling/IFileHandler.cs
  41. 19
      GBase/Interfaces/FileHandling/IGBaseFile.cs
  42. 8
      GBase/Interfaces/IGBase.cs
  43. 2
      GBase/Interfaces/IGBaseColumn.cs
  44. 60
      GBase/Interfaces/IGBaseTable.cs
  45. 41
      GBaseStructure.md
  46. 26
      Test.GBase/DataHandling/XmlDataHandlerLocalIntegrationTest.cs
  47. 163
      Test.GBase/DataHandling/XmlDataHandlerTest.cs
  48. 56
      Test.GBase/GBaseIntegrationTest/GBaseIntegrationTest.cs
  49. 26
      Test.GBase/GBaseIntegrationTest/Group.cs
  50. 15
      Test.GBase/GBaseIntegrationTest/IGroup.cs
  51. 14
      Test.GBase/GBaseIntegrationTest/IItem.cs
  52. 34
      Test.GBase/GBaseIntegrationTest/Item.cs
  53. 54
      Test.GBase/GBaseIntegrationTest/Model.cs
  54. 15
      Test.GBase/GBaseIntegrationTest/Settings.cs
  55. 18
      Test.GBase/GBaseTableIntegrationTest.cs
  56. 2
      Test.GBase/TestClasses/Foo.cs

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

@ -2,5 +2,6 @@
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Author: $USER_NAME$&#xD; <s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Author: $USER_NAME$&#xD;
Created: $CREATED_YEAR$-$CREATED_MONTH$-$CREATED_DAY$&#xD; Created: $CREATED_YEAR$-$CREATED_MONTH$-$CREATED_DAY$&#xD;
Copyright(c) $CREATED_YEAR$ SimonG. All Rights Reserved.</s:String> Copyright(c) $CREATED_YEAR$ SimonG. All Rights Reserved.</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String></wpf:ResourceDictionary> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String></wpf:ResourceDictionary>

@ -13,6 +13,11 @@ namespace GBase.Attributes
[AttributeUsage(AttributeTargets.Class)] [AttributeUsage(AttributeTargets.Class)]
public class GBaseTableAttribute : Attribute //TODO: Decide how to handle enums (as table or their own type) public class GBaseTableAttribute : Attribute //TODO: Decide how to handle enums (as table or their own type)
{ {
public GBaseTableAttribute(string folderName)
{
FolderName = folderName;
}
public string FolderName { get; }
} }
} }

@ -4,7 +4,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.DataHandling.Cache.Factories; using GBase.DataHandling.Cache.Factories;
using GBase.Interfaces.DataHandling.Cache; using GBase.Interfaces.DataHandling.Cache;
@ -103,9 +105,11 @@ namespace GBase.DataHandling.Cache
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="cancellationToken"></param>
/// <returns>An <see cref="IEnumerable{T}"/> with all the values for the property</returns> /// <returns>An <see cref="IEnumerable{T}"/> with all the values for the property</returns>
public async Task<IEnumerable<TProperty>> TryGetValues<T, TProperty>(string propertyName) public async Task<IEnumerable<TProperty>> TryGetValues<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken)
{ {
IXmlDataHandlerCacheEntry entry = _cache.FirstOrDefault(e => e.Type == typeof(T)); IXmlDataHandlerCacheEntry entry = _cache.FirstOrDefault(e => e.Type == typeof(T));
IDataHandlerCachePropertyEntry property = entry?.Properties.FirstOrDefault(p => p.PropertyName.Equals(propertyName)); IDataHandlerCachePropertyEntry property = entry?.Properties.FirstOrDefault(p => p.PropertyName.Equals(propertyName));
@ -114,7 +118,7 @@ namespace GBase.DataHandling.Cache
if (!property.IsInitialized) //initialize property by reading the values from the xml if (!property.IsInitialized) //initialize property by reading the values from the xml
{ {
List<TProperty> values = (await _xmlDataReader.Read<T, TProperty>(propertyName))?.ToList(); List<TProperty> values = (await _xmlDataReader.Read<T, TProperty>(file, propertyName, cancellationToken))?.ToList();
if (values != null) if (values != null)
{ {
foreach (TProperty value in values.Where(value => !property.Values.Any(v => v.Equals(value)))) foreach (TProperty value in values.Where(value => !property.Values.Any(v => v.Equals(value))))

@ -0,0 +1,17 @@
// Author: Gockner, Simon
// Created: 2020-11-09
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
namespace GBase.DataHandling.Exceptions
{
public class InvalidXmlFileException : Exception
{
public InvalidXmlFileException(string message)
: base(message)
{
}
}
}

@ -0,0 +1,13 @@
// Author: Simon Gockner
// Created: 2020-09-19
// Copyright(c) 2020 SimonG. All Rights Reserved.
using GBase.Interfaces.DataHandling;
namespace GBase.DataHandling.Factories
{
public interface IDataHandlerFactory
{
IDataHandler Create();
}
}

@ -14,8 +14,7 @@ namespace GBase.DataHandling.Factories
/// <summary> /// <summary>
/// Creates an <see cref="IXmlDataReader"/> /// Creates an <see cref="IXmlDataReader"/>
/// </summary> /// </summary>
/// <param name="path">The path to the xml file</param>
/// <returns>A newly created instance of the implementation for <see cref="IXmlDataReader"/></returns> /// <returns>A newly created instance of the implementation for <see cref="IXmlDataReader"/></returns>
IXmlDataReader Create(string path); IXmlDataReader Create();
} }
} }

@ -14,9 +14,7 @@ namespace GBase.DataHandling.Factories
/// <summary> /// <summary>
/// Creates an <see cref="IXmlDataWriter"/> /// Creates an <see cref="IXmlDataWriter"/>
/// </summary> /// </summary>
/// <param name="path">The path to the xml file</param>
/// <param name="rootElementName">The root element name of the xml file</param>
/// <returns>A newly created instance of the implementation for <see cref="IXmlDataWriter"/></returns> /// <returns>A newly created instance of the implementation for <see cref="IXmlDataWriter"/></returns>
IXmlDataWriter Create(string path, string rootElementName); IXmlDataWriter Create();
} }
} }

@ -0,0 +1,13 @@
// Author: Simon Gockner
// Created: 2020-09-19
// Copyright(c) 2020 SimonG. All Rights Reserved.
using GBase.Interfaces.DataHandling.Pool;
namespace GBase.DataHandling.Factories.Pool
{
public interface IPoolItemFactory
{
IPoolItem<T> Create<T>(T item);
}
}

@ -0,0 +1,13 @@
// Author: Simon Gockner
// Created: 2020-09-19
// Copyright(c) 2020 SimonG. All Rights Reserved.
using GBase.Interfaces.DataHandling.Pool;
namespace GBase.DataHandling.Factories.Pool
{
public interface IPoolRequestFactory
{
IPoolRequest Create(object requester);
}
}

@ -0,0 +1,14 @@
// Author: Simon Gockner
// Created: 2020-09-19
// Copyright(c) 2020 SimonG. All Rights Reserved.
using GBase.DataHandling.Pool;
using GBase.Interfaces.DataHandling.Pool;
namespace GBase.DataHandling.Factories.Pool
{
public class PoolItemFactory : IPoolItemFactory
{
public IPoolItem<T> Create<T>(T item) => new PoolItem<T>(item);
}
}

@ -0,0 +1,101 @@
// Author: Simon Gockner
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using GBase.DataHandling.Factories;
using GBase.DataHandling.Factories.Pool;
using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Pool;
namespace GBase.DataHandling.Pool
{
public class DataHandlerPool : IDataHandlerPool
{
private readonly int _availableDataHandlers;
private readonly IPoolItemFactory _poolItemFactory;
private readonly IPoolRequestFactory _poolRequestFactory;
private readonly IDataHandlerFactory _dataHandlerFactory;
private readonly List<IPoolItem<IDataHandler>> _pool;
private readonly List<IPoolRequest> _waitingRequesters;
public DataHandlerPool(int availableDataHandlers,
IPoolItemFactory poolItemFactory,
IPoolRequestFactory poolRequestFactory,
IDataHandlerFactory dataHandlerFactory)
{
_availableDataHandlers = availableDataHandlers;
_poolItemFactory = poolItemFactory;
_poolRequestFactory = poolRequestFactory;
_dataHandlerFactory = dataHandlerFactory;
_pool = new List<IPoolItem<IDataHandler>>();
_waitingRequesters = new List<IPoolRequest>();
}
public async Task<IDataHandler> RequestDataHandler(object requester, bool overwrite, CancellationToken cancellationToken)
{
if (_pool.All(i => i.InUse) && _pool.Count == _availableDataHandlers) //no free dataHandlers available
return await WaitForDataHandler(requester, cancellationToken);
else if (_pool.All(i => i.InUse)) //every existing dataHandler is used -> create a new one
return CreateDataHandler(overwrite);
else //there are unused dataHandlers existing
return GetDataHandler();
}
private async Task<IDataHandler> WaitForDataHandler(object requester, CancellationToken cancellationToken)
{
IDataHandler dataHandler = null;
IPoolRequest request = _poolRequestFactory.Create(requester);
while (dataHandler == null)
{
if (_waitingRequesters.Contains(request) && _waitingRequesters.IndexOf(request) == 0) //request is in list and is first
{
if (_pool.Any(i => !i.InUse))
dataHandler = GetDataHandler();
else
await Task.Delay(1000, cancellationToken);
}
else if (_waitingRequesters.Contains(request)) //request is in list but not first
await Task.Delay(1000, cancellationToken);
else
_waitingRequesters.Add(request);
}
_waitingRequesters.Remove(request);
return dataHandler;
}
private IDataHandler CreateDataHandler(bool overwrite)
{
IPoolItem<IDataHandler> item = _poolItemFactory.Create(_dataHandlerFactory.Create());
item.Item.Init(overwrite);
_pool.Add(item);
item.InUse = true;
return item.Item;
}
private IDataHandler GetDataHandler()
{
IPoolItem<IDataHandler> item = _pool.First(i => !i.InUse);
item.InUse = true;
return item.Item;
}
public async ValueTask DisposeAsync()
{
while (_waitingRequesters.Any())
{
await Task.Delay(1000);
}
}
}
}

@ -0,0 +1,19 @@
// Author: Simon Gockner
// Created: 2020-09-19
// Copyright(c) 2020 SimonG. All Rights Reserved.
using GBase.Interfaces.DataHandling.Pool;
namespace GBase.DataHandling.Pool
{
public class PoolItem<T> : IPoolItem<T>
{
public PoolItem(T item)
{
Item = item;
}
public T Item { get; }
public bool InUse { get; set; }
}
}

@ -0,0 +1,18 @@
// Author: Simon Gockner
// Created: 2020-09-19
// Copyright(c) 2020 SimonG. All Rights Reserved.
using GBase.Interfaces.DataHandling.Pool;
namespace GBase.DataHandling.Pool
{
public class PoolRequest : IPoolRequest
{
public PoolRequest(object requester)
{
Requester = requester;
}
public object Requester { get; }
}
}

@ -5,12 +5,15 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.DataHandling.Cache.Factories; using GBase.DataHandling.Cache.Factories;
using GBase.DataHandling.Factories; using GBase.DataHandling.Factories;
using GBase.Helpers; using GBase.Helpers;
using GBase.Interfaces;
using GBase.Interfaces.DataHandling; using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Xml; using GBase.Interfaces.DataHandling.Xml;
using GBase.Interfaces.DataHandling.Xml.Cache; using GBase.Interfaces.DataHandling.Xml.Cache;
@ -46,18 +49,15 @@ namespace GBase.DataHandling
/// A <see cref="IDataHandler"/> that handles its data in an xml file /// A <see cref="IDataHandler"/> that handles its data in an xml file
/// </summary> /// </summary>
/// <param name="path">The path to the xml file</param> /// <param name="path">The path to the xml file</param>
/// <param name="rootElementName">The root element name of the xml file</param>
/// <param name="xmlDataReaderFactory">The <see cref="IXmlDataReader"/> factory</param> /// <param name="xmlDataReaderFactory">The <see cref="IXmlDataReader"/> factory</param>
/// <param name="xmlDataWriterFactory">The <see cref="IXmlDataWriter"/> factory</param> /// <param name="xmlDataWriterFactory">The <see cref="IXmlDataWriter"/> factory</param>
/// <param name="xmlDataHandlerCacheFactory">The <see cref="IXmlDataHandlerCache"/> factory</param> /// <param name="xmlDataHandlerCacheFactory">The <see cref="IXmlDataHandlerCache"/> factory</param>
public XmlDataHandler(string path, public XmlDataHandler(IXmlDataReaderFactory xmlDataReaderFactory,
string rootElementName,
IXmlDataReaderFactory xmlDataReaderFactory,
IXmlDataWriterFactory xmlDataWriterFactory, IXmlDataWriterFactory xmlDataWriterFactory,
IXmlDataHandlerCacheFactory xmlDataHandlerCacheFactory) IXmlDataHandlerCacheFactory xmlDataHandlerCacheFactory)
{ {
_xmlDataWriter = xmlDataWriterFactory.Create(path, rootElementName); _xmlDataWriter = xmlDataWriterFactory.Create();
_xmlDataReader = xmlDataReaderFactory.Create(path); _xmlDataReader = xmlDataReaderFactory.Create();
_cache = xmlDataHandlerCacheFactory.Create(_xmlDataReader); _cache = xmlDataHandlerCacheFactory.Create(_xmlDataReader);
} }
@ -66,35 +66,58 @@ namespace GBase.DataHandling
/// Initialize the <see cref="XmlDataHandler"/> /// Initialize the <see cref="XmlDataHandler"/>
/// </summary> /// </summary>
/// <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param> /// <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param>
/// <returns>Returns true if successful, false if not</returns> /// <returns>Returns true if successful, false if not</returns>
public async Task<bool> Init(bool overwrite, CancellationToken cancellationToken) public bool Init(bool overwrite)
{ {
if (_isInitialized) if (_isInitialized)
return false; return false;
_overwrite = overwrite; _overwrite = overwrite;
if (!await _xmlDataWriter.Init(cancellationToken)) _isInitialized = true;
return false; return true;
}
if (!await _xmlDataReader.Init(cancellationToken)) public async Task<bool> AddEntry<T>(T entry, IGBaseTable table, FileStream entryFile, CancellationToken cancellationToken)
{
if (!await _xmlDataWriter.InitFile(entryFile, table.Type.Name, cancellationToken))
return false; return false;
_isInitialized = true; foreach (var column in table.Columns)
{
//TODO: Set value for each column
PropertyInfo property = entry.GetType().GetProperty(column.Name);
if (property == null)
continue; //TODO: What to do in this case? (Shouldn't really happen...)
string valueString;
if (property.PropertyType != typeof(string) && property.GetValue(entry) is IEnumerable enumerable)
valueString = enumerable.ToGBaseString();
else
valueString = property.GetValue(entry).ToString();
await _xmlDataWriter.Write<T>(entryFile, property.Name, valueString, property.PropertyType, _overwrite, cancellationToken);
}
return true; return true;
} }
public Task<bool> RemoveEntry<T>(T entry)
{
throw new NotImplementedException();
}
/// <summary> /// <summary>
/// Set the value for the given property /// Set the value for the given property
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="entryFile"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param> /// <param name="value">The value to set</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns> /// <returns>A <see cref="Task"/> to await</returns>
public async Task SetValue<T, TProperty>(string propertyName, TProperty value) public async Task SetValue<T, TProperty>(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken)
{ {
if (value == null) if (value == null)
return; return;
@ -106,7 +129,7 @@ namespace GBase.DataHandling
valueString = value.ToString(); valueString = value.ToString();
await _cache.SetValue<T, TProperty>(propertyName, value, _overwrite); await _cache.SetValue<T, TProperty>(propertyName, value, _overwrite);
await _xmlDataWriter.Write<T, TProperty>(propertyName, valueString, _overwrite); await _xmlDataWriter.Write<T, TProperty>(entryFile, propertyName, valueString, _overwrite, cancellationToken);
} }
/// <summary> /// <summary>
@ -114,10 +137,12 @@ namespace GBase.DataHandling
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="entryFile"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param> /// <param name="value">The value to set</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns> /// <returns>A <see cref="Task"/> to await</returns>
public async Task RemoveValue<T, TProperty>(string propertyName, TProperty value) public async Task RemoveValue<T, TProperty>(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken)
{ {
if (value == null) if (value == null)
return; return;
@ -129,7 +154,7 @@ namespace GBase.DataHandling
valueString = value.ToString(); valueString = value.ToString();
await _cache.TryRemoveValue<T, TProperty>(propertyName, value); await _cache.TryRemoveValue<T, TProperty>(propertyName, value);
await _xmlDataWriter.Remove<T, TProperty>(propertyName, valueString); await _xmlDataWriter.Remove<T, TProperty>(entryFile, propertyName, valueString, cancellationToken);
} }
/// <summary> /// <summary>
@ -137,11 +162,13 @@ namespace GBase.DataHandling
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="cancellationToken"></param>
/// <returns>The value for the given property</returns> /// <returns>The value for the given property</returns>
public async Task<TProperty> GetValue<T, TProperty>(string propertyName) public async Task<TProperty> GetValue<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken)
{ {
IEnumerable<TProperty> enumerable = await GetValues<T, TProperty>(propertyName); IEnumerable<TProperty> enumerable = await GetValues<T, TProperty>(file, propertyName, cancellationToken);
return enumerable == null ? default : enumerable.FirstOrDefault(); return enumerable == null ? default : enumerable.FirstOrDefault();
} }
@ -150,25 +177,17 @@ namespace GBase.DataHandling
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="cancellationToken"></param>
/// <returns>An <see cref="IEnumerable{T}"/> with all the values for the property</returns> /// <returns>An <see cref="IEnumerable{T}"/> with all the values for the property</returns>
public async Task<IEnumerable<TProperty>> GetValues<T, TProperty>(string propertyName) public async Task<IEnumerable<TProperty>> GetValues<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken)
{ {
IEnumerable<TProperty> cachedValues = await _cache.TryGetValues<T, TProperty>(propertyName); IEnumerable<TProperty> cachedValues = await _cache.TryGetValues<T, TProperty>(file, propertyName, cancellationToken);
if (cachedValues != null) if (cachedValues != null)
return cachedValues; return cachedValues;
return await _xmlDataReader.Read<T, TProperty>(propertyName); return await _xmlDataReader.Read<T, TProperty>(file, propertyName, cancellationToken);
}
/// <summary>
/// Dispose used resources asynchronously
/// </summary>
/// <returns>A <see cref="ValueTask"/> to await</returns>
public async ValueTask DisposeAsync()
{
await _xmlDataReader.DisposeAsync();
await _xmlDataWriter.DisposeAsync();
} }
} }
} }

@ -10,6 +10,7 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml.Linq; using System.Xml.Linq;
using GBase.DataHandling.Exceptions;
using GBase.Helpers; using GBase.Helpers;
using GBase.Interfaces.DataHandling; using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Xml; using GBase.Interfaces.DataHandling.Xml;
@ -21,65 +22,34 @@ namespace GBase.DataHandling
/// </summary> /// </summary>
public class XmlDataReader : IXmlDataReader public class XmlDataReader : IXmlDataReader
{ {
private readonly FileStream _file;
private XDocument _xmlDocument;
private XElement _rootElement;
private bool _isInitialized;
private CancellationToken _cancellationToken;
/// <summary>
/// A <see cref="IDataReader"/> that reads from a xml file
/// </summary>
/// <param name="path">The path to the xml file</param>
public XmlDataReader(string path)
{
_file = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
}
/// <summary>
/// Initialize the <see cref="XmlDataReader"/>
/// </summary>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param>
/// <returns>Returns true if successful, false if not</returns>
/// <exception cref="Exception">No root element found</exception>
public async Task<bool> Init(CancellationToken cancellationToken)
{
if (_isInitialized)
return false;
_cancellationToken = cancellationToken;
_xmlDocument = await XDocument.LoadAsync(_file, LoadOptions.None, _cancellationToken);
_rootElement = _xmlDocument.Root;
if (_rootElement == null)
throw new Exception("No root element found.");
_isInitialized = true;
return true;
}
/// <summary> /// <summary>
/// Read the data of a property /// Read the data of a property
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/></typeparam> /// <typeparam name="T">The <see cref="Type"/></typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="cancellationToken"></param>
/// <returns>The data of the given property, null if no data found</returns> /// <returns>The data of the given property, null if no data found</returns>
/// <exception cref="ArgumentNullException"><paramref name="propertyName"/></exception> /// <exception cref="ArgumentNullException"><paramref name="propertyName"/></exception>
/// <exception cref="InvalidOperationException">Invalid <see cref="Type"/> found for the read object</exception> /// <exception cref="InvalidOperationException">Invalid <see cref="Type"/> found for the read object</exception>
public async Task<IEnumerable<TProperty>> Read<T, TProperty>(string propertyName) public async Task<IEnumerable<TProperty>> Read<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken)
//TODO: Read currently doesn't work for newly added items -> probably because file was loaded before new items were added; is probably not a problem -> cache //TODO: Read currently doesn't work for newly added items -> probably because file was loaded before new items were added; is probably not a problem -> cache
{ {
string typeName = typeof(T).FullName; string typeName = typeof(T).FullName;
if (typeName == null) if (typeName == null)
throw new ArgumentNullException(nameof(typeName)); throw new ArgumentNullException(nameof(typeName));
XDocument xmlDocument = await XDocument.LoadAsync(file, LoadOptions.None, cancellationToken);
file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
return await Task.Run(() => return await Task.Run(() =>
{ {
XElement typeElement = _rootElement.Element(typeName); XElement rootElement = xmlDocument.Root;
XElement propertyElement = typeElement?.Element(propertyName); if (rootElement == null)
throw new InvalidXmlFileException("No root element is set.");
XElement propertyElement = rootElement.Element(propertyName);
XAttribute propertyTypeAttribute = propertyElement?.Attribute(XmlDataHandler.VALUE_TYPE_ATTRIBUTE_NAME); XAttribute propertyTypeAttribute = propertyElement?.Attribute(XmlDataHandler.VALUE_TYPE_ATTRIBUTE_NAME);
if (propertyTypeAttribute == null) if (propertyTypeAttribute == null)
return null; return null;
@ -98,16 +68,7 @@ namespace GBase.DataHandling
return values.Select(Enumerables.ConvertToGBaseEnumerable<TProperty>).ToList(); return values.Select(Enumerables.ConvertToGBaseEnumerable<TProperty>).ToList();
return values.Select(value => (TProperty)Convert.ChangeType(value, typeof(TProperty))).ToList(); return values.Select(value => (TProperty)Convert.ChangeType(value, typeof(TProperty))).ToList();
}, _cancellationToken); }, cancellationToken);
}
/// <summary>
/// Dispose used resources asynchronously
/// </summary>
/// <returns>A <see cref="ValueTask"/> to await</returns>
public async ValueTask DisposeAsync()
{
await _file.DisposeAsync();
} }
} }
} }

@ -8,6 +8,7 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml.Linq; using System.Xml.Linq;
using GBase.DataHandling.Exceptions;
using GBase.Interfaces.DataHandling; using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Xml; using GBase.Interfaces.DataHandling.Xml;
@ -18,81 +19,70 @@ namespace GBase.DataHandling
/// </summary> /// </summary>
public class XmlDataWriter : IXmlDataWriter public class XmlDataWriter : IXmlDataWriter
{ {
private readonly string _rootElementName;
private readonly FileStream _file;
private XDocument _xmlDocument;
private XElement _rootElement;
private bool _isInitialized;
private CancellationToken _cancellationToken;
/// <summary>
/// A <see cref="IDataWriter"/> that writes to an xml file
/// </summary>
/// <param name="path">The path to the xml file</param>
/// <param name="rootElementName">The root element name of the xml file</param>
public XmlDataWriter(string path, string rootElementName)
{
_rootElementName = rootElementName;
_file = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
}
/// <summary> /// <summary>
/// Initialize the <see cref="XmlDataWriter"/> /// Initialize the <see cref="XmlDataWriter"/>
/// </summary> /// </summary>
/// <param name="file"></param>
/// <param name="rootElementName"></param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param>
/// <returns>Returns true if successful, false if not</returns> /// <returns>Returns true if successful, false if not</returns>
/// <exception cref="Exception">No root element found</exception> /// <exception cref="Exception">No root element found</exception>
public async Task<bool> Init(CancellationToken cancellationToken) public async Task<bool> InitFile(FileStream file, string rootElementName, CancellationToken cancellationToken)
{
if (_isInitialized)
return false;
_cancellationToken = cancellationToken;
//if the xml file is empty, write the root element
if (_file.Length <= 3) //<= 3 because of BOM
{
_xmlDocument = new XDocument();
_xmlDocument.Add(new XElement(_rootElementName));
_file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
await _xmlDocument.SaveAsync(_file, SaveOptions.OmitDuplicateNamespaces, cancellationToken);
}
else
{ {
_xmlDocument = await XDocument.LoadAsync(_file, LoadOptions.None, _cancellationToken); //if the xml file isn't empty, return
} if (file.Length > 3) //> 3 because of BOM
return true; //TODO: Don't return bool?
_rootElement = _xmlDocument.Root;//?.Element(_rootElementName); XDocument xmlDocument = new XDocument();
if (_rootElement == null) xmlDocument.Add(new XElement(rootElementName));
throw new Exception("No root element found."); file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
await xmlDocument.SaveAsync(file, SaveOptions.OmitDuplicateNamespaces, cancellationToken);
_isInitialized = true;
return true; return true;
} }
/// <summary> /// <summary>
/// Write the data of a property /// Write the data of a property
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam> /// <typeparam name="T">The <see cref="Type"/></typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="value">The value of the property</param> /// <param name="value">The value of the property</param>
/// <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param> /// <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns>
public async Task Write<T, TProperty>(FileStream file, string propertyName, string value, bool overwrite, CancellationToken cancellationToken) =>
await Write<T>(file, propertyName, value, typeof(TProperty), overwrite, cancellationToken);
/// <summary>
/// Write the data of a property
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param>
/// <param name="value">The value of the property</param>
/// <param name="propertyType"></param>
/// <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns> /// <returns>A <see cref="Task"/> to await</returns>
/// <exception cref="ArgumentNullException"><paramref name="propertyName"/></exception> /// <exception cref="ArgumentNullException"><paramref name="propertyName"/></exception>
public async Task Write<T, TProperty>(string propertyName, string value, bool overwrite) /// <exception cref="InvalidXmlFileException">No root element is set</exception>
public async Task Write<T>(FileStream file, string propertyName, string value, Type propertyType, bool overwrite, CancellationToken cancellationToken)
{ {
string typeName = typeof(T).FullName; string typeName = typeof(T).FullName;
if (typeName == null) if (typeName == null)
throw new ArgumentNullException(nameof(typeName)); throw new ArgumentNullException(nameof(typeName));
_file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
XDocument xmlDocument = await XDocument.LoadAsync(file, LoadOptions.None, cancellationToken);
file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
XElement typeElement = _rootElement.Element(typeName); XElement rootElement = xmlDocument.Root;
if (typeElement != null) //type element already exists if (rootElement == null)
{ throw new InvalidXmlFileException("No root element is set.");
XElement propertyElement = typeElement.Element(propertyName);
XElement propertyElement = rootElement.Element(propertyName);
if (propertyElement != null) //property element already exists if (propertyElement != null) //property element already exists
{ {
XElement valueElement = propertyElement.Element(XmlDataHandler.VALUE_ELEMENT_NAME); XElement valueElement = propertyElement.Element(XmlDataHandler.VALUE_ELEMENT_NAME);
@ -112,21 +102,13 @@ namespace GBase.DataHandling
else //property element doesn't exist else //property element doesn't exist
{ {
propertyElement = new XElement(propertyName, new XElement(XmlDataHandler.VALUE_ELEMENT_NAME) { Value = value }); //create the new property element with the value element propertyElement = new XElement(propertyName, new XElement(XmlDataHandler.VALUE_ELEMENT_NAME) { Value = value }); //create the new property element with the value element
propertyElement.SetAttributeValue(XmlDataHandler.VALUE_TYPE_ATTRIBUTE_NAME, typeof(TProperty).FullName); //add the property type attribute propertyElement.SetAttributeValue(XmlDataHandler.VALUE_TYPE_ATTRIBUTE_NAME, propertyType.FullName); //add the property type attribute
typeElement.Add(propertyElement); //create new property element with the value element rootElement.Add(propertyElement); //create new property element with the value element
}
}
else //type element doesn't exist
{
XElement propertyElement = new XElement(propertyName, new XElement(XmlDataHandler.VALUE_ELEMENT_NAME) { Value = value }); //create the new property element with the value element
propertyElement.SetAttributeValue(XmlDataHandler.VALUE_TYPE_ATTRIBUTE_NAME, typeof(TProperty).FullName); //add the property type attribute
_rootElement.Add(new XElement(typeName, propertyElement)); //create a new type element with the new property element
} }
//TODO: check if whole file is overwritten (probably) -> performance issues for large files? //TODO: check if whole file is overwritten (probably) -> performance issues for large files?
await _xmlDocument.SaveAsync(_file, SaveOptions.OmitDuplicateNamespaces, _cancellationToken); //save the document with the added elements await xmlDocument.SaveAsync(file, SaveOptions.OmitDuplicateNamespaces, cancellationToken); //save the document with the added elements
} }
/// <summary> /// <summary>
@ -134,19 +116,27 @@ namespace GBase.DataHandling
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param> /// <param name="value">The value to set</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns> /// <returns>A <see cref="Task"/> to await</returns>
/// <exception cref="ArgumentNullException"><paramref name="propertyName"/></exception> /// <exception cref="ArgumentNullException"><paramref name="propertyName"/></exception>
public async Task Remove<T, TProperty>(string propertyName, string value) /// <exception cref="InvalidXmlFileException">No root element is set</exception>
public async Task Remove<T, TProperty>(FileStream file, string propertyName, string value, CancellationToken cancellationToken)
{ {
string typeName = typeof(T).FullName; string typeName = typeof(T).FullName;
if (typeName == null) if (typeName == null)
throw new ArgumentNullException(nameof(typeName)); throw new ArgumentNullException(nameof(typeName));
_file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it XDocument xmlDocument = await XDocument.LoadAsync(file, LoadOptions.None, cancellationToken);
file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
XElement typeElement = _rootElement.Element(typeName); XElement rootElement = xmlDocument.Root;
if (rootElement == null)
throw new InvalidXmlFileException("No root element is set.");
XElement typeElement = rootElement.Element(typeName);
XElement propertyElement = typeElement?.Element(propertyName); XElement propertyElement = typeElement?.Element(propertyName);
XElement valueElement = propertyElement?.Elements(XmlDataHandler.VALUE_ELEMENT_NAME).FirstOrDefault(e => e.Value.Equals(value)); XElement valueElement = propertyElement?.Elements(XmlDataHandler.VALUE_ELEMENT_NAME).FirstOrDefault(e => e.Value.Equals(value));
if (valueElement == null) if (valueElement == null)
@ -155,17 +145,7 @@ namespace GBase.DataHandling
valueElement.Remove(); valueElement.Remove();
//TODO: check if whole file is overwritten (probably) -> performance issues for large files? //TODO: check if whole file is overwritten (probably) -> performance issues for large files?
await _xmlDocument.SaveAsync(_file, SaveOptions.OmitDuplicateNamespaces, _cancellationToken); //save the document with the added elements await xmlDocument.SaveAsync(file, SaveOptions.OmitDuplicateNamespaces, cancellationToken); //save the document with the added elements
}
/// <summary>
/// Dispose used resources asynchronously
/// </summary>
/// <returns>A <see cref="ValueTask"/> to await</returns>
public async ValueTask DisposeAsync()
{
await _xmlDocument.SaveAsync(_file, SaveOptions.None, _cancellationToken);
await _file.DisposeAsync();
} }
} }
} }

@ -0,0 +1,27 @@
// Author: Simon Gockner
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using GBase.Api;
namespace GBase.Exceptions
{
/// <summary>
/// <see cref="Exception"/> that the passed table type doesn't implement <see cref="INotifyGBaseEntryChanged"/>"/>
/// </summary>
public class InvalidTableTypeException : Exception
{
/// <summary>
/// <see cref="Exception"/> that the passed table type doesn't implement <see cref="INotifyGBaseEntryChanged"/>"/>
/// </summary>
/// <param name="type">The table type</param>
public InvalidTableTypeException(Type type)
: base($"Table type ({type}) doesn't implement {nameof(INotifyGBaseEntryChanged)}.")
{
Type = type;
}
public Type Type { get; }
}
}

@ -0,0 +1,23 @@
// Author: Gockner, Simon
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
namespace GBase.Exceptions
{
/// <summary>
/// <see cref="Exception"/> that the table for the given <see cref="Type"/> is missing
/// </summary>
public class MissingTableException<T> : Exception
{
/// <summary>
/// <see cref="Exception"/> that the table for the given <see cref="Type"/> is missing
/// </summary>
public MissingTableException()
: base($"There is no table for type {typeof(T)}.")
{
}
}
}

@ -0,0 +1,45 @@
// Author: Simon Gockner
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using GBase.FileHandling.Factories;
using GBase.Interfaces;
using GBase.Interfaces.DataHandling.Pool;
using GBase.Interfaces.FileHandling;
namespace GBase.Factories
{
/// <summary>
/// Factory for the <see cref="IGBaseTable"/>
/// </summary>
public class GBaseTableFactory : IGBaseTableFactory
{
private readonly IFileHandlerFactory _fileHandlerFactory;
private readonly IDataHandlerPool _dataHandlerPool;
private readonly IGBaseColumnFactory _gBaseColumnFactory;
/// <summary>
/// Factory for the <see cref="IGBaseTable"/>
/// </summary>
/// <param name="fileHandlerFactory">Factory for the <see cref="IFileHandler"/></param>
/// <param name="dataHandlerPool"></param>
/// <param name="gBaseColumnFactory">Factory for the <see cref="IGBaseColumn"/></param>
public GBaseTableFactory(IFileHandlerFactory fileHandlerFactory, IDataHandlerPool dataHandlerPool, IGBaseColumnFactory gBaseColumnFactory)
{
_fileHandlerFactory = fileHandlerFactory;
_dataHandlerPool = dataHandlerPool;
_gBaseColumnFactory = gBaseColumnFactory;
}
/// <summary>
/// Creates an <see cref="IGBaseTable"/>
/// </summary>
/// <returns>A newly created instance of the implementation for <see cref="IGBaseTable"/></returns>
public IGBaseTable Create(Type type)
{
Type gBaseTableType = typeof(GBaseTable<>).MakeGenericType(type);
return (IGBaseTable) Activator.CreateInstance(gBaseTableType, _fileHandlerFactory, _dataHandlerPool, _gBaseColumnFactory);
}
}
}

@ -16,6 +16,6 @@ namespace GBase.Factories
/// Creates an <see cref="IGBaseColumn"/> /// Creates an <see cref="IGBaseColumn"/>
/// </summary> /// </summary>
/// <returns>A newly created instance of the implementation for <see cref="IGBaseColumn"/></returns> /// <returns>A newly created instance of the implementation for <see cref="IGBaseColumn"/></returns>
IGBaseColumn Create(); IGBaseColumn Create(string name);
} }
} }

@ -3,6 +3,7 @@
// Copyright(c) 2020 SimonG. All Rights Reserved. // Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using GBase.Interfaces; using GBase.Interfaces;
namespace GBase.Factories namespace GBase.Factories
@ -16,6 +17,6 @@ namespace GBase.Factories
/// Creates an <see cref="IGBaseTable"/> /// Creates an <see cref="IGBaseTable"/>
/// </summary> /// </summary>
/// <returns>A newly created instance of the implementation for <see cref="IGBaseTable"/></returns> /// <returns>A newly created instance of the implementation for <see cref="IGBaseTable"/></returns>
IGBaseTable Create(); IGBaseTable Create(Type type);
} }
} }

@ -0,0 +1,17 @@
// Author: Gockner, Simon
// Created: 2020-11-10
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
namespace GBase.FileHandling.Exceptions
{
public class FileNotExistingException<T> : Exception
{
public FileNotExistingException()
: base($"File for the given type {typeof(T)} is not existing.")
{
}
}
}

@ -2,13 +2,13 @@
// Created: 2020-02-12 // Created: 2020-02-12
// Copyright(c) 2020 SimonG. All Rights Reserved. // Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.DataHandling.Factories; using GBase.FileHandling.Exceptions;
using GBase.Interfaces.DataHandling; using GBase.Interfaces;
using GBase.Interfaces.DataHandling.Xml;
using GBase.Interfaces.FileHandling; using GBase.Interfaces.FileHandling;
namespace GBase.FileHandling namespace GBase.FileHandling
@ -18,22 +18,22 @@ namespace GBase.FileHandling
/// </summary> /// </summary>
public class FileHandler : IFileHandler public class FileHandler : IFileHandler
{ {
private readonly IXmlDataHandlerFactory _dataHandlerFactory; /// <summary>
/// The file extension for all GBase tables
/// </summary>
public const string GBASE_TABLE_FILE_EXTENSION = "gb";
private readonly List<IGBaseFile> _files;
private string _path;
/// <summary> /// <summary>
/// Internal file handler /// Internal file handler
/// </summary> /// </summary>
/// <param name="xmlDataHandlerFactory">Factory for the <see cref="IXmlDataHandler"/></param> public FileHandler()
public FileHandler(IXmlDataHandlerFactory xmlDataHandlerFactory)
{ {
_dataHandlerFactory = xmlDataHandlerFactory; _files = new List<IGBaseFile>();
} }
/// <summary>
/// The <see cref="IDataHandler"/> of this <see cref="IFileHandler"/>
/// </summary>
private IDataHandler DataHandler { get; set; }
/// <summary> /// <summary>
/// Initialize this <see cref="IFileHandler"/> /// Initialize this <see cref="IFileHandler"/>
/// </summary> /// </summary>
@ -42,60 +42,48 @@ namespace GBase.FileHandling
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
public async Task<bool> Init(string path, CancellationToken cancellationToken) public async Task<bool> Init(string path, CancellationToken cancellationToken)
{ {
DataHandler = _dataHandlerFactory.Create(); _path = path;
return true; //TODO: initialize existing files
bool success = await DataHandler.Init(false, cancellationToken);
return success;
} }
/// <summary> public IGBaseFile CreateEntryFile<T>(T entry, IGBaseTable table)
/// Set the value for the given property
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param>
/// <returns>A <see cref="Task"/> to await</returns>
public async Task SetValue<T, TProperty>(string propertyName, TProperty value)
{ {
await DataHandler.SetValue<T, TProperty>(propertyName, value); string directoryPath = Path.Combine(_path, table.FolderName);
}
/// <summary> //create directory if it doesn't exist
/// Remove the value for the given property Directory.CreateDirectory(directoryPath);
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam> //create new entry file
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> string filePath = $"{Path.Combine(directoryPath, entry.ToString())}.{GBASE_TABLE_FILE_EXTENSION}";
/// <param name="propertyName">The name of the property</param> FileStream entryFile = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite); //TODO: Stream has to be disposed
/// <param name="value">The value to set</param>
/// <returns>A <see cref="Task"/> to await</returns> IGBaseFile file = new GBaseFile(entry, entryFile, filePath);
public async Task RemoveValue<T, TProperty>(string propertyName, TProperty value) _files.Add(file);
{
await DataHandler.RemoveValue<T, TProperty>(propertyName, value); return file.UseFile();
} }
/// <summary> public async Task<bool> DeleteEntryFile<T>(T entry)
/// Get the value for the given property, if multiple values are set the first is returned
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="propertyName">The name of the property</param>
/// <returns>The value for the given property</returns>
public async Task<TProperty> GetValue<T, TProperty>(string propertyName)
{ {
return await DataHandler.GetValue<T, TProperty>(propertyName); IGBaseFile file = _files.FirstOrDefault(f => f.Entry.Equals(entry));
if (file == default)
return false;
await file.File.DisposeAsync();
File.Delete(file.FilePath);
return true;
} }
/// <summary> public async Task<IGBaseFile> RequestEntryFile<T>(T entry)
/// Get all the values that are set for the given property
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="propertyName">The name of the property</param>
/// <returns>An <see cref="IEnumerable{T}"/> with all the values for the property</returns>
public async Task<IEnumerable<TProperty>> GetValues<T, TProperty>(string propertyName)
{ {
return await DataHandler.GetValues<T, TProperty>(propertyName); IGBaseFile file = _files.FirstOrDefault(f => f.Entry.Equals(entry));
if (file == default)
throw new FileNotExistingException<T>();
if (file.InUse)
await Task.Delay(1000);
return file.UseFile();
} }
/// <summary> /// <summary>
@ -104,7 +92,15 @@ namespace GBase.FileHandling
/// <returns>A <see cref="ValueTask"/> to await</returns> /// <returns>A <see cref="ValueTask"/> to await</returns>
public async ValueTask DisposeAsync() public async ValueTask DisposeAsync()
{ {
await DataHandler.DisposeAsync(); while (_files.Any(f => f.InUse))
{
await Task.Delay(1000);
}
foreach (var file in _files)
{
await file.File.DisposeAsync();
}
} }
} }
} }

@ -0,0 +1,32 @@
// Author: Gockner, Simon
// Created: 2020-11-10
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System.IO;
using GBase.Interfaces.FileHandling;
namespace GBase.FileHandling
{
public class GBaseFile : IGBaseFile
{
public GBaseFile(object entry, FileStream file, string filePath)
{
Entry = entry;
File = file;
FilePath = filePath;
}
public object Entry { get; }
public FileStream File { get; }
public string FilePath { get; }
public bool InUse { get; private set; }
public IGBaseFile UseFile()
{
InUse = true;
return this;
}
public void Dispose() => InUse = false;
}
}

@ -9,6 +9,7 @@ using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.Attributes; using GBase.Attributes;
using GBase.Exceptions;
using GBase.Factories; using GBase.Factories;
using GBase.Interfaces; using GBase.Interfaces;
using GBase.Interfaces.Settings; using GBase.Interfaces.Settings;
@ -20,11 +21,6 @@ namespace GBase
/// </summary> /// </summary>
public class GBase : IGBase public class GBase : IGBase
{ {
/// <summary>
/// The file extension for all GBase tables
/// </summary>
public const string GBASE_TABLE_FILE_EXTENSION = "gb"; //TODO: Find correct place for this const
private readonly IGBaseTableFactory _gBaseTableFactory; private readonly IGBaseTableFactory _gBaseTableFactory;
/// <summary> /// <summary>
@ -74,8 +70,8 @@ namespace GBase
if (gBaseTableAttribute == null) if (gBaseTableAttribute == null)
continue; continue;
IGBaseTable gBaseTable = _gBaseTableFactory.Create(); IGBaseTable gBaseTable = _gBaseTableFactory.Create(type);
await gBaseTable.Init(type, type.Name, Settings.DatabasePath, cancellationToken); await gBaseTable.Init(type, Settings.DatabasePath, gBaseTableAttribute.FolderName, cancellationToken);
AddTable(gBaseTable); AddTable(gBaseTable);
} }
@ -93,13 +89,23 @@ namespace GBase
if (Tables.Contains(table)) if (Tables.Contains(table))
return false; return false;
if (Tables.Any(t => t.Name.Equals(table.Name))) if (Tables.Any(t => t.FolderName.Equals(table.FolderName)))
return false; return false;
Tables.Add(table); Tables.Add(table);
return true; return true;
} }
public IGBaseTable<T> GetTable<T>()
{
if (Tables.OfType<IGBaseTable<T>>().Any())
return Tables.OfType<IGBaseTable<T>>().First();
throw new MissingTableException<T>();
// //TODO: This probably doesn't work, because even though t.Type : T, IGBaseTable<t.Type> !: IGBaseTable<T>
// return (IGBaseTable<T>) Convert.ChangeType(Tables.FirstOrDefault(t => typeof(T).IsAssignableFrom(t.Type)), typeof(IGBaseTable<T>)); //TestMe
}
/// <summary> /// <summary>
/// Removes a given <see cref="IGBaseTable"/> from this <see cref="GBase"/> /// Removes a given <see cref="IGBaseTable"/> from this <see cref="GBase"/>
/// </summary> /// </summary>
@ -113,6 +119,43 @@ namespace GBase
return Tables.Remove(table); return Tables.Remove(table);
} }
public async Task<bool> AddEntry<T>(T entry, CancellationToken cancellationToken)
{
IGBaseTable<T> table = GetTable<T>();
if (table == null)
throw new MissingTableException<T>();
return await table.AddEntry(entry, cancellationToken);
}
public async Task SetValue<T, TProperty>(T entry, string propertyName, TProperty value, CancellationToken cancellationToken)
{
IGBaseTable<T> table = GetTable<T>();
if (table == null)
throw new MissingTableException<T>();
await table.SetValue(entry, propertyName, value, cancellationToken);
}
public async Task<TProperty> GetValue<T, TProperty>(T entry, string propertyName, CancellationToken cancellationToken)
{
IGBaseTable<T> table = GetTable<T>();
if (table == null)
throw new MissingTableException<T>();
return await table.GetValue<TProperty>(entry, propertyName, cancellationToken);
}
public async Task<IEnumerable<TProperty>> GetValues<T, TProperty>(T entry, string propertyName, CancellationToken cancellationToken)
{
IGBaseTable<T> table = GetTable<T>();
if (table == null)
throw new MissingTableException<T>();
return await table.GetValues<TProperty>(entry, propertyName, cancellationToken);
}
/// <summary> /// <summary>
/// Dispose used resources asynchronously /// Dispose used resources asynchronously
/// </summary> /// </summary>

@ -87,13 +87,15 @@
<param name="value">The value to set</param> <param name="value">The value to set</param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.DataHandling.Cache.XmlDataHandlerCache.TryGetValues``2(System.String)"> <member name="M:GBase.DataHandling.Cache.XmlDataHandlerCache.TryGetValues``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Try to get values from the cache for the given property Try to get values from the cache for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns> <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns>
</member> </member>
<member name="T:GBase.DataHandling.Cache.XmlDataHandlerCacheEntry"> <member name="T:GBase.DataHandling.Cache.XmlDataHandlerCacheEntry">
@ -163,11 +165,10 @@
Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/> Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.DataHandling.Factories.IXmlDataReaderFactory.Create(System.String)"> <member name="M:GBase.DataHandling.Factories.IXmlDataReaderFactory.Create">
<summary> <summary>
Creates an <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/> Creates an <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/>
</summary> </summary>
<param name="path">The path to the xml file</param>
<returns>A newly created instance of the implementation for <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/></returns> <returns>A newly created instance of the implementation for <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/></returns>
</member> </member>
<member name="T:GBase.DataHandling.Factories.IXmlDataWriterFactory"> <member name="T:GBase.DataHandling.Factories.IXmlDataWriterFactory">
@ -175,12 +176,10 @@
Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/> Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.DataHandling.Factories.IXmlDataWriterFactory.Create(System.String,System.String)"> <member name="M:GBase.DataHandling.Factories.IXmlDataWriterFactory.Create">
<summary> <summary>
Creates an <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/> Creates an <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/>
</summary> </summary>
<param name="path">The path to the xml file</param>
<param name="rootElementName">The root element name of the xml file</param>
<returns>A newly created instance of the implementation for <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/></returns> <returns>A newly created instance of the implementation for <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/></returns>
</member> </member>
<member name="T:GBase.DataHandling.XmlDataHandler"> <member name="T:GBase.DataHandling.XmlDataHandler">
@ -198,152 +197,142 @@
The attribute name of the value <see cref="T:System.Type"/> attribute The attribute name of the value <see cref="T:System.Type"/> attribute
</summary> </summary>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.#ctor(System.String,System.String,GBase.DataHandling.Factories.IXmlDataReaderFactory,GBase.DataHandling.Factories.IXmlDataWriterFactory,GBase.DataHandling.Cache.Factories.IXmlDataHandlerCacheFactory)"> <member name="M:GBase.DataHandling.XmlDataHandler.#ctor(GBase.DataHandling.Factories.IXmlDataReaderFactory,GBase.DataHandling.Factories.IXmlDataWriterFactory,GBase.DataHandling.Cache.Factories.IXmlDataHandlerCacheFactory)">
<summary> <summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/> that handles its data in an xml file A <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/> that handles its data in an xml file
</summary> </summary>
<param name="path">The path to the xml file</param> <param name="path">The path to the xml file</param>
<param name="rootElementName">The root element name of the xml file</param>
<param name="xmlDataReaderFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/> factory</param> <param name="xmlDataReaderFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/> factory</param>
<param name="xmlDataWriterFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/> factory</param> <param name="xmlDataWriterFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/> factory</param>
<param name="xmlDataHandlerCacheFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.Cache.IXmlDataHandlerCache"/> factory</param> <param name="xmlDataHandlerCacheFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.Cache.IXmlDataHandlerCache"/> factory</param>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.Init(System.Boolean,System.Threading.CancellationToken)"> <member name="M:GBase.DataHandling.XmlDataHandler.Init(System.Boolean)">
<summary> <summary>
Initialize the <see cref="T:GBase.DataHandling.XmlDataHandler"/> Initialize the <see cref="T:GBase.DataHandling.XmlDataHandler"/>
</summary> </summary>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param> <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param>
<returns>Returns true if successful, false if not</returns> <returns>Returns true if successful, false if not</returns>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.SetValue``2(System.String,``1)"> <member name="M:GBase.DataHandling.XmlDataHandler.SetValue``2(System.IO.FileStream,System.String,``1,System.Threading.CancellationToken)">
<summary> <summary>
Set the value for the given property Set the value for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="entryFile"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value to set</param> <param name="value">The value to set</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.RemoveValue``2(System.String,``1)"> <member name="M:GBase.DataHandling.XmlDataHandler.RemoveValue``2(System.IO.FileStream,System.String,``1,System.Threading.CancellationToken)">
<summary> <summary>
Remove the value for the given property Remove the value for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="entryFile"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value to set</param> <param name="value">The value to set</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.GetValue``2(System.String)"> <member name="M:GBase.DataHandling.XmlDataHandler.GetValue``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Get the value for the given property, if multiple values are set the first is returned Get the value for the given property, if multiple values are set the first is returned
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>The value for the given property</returns> <returns>The value for the given property</returns>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.GetValues``2(System.String)"> <member name="M:GBase.DataHandling.XmlDataHandler.GetValues``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Get all the values that are set for the given property Get all the values that are set for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns> <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.DisposeAsync">
<summary>
Dispose used resources asynchronously
</summary>
<returns>A <see cref="T:System.Threading.Tasks.ValueTask"/> to await</returns>
</member>
<member name="T:GBase.DataHandling.XmlDataReader"> <member name="T:GBase.DataHandling.XmlDataReader">
<summary> <summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file A <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file
</summary> </summary>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataReader.#ctor(System.String)"> <member name="M:GBase.DataHandling.XmlDataReader.Read``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file
</summary>
<param name="path">The path to the xml file</param>
</member>
<member name="M:GBase.DataHandling.XmlDataReader.Init(System.Threading.CancellationToken)">
<summary>
Initialize the <see cref="T:GBase.DataHandling.XmlDataReader"/>
</summary>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param>
<returns>Returns true if successful, false if not</returns>
<exception cref="T:System.Exception">No root element found</exception>
</member>
<member name="M:GBase.DataHandling.XmlDataReader.Read``2(System.String)">
<summary> <summary>
Read the data of a property Read the data of a property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/></typeparam> <typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>The data of the given property, null if no data found</returns> <returns>The data of the given property, null if no data found</returns>
<exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception> <exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception>
<exception cref="T:System.InvalidOperationException">Invalid <see cref="T:System.Type"/> found for the read object</exception> <exception cref="T:System.InvalidOperationException">Invalid <see cref="T:System.Type"/> found for the read object</exception>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataReader.DisposeAsync">
<summary>
Dispose used resources asynchronously
</summary>
<returns>A <see cref="T:System.Threading.Tasks.ValueTask"/> to await</returns>
</member>
<member name="T:GBase.DataHandling.XmlDataWriter"> <member name="T:GBase.DataHandling.XmlDataWriter">
<summary> <summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataWriter"/> that writes to a xml file A <see cref="T:GBase.Interfaces.DataHandling.IDataWriter"/> that writes to a xml file
</summary> </summary>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataWriter.#ctor(System.String,System.String)"> <member name="M:GBase.DataHandling.XmlDataWriter.InitFile(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataWriter"/> that writes to an xml file
</summary>
<param name="path">The path to the xml file</param>
<param name="rootElementName">The root element name of the xml file</param>
</member>
<member name="M:GBase.DataHandling.XmlDataWriter.Init(System.Threading.CancellationToken)">
<summary> <summary>
Initialize the <see cref="T:GBase.DataHandling.XmlDataWriter"/> Initialize the <see cref="T:GBase.DataHandling.XmlDataWriter"/>
</summary> </summary>
<param name="file"></param>
<param name="rootElementName"></param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param> <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param>
<returns>Returns true if successful, false if not</returns> <returns>Returns true if successful, false if not</returns>
<exception cref="T:System.Exception">No root element found</exception> <exception cref="T:System.Exception">No root element found</exception>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataWriter.Write``2(System.String,System.String,System.Boolean)"> <member name="M:GBase.DataHandling.XmlDataWriter.Write``2(System.IO.FileStream,System.String,System.String,System.Boolean,System.Threading.CancellationToken)">
<summary> <summary>
Write the data of a property Write the data of a property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value of the property</param> <param name="value">The value of the property</param>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param> <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member>
<member name="M:GBase.DataHandling.XmlDataWriter.Write``1(System.IO.FileStream,System.String,System.String,System.Type,System.Boolean,System.Threading.CancellationToken)">
<summary>
Write the data of a property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param>
<param name="value">The value of the property</param>
<param name="propertyType"></param>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
<exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception> <exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception>
<exception cref="T:GBase.DataHandling.Exceptions.InvalidXmlFileException">No root element is set</exception>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataWriter.Remove``2(System.String,System.String)"> <member name="M:GBase.DataHandling.XmlDataWriter.Remove``2(System.IO.FileStream,System.String,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Remove the value for the given property Remove the value for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value to set</param> <param name="value">The value to set</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
<exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception> <exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception>
</member> <exception cref="T:GBase.DataHandling.Exceptions.InvalidXmlFileException">No root element is set</exception>
<member name="M:GBase.DataHandling.XmlDataWriter.DisposeAsync">
<summary>
Dispose used resources asynchronously
</summary>
<returns>A <see cref="T:System.Threading.Tasks.ValueTask"/> to await</returns>
</member> </member>
<member name="T:GBase.Exceptions.InterfaceEnumerablePassedException"> <member name="T:GBase.Exceptions.InterfaceEnumerablePassedException">
<summary> <summary>
@ -361,12 +350,52 @@
The <see cref="T:System.Type"/> of the passed interface The <see cref="T:System.Type"/> of the passed interface
</summary> </summary>
</member> </member>
<member name="T:GBase.Exceptions.InvalidTableTypeException">
<summary>
<see cref="T:System.Exception"/> that the passed table type doesn't implement <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/>"/>
</summary>
</member>
<member name="M:GBase.Exceptions.InvalidTableTypeException.#ctor(System.Type)">
<summary>
<see cref="T:System.Exception"/> that the passed table type doesn't implement <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/>"/>
</summary>
<param name="type">The table type</param>
</member>
<member name="T:GBase.Exceptions.MissingTableException`1">
<summary>
<see cref="T:System.Exception"/> that the table for the given <see cref="T:System.Type"/> is missing
</summary>
</member>
<member name="M:GBase.Exceptions.MissingTableException`1.#ctor">
<summary>
<see cref="T:System.Exception"/> that the table for the given <see cref="T:System.Type"/> is missing
</summary>
</member>
<member name="T:GBase.Factories.GBaseTableFactory">
<summary>
Factory for the <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
</member>
<member name="M:GBase.Factories.GBaseTableFactory.#ctor(GBase.FileHandling.Factories.IFileHandlerFactory,GBase.Interfaces.DataHandling.Pool.IDataHandlerPool,GBase.Factories.IGBaseColumnFactory)">
<summary>
Factory for the <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<param name="fileHandlerFactory">Factory for the <see cref="T:GBase.Interfaces.FileHandling.IFileHandler"/></param>
<param name="dataHandlerPool"></param>
<param name="gBaseColumnFactory">Factory for the <see cref="T:GBase.Interfaces.IGBaseColumn"/></param>
</member>
<member name="M:GBase.Factories.GBaseTableFactory.Create(System.Type)">
<summary>
Creates an <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<returns>A newly created instance of the implementation for <see cref="T:GBase.Interfaces.IGBaseTable"/></returns>
</member>
<member name="T:GBase.Factories.IGBaseColumnFactory"> <member name="T:GBase.Factories.IGBaseColumnFactory">
<summary> <summary>
Factory for the <see cref="T:GBase.Interfaces.IGBaseColumn"/> Factory for the <see cref="T:GBase.Interfaces.IGBaseColumn"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.Factories.IGBaseColumnFactory.Create"> <member name="M:GBase.Factories.IGBaseColumnFactory.Create(System.String)">
<summary> <summary>
Creates an <see cref="T:GBase.Interfaces.IGBaseColumn"/> Creates an <see cref="T:GBase.Interfaces.IGBaseColumn"/>
</summary> </summary>
@ -389,7 +418,7 @@
Factory for the <see cref="T:GBase.Interfaces.IGBaseTable"/> Factory for the <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.Factories.IGBaseTableFactory.Create"> <member name="M:GBase.Factories.IGBaseTableFactory.Create(System.Type)">
<summary> <summary>
Creates an <see cref="T:GBase.Interfaces.IGBaseTable"/> Creates an <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
@ -411,15 +440,14 @@
Internal file handler Internal file handler
</summary> </summary>
</member> </member>
<member name="M:GBase.FileHandling.FileHandler.#ctor(GBase.DataHandling.Factories.IXmlDataHandlerFactory)"> <member name="F:GBase.FileHandling.FileHandler.GBASE_TABLE_FILE_EXTENSION">
<summary> <summary>
Internal file handler The file extension for all GBase tables
</summary> </summary>
<param name="xmlDataHandlerFactory">Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataHandler"/></param>
</member> </member>
<member name="P:GBase.FileHandling.FileHandler.DataHandler"> <member name="M:GBase.FileHandling.FileHandler.#ctor">
<summary> <summary>
The <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/> of this <see cref="T:GBase.Interfaces.FileHandling.IFileHandler"/> Internal file handler
</summary> </summary>
</member> </member>
<member name="M:GBase.FileHandling.FileHandler.Init(System.String,System.Threading.CancellationToken)"> <member name="M:GBase.FileHandling.FileHandler.Init(System.String,System.Threading.CancellationToken)">
@ -430,44 +458,6 @@
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the asynchronous operation</param> <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the asynchronous operation</param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.FileHandling.FileHandler.SetValue``2(System.String,``1)">
<summary>
Set the value for the given property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="propertyName">The name of the property</param>
<param name="value">The value to set</param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member>
<member name="M:GBase.FileHandling.FileHandler.RemoveValue``2(System.String,``1)">
<summary>
Remove the value for the given property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="propertyName">The name of the property</param>
<param name="value">The value to set</param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member>
<member name="M:GBase.FileHandling.FileHandler.GetValue``2(System.String)">
<summary>
Get the value for the given property, if multiple values are set the first is returned
</summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="propertyName">The name of the property</param>
<returns>The value for the given property</returns>
</member>
<member name="M:GBase.FileHandling.FileHandler.GetValues``2(System.String)">
<summary>
Get all the values that are set for the given property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="propertyName">The name of the property</param>
<returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns>
</member>
<member name="M:GBase.FileHandling.FileHandler.DisposeAsync"> <member name="M:GBase.FileHandling.FileHandler.DisposeAsync">
<summary> <summary>
Dispose used resources asynchronously Dispose used resources asynchronously
@ -479,11 +469,6 @@
The base class of the GBase database The base class of the GBase database
</summary> </summary>
</member> </member>
<member name="F:GBase.GBase.GBASE_TABLE_FILE_EXTENSION">
<summary>
The file extension for all GBase tables
</summary>
</member>
<member name="M:GBase.GBase.#ctor(GBase.Interfaces.Settings.IGBaseSettings,GBase.Factories.IGBaseTableFactory)"> <member name="M:GBase.GBase.#ctor(GBase.Interfaces.Settings.IGBaseSettings,GBase.Factories.IGBaseTableFactory)">
<summary> <summary>
The base class of the GBase database The base class of the GBase database
@ -540,7 +525,7 @@
A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/> A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.GBaseColumn.#ctor"> <member name="M:GBase.GBaseColumn.#ctor(System.String)">
<summary> <summary>
A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/> A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
@ -551,91 +536,96 @@
</summary> </summary>
<returns>A <see cref="T:System.Threading.Tasks.ValueTask"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.ValueTask"/> to await</returns>
</member> </member>
<member name="T:GBase.GBaseTable"> <member name="T:GBase.GBaseObject`1">
<summary>
GBase object that supplies inheriting classes with methods to get data from a <see cref="T:GBase.Interfaces.IGBase"/>
</summary>
</member>
<member name="M:GBase.GBaseObject`1.#ctor(GBase.Interfaces.IGBase)">
<summary>
GBase object that allows conversion from <see cref="T:System.String"/>
</summary>
<exception cref="T:GBase.Exceptions.MissingTableException`1">No table for <typeparamref name="T"/> is existing</exception>
</member>
<member name="M:GBase.GBaseObject`1.InitializeFromString(System.String)">
<summary>
Initialize this <see cref="T:GBase.GBaseObject`1"/> from a given <see cref="T:System.String"/>
</summary>
<param name="string">The given <see cref="T:System.String"/></param>
</member>
<member name="T:GBase.GBaseTable`1">
<summary> <summary>
A <see cref="T:GBase.Interfaces.IGBase"/> table A <see cref="T:GBase.Interfaces.IGBase"/> table
</summary> </summary>
</member> </member>
<member name="M:GBase.GBaseTable.#ctor(GBase.FileHandling.Factories.IFileHandlerFactory,GBase.Factories.IGBaseColumnFactory)"> <member name="M:GBase.GBaseTable`1.#ctor(GBase.FileHandling.Factories.IFileHandlerFactory,GBase.Interfaces.DataHandling.Pool.IDataHandlerPool,GBase.Factories.IGBaseColumnFactory)">
<summary> <summary>
A <see cref="T:GBase.Interfaces.IGBase"/> table A <see cref="T:GBase.Interfaces.IGBase"/> table
</summary> </summary>
<param name="fileHandlerFactory"></param>
<param name="dataHandlerPool">The <see cref="T:GBase.Interfaces.DataHandling.Pool.IDataHandlerPool"/></param>
<param name="gBaseColumnFactory"></param>
</member> </member>
<member name="P:GBase.GBaseTable.Type"> <member name="P:GBase.GBaseTable`1.Type">
<summary> <summary>
The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents
</summary> </summary>
</member> </member>
<member name="P:GBase.GBaseTable.Name"> <member name="P:GBase.GBaseTable`1.FolderName">
<summary> <summary>
The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/> The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="P:GBase.GBaseTable.Columns"> <member name="P:GBase.GBaseTable`1.Columns">
<summary> <summary>
The <see cref="T:GBase.Interfaces.IGBaseColumn"/>s of this <see cref="T:GBase.Interfaces.IGBaseTable"/> The <see cref="T:GBase.Interfaces.IGBaseColumn"/>s of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="P:GBase.GBaseTable.Entries"> <member name="P:GBase.GBaseTable`1.Entries">
<summary> <summary>
The entries of this <see cref="T:GBase.Interfaces.IGBaseTable"/> The entries of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.GBaseTable.Init(System.Type,System.String,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.GBaseTable`1.Init(System.Type,System.String,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Initialize this <see cref="T:GBase.Interfaces.IGBase"/> Initialize this <see cref="T:GBase.Interfaces.IGBase"/>
</summary> </summary>
<param name="type">The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents</param> <param name="type">The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents</param>
<param name="name">The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/></param>
<param name="databasePath">The path to the database files</param> <param name="databasePath">The path to the database files</param>
<param name="folderName"></param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the asynchronous operation</param> <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the asynchronous operation</param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.GBaseTable.AddColumn(GBase.Interfaces.IGBaseColumn)"> <member name="M:GBase.GBaseTable`1.AddColumn(GBase.Interfaces.IGBaseColumn)">
<summary> <summary>
Add a given <see cref="T:GBase.Interfaces.IGBaseColumn"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/> Add a given <see cref="T:GBase.Interfaces.IGBaseColumn"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
<param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param> <param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.GBaseTable.RemoveColumn(GBase.Interfaces.IGBaseColumn)"> <member name="M:GBase.GBaseTable`1.RemoveColumn(GBase.Interfaces.IGBaseColumn)">
<summary> <summary>
Remove a given <see cref="T:GBase.Interfaces.IGBaseColumn"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/> Remove a given <see cref="T:GBase.Interfaces.IGBaseColumn"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
<param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param> <param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.GBaseTable.AddEntry(GBase.Api.INotifyGBaseEntryChanged)"> <member name="M:GBase.GBaseTable`1.AddEntry(`0,System.Threading.CancellationToken)">
<summary> <summary>
Add an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/> Add an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
<param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param> <param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<param name="cancellationToken"></param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.GBaseTable.RemoveEntry(GBase.Api.INotifyGBaseEntryChanged)"> <member name="M:GBase.GBaseTable`1.RemoveEntry(`0)">
<summary> <summary>
Remove an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/> Remove an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
<param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param> <param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.GBaseTable.ModifyEntry(System.Object,System.String,System.Object)"> <member name="M:GBase.GBaseTable`1.DisposeAsync">
<summary>
Modify the property of a given entry with the given value
</summary>
<param name="entry">The entry</param>
<param name="propertyName">The name of the property</param>
<param name="value">The new value to set</param>
<returns>True if successful, false if not</returns>
</member>
<member name="M:GBase.GBaseTable.OnGBaseEntryChanged(System.Object,GBase.Api.GBaseEntryChangedEventArgs)">
<summary>
A <see cref="T:GBase.Interfaces.IGBase"/> entry changed
</summary>
<param name="entry">The entry (sender)</param>
<param name="args">The <see cref="T:GBase.Api.GBaseEntryChangedEventArgs"/></param>
</member>
<member name="M:GBase.GBaseTable.DisposeAsync">
<summary> <summary>
The <see cref="M:System.IAsyncDisposable.DisposeAsync"/> method The <see cref="M:System.IAsyncDisposable.DisposeAsync"/> method
</summary> </summary>
@ -707,13 +697,15 @@
<param name="value">The value to set</param> <param name="value">The value to set</param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.Cache.IDataHandlerCache.TryGetValues``2(System.String)"> <member name="M:GBase.Interfaces.DataHandling.Cache.IDataHandlerCache.TryGetValues``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Try to get values from the cache for the given property Try to get values from the cache for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns> <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns>
</member> </member>
<member name="T:GBase.Interfaces.DataHandling.Cache.IDataHandlerCacheEntry"> <member name="T:GBase.Interfaces.DataHandling.Cache.IDataHandlerCacheEntry">
@ -756,50 +748,57 @@
Interface for data handlers to implement Interface for data handlers to implement
</summary> </summary>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.Init(System.Boolean,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.Init(System.Boolean)">
<summary> <summary>
Initialize the <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/> Initialize the <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/>
</summary> </summary>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param> <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param>
<returns>Returns true if successful, false if not</returns> <returns>Returns true if successful, false if not</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.SetValue``2(System.String,``1)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.SetValue``2(System.IO.FileStream,System.String,``1,System.Threading.CancellationToken)">
<summary> <summary>
Set the value for the given property Set the value for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="entryFile"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value to set</param> <param name="value">The value to set</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.RemoveValue``2(System.String,``1)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.RemoveValue``2(System.IO.FileStream,System.String,``1,System.Threading.CancellationToken)">
<summary> <summary>
Remove the value for the given property Remove the value for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="entryFile"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value to set</param> <param name="value">The value to set</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValue``2(System.String)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValue``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Get the value for the given property, if multiple values are set the first is returned Get the value for the given property, if multiple values are set the first is returned
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>The value for the given property</returns> <returns>The value for the given property</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValues``2(System.String)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValues``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Get all the values that are set for the given property Get all the values that are set for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns> <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns>
</member> </member>
<member name="T:GBase.Interfaces.DataHandling.IDataReader"> <member name="T:GBase.Interfaces.DataHandling.IDataReader">
@ -807,20 +806,15 @@
Interface for data readers to implement Interface for data readers to implement
</summary> </summary>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataReader.Init(System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataReader.Read``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary>
Initialize the <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/>
</summary>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param>
<returns>Returns true if successful, false if not</returns>
</member>
<member name="M:GBase.Interfaces.DataHandling.IDataReader.Read``2(System.String)">
<summary> <summary>
Read the data of a property Read the data of a property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/></typeparam> <typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>The data of the given property, null if no data found</returns> <returns>The data of the given property, null if no data found</returns>
</member> </member>
<member name="T:GBase.Interfaces.DataHandling.IDataWriter"> <member name="T:GBase.Interfaces.DataHandling.IDataWriter">
@ -828,32 +822,51 @@
Interface for data writers to implement Interface for data writers to implement
</summary> </summary>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.Init(System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataWriter.InitFile(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Initialize the <see cref="T:GBase.Interfaces.DataHandling.IDataWriter"/> Initialize the <see cref="T:GBase.Interfaces.DataHandling.IDataWriter"/>
</summary> </summary>
<param name="file"></param>
<param name="rootElementName"></param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param> <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param>
<returns>Returns true if successful, false if not</returns> <returns>Returns true if successful, false if not</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.Write``2(System.String,System.String,System.Boolean)"> <member name="M:GBase.Interfaces.DataHandling.IDataWriter.Write``2(System.IO.FileStream,System.String,System.String,System.Boolean,System.Threading.CancellationToken)">
<summary> <summary>
Write the data of a property Write the data of a property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/></typeparam> <typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value of the property</param> <param name="value">The value of the property</param>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param> <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.Remove``2(System.String,System.String)"> <member name="M:GBase.Interfaces.DataHandling.IDataWriter.Write``1(System.IO.FileStream,System.String,System.String,System.Type,System.Boolean,System.Threading.CancellationToken)">
<summary>
Write the data of a property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param>
<param name="value">The value of the property</param>
<param name="propertyType"></param>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member>
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.Remove``2(System.IO.FileStream,System.String,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Remove the value for the given property Remove the value for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value to set</param> <param name="value">The value to set</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="T:GBase.Interfaces.DataHandling.Xml.Cache.IXmlDataHandlerCache"> <member name="T:GBase.Interfaces.DataHandling.Xml.Cache.IXmlDataHandlerCache">
@ -899,44 +912,6 @@
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the asynchronous operation</param> <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the asynchronous operation</param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.Interfaces.FileHandling.IFileHandler.SetValue``2(System.String,``1)">
<summary>
Set the value for the given property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="propertyName">The name of the property</param>
<param name="value">The value to set</param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member>
<member name="M:GBase.Interfaces.FileHandling.IFileHandler.RemoveValue``2(System.String,``1)">
<summary>
Remove the value for the given property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="propertyName">The name of the property</param>
<param name="value">The value to set</param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member>
<member name="M:GBase.Interfaces.FileHandling.IFileHandler.GetValue``2(System.String)">
<summary>
Get the value for the given property, if multiple values are set the first is returned
</summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="propertyName">The name of the property</param>
<returns>The value for the given property</returns>
</member>
<member name="M:GBase.Interfaces.FileHandling.IFileHandler.GetValues``2(System.String)">
<summary>
Get all the values that are set for the given property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="propertyName">The name of the property</param>
<returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns>
</member>
<member name="T:GBase.Interfaces.IGBase"> <member name="T:GBase.Interfaces.IGBase">
<summary> <summary>
The base class of the GBase database The base class of the GBase database
@ -985,6 +960,26 @@
A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/> A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="P:GBase.Interfaces.IGBaseTable`1.Entries">
<summary>
The entries of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
</member>
<member name="M:GBase.Interfaces.IGBaseTable`1.AddEntry(`0,System.Threading.CancellationToken)">
<summary>
Add an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<param name="cancellationToken"></param>
<returns>True if successful, false if not</returns>
</member>
<member name="M:GBase.Interfaces.IGBaseTable`1.RemoveEntry(`0)">
<summary>
Remove an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<returns>True if successful, false if not</returns>
</member>
<member name="T:GBase.Interfaces.IGBaseTable"> <member name="T:GBase.Interfaces.IGBaseTable">
<summary> <summary>
A <see cref="T:GBase.Interfaces.IGBase"/> table A <see cref="T:GBase.Interfaces.IGBase"/> table
@ -995,7 +990,7 @@
The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents
</summary> </summary>
</member> </member>
<member name="P:GBase.Interfaces.IGBaseTable.Name"> <member name="P:GBase.Interfaces.IGBaseTable.FolderName">
<summary> <summary>
The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/> The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
@ -1005,19 +1000,15 @@
The <see cref="T:GBase.Interfaces.IGBaseColumn"/>s of this <see cref="T:GBase.Interfaces.IGBaseTable"/> The <see cref="T:GBase.Interfaces.IGBaseColumn"/>s of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="P:GBase.Interfaces.IGBaseTable.Entries">
<summary>
The entries of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
</member>
<member name="M:GBase.Interfaces.IGBaseTable.Init(System.Type,System.String,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.IGBaseTable.Init(System.Type,System.String,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Initialize this <see cref="T:GBase.Interfaces.IGBase"/> Initialize this <see cref="T:GBase.Interfaces.IGBase"/>
</summary> </summary>
<param name="type">The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents</param> <param name="type">The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents</param>
<param name="name">The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/></param> <param name="databasePath">The path to the database files</param>
/// <param name="databasePath">The path to the database files</param> <param name="folderName"></param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the asynchronous operation</param> <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the asynchronous operation</param>
///
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.Interfaces.IGBaseTable.AddColumn(GBase.Interfaces.IGBaseColumn)"> <member name="M:GBase.Interfaces.IGBaseTable.AddColumn(GBase.Interfaces.IGBaseColumn)">
@ -1034,20 +1025,6 @@
<param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param> <param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.Interfaces.IGBaseTable.AddEntry(GBase.Api.INotifyGBaseEntryChanged)">
<summary>
Add an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<returns>True if successful, false if not</returns>
</member>
<member name="M:GBase.Interfaces.IGBaseTable.RemoveEntry(GBase.Api.INotifyGBaseEntryChanged)">
<summary>
Remove an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<returns>True if successful, false if not</returns>
</member>
<member name="T:GBase.Interfaces.Settings.IGBaseSettings"> <member name="T:GBase.Interfaces.Settings.IGBaseSettings">
<summary> <summary>
Settings of a <see cref="T:GBase.Interfaces.IGBase"/> instance Settings of a <see cref="T:GBase.Interfaces.IGBase"/> instance

@ -16,11 +16,13 @@ namespace GBase
/// <summary> /// <summary>
/// A column of a <see cref="IGBaseTable"/> /// A column of a <see cref="IGBaseTable"/>
/// </summary> /// </summary>
public GBaseColumn() public GBaseColumn(string name)
{ {
Name = name;
} }
public string Name { get; }
/// <summary> /// <summary>
/// The <see cref="IAsyncDisposable.DisposeAsync"/> method /// The <see cref="IAsyncDisposable.DisposeAsync"/> method
/// </summary> /// </summary>

@ -0,0 +1,47 @@
// Author: Gockner, Simon
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using GBase.Api;
using GBase.Exceptions;
using GBase.Interfaces;
namespace GBase
{
/// <summary>
/// GBase object that supplies inheriting classes with methods to get data from a <see cref="IGBase"/>
/// </summary>
public abstract class GBaseObject<T> : IGBaseObject
{
private readonly IGBaseTable<T> _gBaseTable;
/// <summary>
/// GBase object that allows conversion from <see cref="string"/>
/// </summary>
/// <exception cref="MissingTableException{T}">No table for <typeparamref name="T"/> is existing</exception>
protected GBaseObject(IGBase gBase)
{
_gBaseTable = gBase.GetTable<T>();
if (_gBaseTable == null)
throw new MissingTableException<T>();
}
protected async Task SetValue<TProperty>(T @this, string propertyName, TProperty value, CancellationToken cancellationToken) =>
await _gBaseTable.SetValue(@this, propertyName, value, cancellationToken);
protected async Task<TProperty> GetValue<TProperty>(T @this, string propertyName, CancellationToken cancellationToken) =>
await _gBaseTable.GetValue<TProperty>(@this, propertyName, cancellationToken);
protected async Task<IEnumerable<TProperty>> GetValues<TProperty>(T @this, string propertyName, CancellationToken cancellationToken) =>
await _gBaseTable.GetValues<TProperty>(@this, propertyName, cancellationToken);
/// <summary>
/// Initialize this <see cref="GBaseObject{T}"/> from a given <see cref="string"/>
/// </summary>
/// <param name="string">The given <see cref="string"/></param>
public abstract void InitializeFromString(string @string);
}
}

@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
@ -14,6 +13,8 @@ using GBase.Attributes;
using GBase.Factories; using GBase.Factories;
using GBase.FileHandling.Factories; using GBase.FileHandling.Factories;
using GBase.Interfaces; using GBase.Interfaces;
using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Pool;
using GBase.Interfaces.FileHandling; using GBase.Interfaces.FileHandling;
namespace GBase namespace GBase
@ -21,21 +22,26 @@ namespace GBase
/// <summary> /// <summary>
/// A <see cref="IGBase"/> table /// A <see cref="IGBase"/> table
/// </summary> /// </summary>
public class GBaseTable : IGBaseTable public class GBaseTable<T> : IGBaseTable<T>
{ {
private readonly IFileHandler _fileHandler; private readonly IFileHandler _fileHandler;
private readonly IDataHandlerPool _dataHandlerPool;
private readonly IGBaseColumnFactory _gBaseColumnFactory; private readonly IGBaseColumnFactory _gBaseColumnFactory;
/// <summary> /// <summary>
/// A <see cref="IGBase"/> table /// A <see cref="IGBase"/> table
/// </summary> /// </summary>
public GBaseTable(IFileHandlerFactory fileHandlerFactory, IGBaseColumnFactory gBaseColumnFactory) /// <param name="fileHandlerFactory"></param>
/// <param name="dataHandlerPool">The <see cref="IDataHandlerPool"/></param>
/// <param name="gBaseColumnFactory"></param>
public GBaseTable(IFileHandlerFactory fileHandlerFactory, IDataHandlerPool dataHandlerPool, IGBaseColumnFactory gBaseColumnFactory)
{ {
_fileHandler = fileHandlerFactory.Create(); _fileHandler = fileHandlerFactory.Create();
_dataHandlerPool = dataHandlerPool;
_gBaseColumnFactory = gBaseColumnFactory; _gBaseColumnFactory = gBaseColumnFactory;
Columns = new List<IGBaseColumn>(); Columns = new List<IGBaseColumn>();
Entries = new List<object>(); Entries = new List<T>();
} }
@ -47,7 +53,7 @@ namespace GBase
/// <summary> /// <summary>
/// The name of this <see cref="IGBaseTable"/> /// The name of this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
public string Name { get; private set; } public string FolderName { get; private set; }
/// <summary> /// <summary>
/// The <see cref="IGBaseColumn"/>s of this <see cref="IGBaseTable"/> /// The <see cref="IGBaseColumn"/>s of this <see cref="IGBaseTable"/>
@ -57,25 +63,22 @@ namespace GBase
/// <summary> /// <summary>
/// The entries of this <see cref="IGBaseTable"/> /// The entries of this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
public List<object> Entries { get; } public List<T> Entries { get; }
/// <summary> /// <summary>
/// Initialize this <see cref="IGBase"/> /// Initialize this <see cref="IGBase"/>
/// </summary> /// </summary>
/// <param name="type">The <see cref="System.Type"/> of the class that this <see cref="IGBaseTable"/> represents</param> /// <param name="type">The <see cref="System.Type"/> of the class that this <see cref="IGBaseTable"/> represents</param>
/// <param name="name">The name of this <see cref="IGBaseTable"/></param>
/// <param name="databasePath">The path to the database files</param> /// <param name="databasePath">The path to the database files</param>
/// <param name="folderName"></param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the asynchronous operation</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the asynchronous operation</param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
public async Task<bool> Init(Type type, string name, string databasePath, CancellationToken cancellationToken) public async Task<bool> Init(Type type, string databasePath, string folderName, CancellationToken cancellationToken)
{ {
Type = type; Type = type;
Name = name; FolderName = folderName;
await _fileHandler.Init(databasePath, cancellationToken);
string fileName = $"{name}.{GBase.GBASE_TABLE_FILE_EXTENSION}";
string path = Path.Combine(databasePath, fileName);
await _fileHandler.Init(path, cancellationToken);
//TODO: Init columns list depending on GBaseColumnAttributes set for this GBaseTable //TODO: Init columns list depending on GBaseColumnAttributes set for this GBaseTable
foreach (var property in type.GetProperties()) foreach (var property in type.GetProperties())
@ -84,7 +87,7 @@ namespace GBase
if (gBaseColumnAttribute == null) if (gBaseColumnAttribute == null)
continue; continue;
IGBaseColumn gBaseColumn = _gBaseColumnFactory.Create(); IGBaseColumn gBaseColumn = _gBaseColumnFactory.Create(property.Name);
AddColumn(gBaseColumn); AddColumn(gBaseColumn);
} }
@ -96,7 +99,7 @@ namespace GBase
/// </summary> /// </summary>
/// <param name="column">The given <see cref="IGBaseColumn"/></param> /// <param name="column">The given <see cref="IGBaseColumn"/></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
public bool AddColumn(IGBaseColumn column) public bool AddColumn(IGBaseColumn column) //TODO: if a column is added, it has to be added to every entry file as well
{ {
if (Columns.Contains(column)) if (Columns.Contains(column))
return false; return false;
@ -110,7 +113,7 @@ namespace GBase
/// </summary> /// </summary>
/// <param name="column">The given <see cref="IGBaseColumn"/></param> /// <param name="column">The given <see cref="IGBaseColumn"/></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
public bool RemoveColumn(IGBaseColumn column) public bool RemoveColumn(IGBaseColumn column) //TODO: if a column is removed, it has to be removed from every entry file as well
{ {
if (!Columns.Contains(column)) if (!Columns.Contains(column))
return false; return false;
@ -122,11 +125,15 @@ namespace GBase
/// Add an entry that implements <see cref="INotifyGBaseEntryChanged"/> to this <see cref="IGBaseTable"/> /// Add an entry that implements <see cref="INotifyGBaseEntryChanged"/> to this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
/// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param> /// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <param name="cancellationToken"></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
public bool AddEntry(INotifyGBaseEntryChanged entry) //TODO: Write to file public async Task<bool> AddEntry(T entry, CancellationToken cancellationToken)
{ {
Entries.Add(entry); Entries.Add(entry);
entry.GBaseEntryChanged += OnGBaseEntryChanged;
using IGBaseFile file = _fileHandler.CreateEntryFile(entry, this);
IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
await dataHandler.AddEntry(entry, this, file.File, cancellationToken);
return true; return true;
} }
@ -136,41 +143,35 @@ namespace GBase
/// </summary> /// </summary>
/// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param> /// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
public bool RemoveEntry(INotifyGBaseEntryChanged entry) //TODO: remove from file public async Task<bool> RemoveEntry(T entry)
{ {
if (!Entries.Contains(entry)) if (!Entries.Contains(entry))
return false; return false;
entry.GBaseEntryChanged -= OnGBaseEntryChanged; await _fileHandler.DeleteEntryFile(entry);
return Entries.Remove(entry); return Entries.Remove(entry);
} }
/// <summary> public async Task SetValue<TProperty>(T entry, string propertyName, TProperty value, CancellationToken cancellationToken)
/// Modify the property of a given entry with the given value
/// </summary>
/// <param name="entry">The entry</param>
/// <param name="propertyName">The name of the property</param>
/// <param name="value">The new value to set</param>
/// <returns>True if successful, false if not</returns>
private bool ModifyEntry(object entry, string propertyName, object value) //TODO: Write to file
{ {
//don't need to change value of property in `Entries` list, the instance is saved there, any property change is already changed there as well using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
return true; IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, CancellationToken.None);
await dataHandler.SetValue<T, TProperty>(file.File, propertyName, value, cancellationToken);
} }
/// <summary> public async Task<TProperty> GetValue<TProperty>(T entry, string propertyName, CancellationToken cancellationToken)
/// A <see cref="IGBase"/> entry changed
/// </summary>
/// <param name="entry">The entry (sender)</param>
/// <param name="args">The <see cref="GBaseEntryChangedEventArgs"/></param>
private void OnGBaseEntryChanged(object entry, GBaseEntryChangedEventArgs args)
{ {
//TODO: Might change, depending on #23 using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
bool success = ModifyEntry(entry, args.ColumnName, args.Value); IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, CancellationToken.None);
return await dataHandler.GetValue<T, TProperty>(file.File, propertyName, cancellationToken);
}
if (!success) public async Task<IEnumerable<TProperty>> GetValues<TProperty>(T entry, string propertyName, CancellationToken cancellationToken)
throw new Exception("Failed to handle EntryChanged"); //TODO: Decide what to do here {
using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, CancellationToken.None);
return await dataHandler.GetValues<T, TProperty>(file.File, propertyName, cancellationToken);
} }
/// <summary> /// <summary>
@ -180,6 +181,7 @@ namespace GBase
public async ValueTask DisposeAsync() public async ValueTask DisposeAsync()
{ {
await _fileHandler.DisposeAsync(); await _fileHandler.DisposeAsync();
await _dataHandlerPool.DisposeAsync();
foreach (var column in Columns) foreach (var column in Columns)
{ {
@ -188,9 +190,9 @@ namespace GBase
Columns.Clear(); Columns.Clear();
foreach (var entry in Entries.OfType<INotifyGBaseEntryChanged>().ToList()) foreach (var entry in Entries.ToList())
{ {
RemoveEntry(entry); await RemoveEntry(entry);
} }
Entries.Clear(); Entries.Clear();

@ -7,8 +7,13 @@ using GBase.DataHandling;
using GBase.DataHandling.Cache; using GBase.DataHandling.Cache;
using GBase.DataHandling.Cache.Factories; using GBase.DataHandling.Cache.Factories;
using GBase.DataHandling.Factories; using GBase.DataHandling.Factories;
using GBase.DataHandling.Factories.Pool;
using GBase.DataHandling.Pool;
using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Pool;
using GBase.Interfaces.DataHandling.Xml; using GBase.Interfaces.DataHandling.Xml;
using GBase.Interfaces.DataHandling.Xml.Cache; using GBase.Interfaces.DataHandling.Xml.Cache;
using LightweightIocContainer;
using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Installers; using LightweightIocContainer.Interfaces.Installers;
@ -22,16 +27,22 @@ namespace GBase.Installers
/// <inheritdoc /> /// <inheritdoc />
public void Install(IIocContainer container) public void Install(IIocContainer container)
{ {
container.Register<IXmlDataHandler, XmlDataHandler>(); container.Register<IDataHandler, IXmlDataHandler, XmlDataHandler>();
container.Register<IXmlDataReader, XmlDataReader>(); container.Register<IDataReader, IXmlDataReader, XmlDataReader>();
container.Register<IXmlDataWriter, XmlDataWriter>(); container.Register<IDataWriter, IXmlDataWriter, XmlDataWriter>();
//cache //cache
container.Register<IXmlDataHandlerCache, XmlDataHandlerCache>(); container.Register<IXmlDataHandlerCache, XmlDataHandlerCache>();
container.Register<IXmlDataHandlerCacheEntry, XmlDataHandlerCacheEntry>(); container.Register<IXmlDataHandlerCacheEntry, XmlDataHandlerCacheEntry>();
container.Register<IXmlDataHandlerCachePropertyEntry, XmlDataHandlerCachePropertyEntry>(); container.Register<IXmlDataHandlerCachePropertyEntry, XmlDataHandlerCachePropertyEntry>();
//pool
container.Register<IDataHandlerPool, DataHandlerPool>(Lifestyle.Singleton).WithParameters(10);
container.Register<IPoolItemFactory, PoolItemFactory>();
container.RegisterFactory<IPoolRequestFactory>();
//factories //factories
container.RegisterFactory<IDataHandlerFactory>();
container.RegisterFactory<IXmlDataHandlerFactory>(); container.RegisterFactory<IXmlDataHandlerFactory>();
container.RegisterFactory<IXmlDataReaderFactory>(); container.RegisterFactory<IXmlDataReaderFactory>();
container.RegisterFactory<IXmlDataWriterFactory>(); container.RegisterFactory<IXmlDataWriterFactory>();

@ -19,12 +19,11 @@ namespace GBase.Installers
public void Install(IIocContainer container) public void Install(IIocContainer container)
{ {
container.Register<IGBase, GBase>(); container.Register<IGBase, GBase>();
container.Register<IGBaseTable, GBaseTable>();
container.Register<IGBaseColumn, GBaseColumn>(); container.Register<IGBaseColumn, GBaseColumn>();
//factories //factories
container.RegisterFactory<IGBaseFactory>(); container.RegisterFactory<IGBaseFactory>();
container.RegisterFactory<IGBaseTableFactory>(); container.Register<IGBaseTableFactory, GBaseTableFactory>(); //TODO: Once LightweightIocContainer can handle open generic registrations this can be changed back again
container.RegisterFactory<IGBaseColumnFactory>(); container.RegisterFactory<IGBaseColumnFactory>();
} }
} }

@ -4,6 +4,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace GBase.Interfaces.DataHandling.Cache namespace GBase.Interfaces.DataHandling.Cache
@ -39,8 +41,10 @@ namespace GBase.Interfaces.DataHandling.Cache
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="cancellationToken"></param>
/// <returns>An <see cref="IEnumerable{T}"/> with all the values for the property</returns> /// <returns>An <see cref="IEnumerable{T}"/> with all the values for the property</returns>
Task<IEnumerable<TProperty>> TryGetValues<T, TProperty>(string propertyName); Task<IEnumerable<TProperty>> TryGetValues<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken);
} }
} }

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -12,52 +13,63 @@ namespace GBase.Interfaces.DataHandling
/// <summary> /// <summary>
/// Interface for data handlers to implement /// Interface for data handlers to implement
/// </summary> /// </summary>
public interface IDataHandler : IAsyncDisposable public interface IDataHandler
{ {
/// <summary> /// <summary>
/// Initialize the <see cref="IDataHandler"/> /// Initialize the <see cref="IDataHandler"/>
/// </summary> /// </summary>
/// <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param> /// <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param>
/// <returns>Returns true if successful, false if not</returns> /// <returns>Returns true if successful, false if not</returns>
Task<bool> Init(bool overwrite, CancellationToken cancellationToken); bool Init(bool overwrite);
Task<bool> AddEntry<T>(T entry, IGBaseTable table, FileStream entryFile, CancellationToken cancellationToken);
Task<bool> RemoveEntry<T>(T entry);
/// <summary> /// <summary>
/// Set the value for the given property /// Set the value for the given property
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="entryFile"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param> /// <param name="value">The value to set</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns> /// <returns>A <see cref="Task"/> to await</returns>
Task SetValue<T, TProperty>(string propertyName, TProperty value); Task SetValue<T, TProperty>(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Remove the value for the given property /// Remove the value for the given property
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="entryFile"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param> /// <param name="value">The value to set</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns> /// <returns>A <see cref="Task"/> to await</returns>
Task RemoveValue<T, TProperty>(string propertyName, TProperty value); Task RemoveValue<T, TProperty>(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Get the value for the given property, if multiple values are set the first is returned /// Get the value for the given property, if multiple values are set the first is returned
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="cancellationToken"></param>
/// <returns>The value for the given property</returns> /// <returns>The value for the given property</returns>
Task<TProperty> GetValue<T, TProperty>(string propertyName); Task<TProperty> GetValue<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Get all the values that are set for the given property /// Get all the values that are set for the given property
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="cancellationToken"></param>
/// <returns>An <see cref="IEnumerable{T}"/> with all the values for the property</returns> /// <returns>An <see cref="IEnumerable{T}"/> with all the values for the property</returns>
Task<IEnumerable<TProperty>> GetValues<T, TProperty>(string propertyName); Task<IEnumerable<TProperty>> GetValues<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken);
} }
} }

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -12,22 +13,17 @@ namespace GBase.Interfaces.DataHandling
/// <summary> /// <summary>
/// Interface for data readers to implement /// Interface for data readers to implement
/// </summary> /// </summary>
public interface IDataReader : IAsyncDisposable public interface IDataReader
{ {
/// <summary>
/// Initialize the <see cref="IDataReader"/>
/// </summary>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param>
/// <returns>Returns true if successful, false if not</returns>
Task<bool> Init(CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Read the data of a property /// Read the data of a property
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/></typeparam> /// <typeparam name="T">The <see cref="Type"/></typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="cancellationToken"></param>
/// <returns>The data of the given property, null if no data found</returns> /// <returns>The data of the given property, null if no data found</returns>
Task<IEnumerable<TProperty>> Read<T, TProperty>(string propertyName); Task<IEnumerable<TProperty>> Read<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken);
} }
} }

@ -3,6 +3,7 @@
// Copyright(c) 2020 SimonG. All Rights Reserved. // Copyright(c) 2020 SimonG. All Rights Reserved.
using System; using System;
using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -11,34 +12,53 @@ namespace GBase.Interfaces.DataHandling
/// <summary> /// <summary>
/// Interface for data writers to implement /// Interface for data writers to implement
/// </summary> /// </summary>
public interface IDataWriter : IAsyncDisposable public interface IDataWriter
{ {
/// <summary> /// <summary>
/// Initialize the <see cref="IDataWriter"/> /// Initialize the <see cref="IDataWriter"/>
/// </summary> /// </summary>
/// <param name="file"></param>
/// <param name="rootElementName"></param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param>
/// <returns>Returns true if successful, false if not</returns> /// <returns>Returns true if successful, false if not</returns>
Task<bool> Init(CancellationToken cancellationToken); Task<bool> InitFile(FileStream file, string rootElementName, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Write the data of a property /// Write the data of a property
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/></typeparam> /// <typeparam name="T">The <see cref="Type"/></typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="value">The value of the property</param> /// <param name="value">The value of the property</param>
/// <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param> /// <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns> /// <returns>A <see cref="Task"/> to await</returns>
Task Write<T, TProperty>(string propertyName, string value, bool overwrite); Task Write<T, TProperty>(FileStream file, string propertyName, string value, bool overwrite, CancellationToken cancellationToken);
/// <summary>
/// Write the data of a property
/// </summary>
/// <typeparam name="T">The <see cref="Type"/></typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param>
/// <param name="value">The value of the property</param>
/// <param name="propertyType"></param>
/// <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns>
Task Write<T>(FileStream file, string propertyName, string value, Type propertyType, bool overwrite, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Remove the value for the given property /// Remove the value for the given property
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param> /// <param name="value">The value to set</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns> /// <returns>A <see cref="Task"/> to await</returns>
Task Remove<T, TProperty>(string propertyName, string value); Task Remove<T, TProperty>(FileStream file, string propertyName, string value, CancellationToken cancellationToken);
} }
} }

@ -0,0 +1,15 @@
// Author: Simon Gockner
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace GBase.Interfaces.DataHandling.Pool
{
public interface IDataHandlerPool : IAsyncDisposable
{
Task<IDataHandler> RequestDataHandler(object requester, bool overwrite, CancellationToken cancellationToken);
}
}

@ -0,0 +1,12 @@
// Author: Simon Gockner
// Created: 2020-09-19
// Copyright(c) 2020 SimonG. All Rights Reserved.
namespace GBase.Interfaces.DataHandling.Pool
{
public interface IPoolItem<T>
{
T Item { get; }
bool InUse { get; set; }
}
}

@ -0,0 +1,14 @@
// Author: Simon Gockner
// Created: 2020-09-19
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using System.Threading.Tasks;
namespace GBase.Interfaces.DataHandling.Pool
{
public interface IPoolRequest
{
object Requester { get; }
}
}

@ -3,7 +3,6 @@
// Copyright(c) 2020 SimonG. All Rights Reserved. // Copyright(c) 2020 SimonG. All Rights Reserved.
using System; using System;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -22,42 +21,10 @@ namespace GBase.Interfaces.FileHandling
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
Task<bool> Init(string path, CancellationToken cancellationToken); Task<bool> Init(string path, CancellationToken cancellationToken);
/// <summary> IGBaseFile CreateEntryFile<T>(T entry, IGBaseTable table);
/// Set the value for the given property
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param>
/// <returns>A <see cref="Task"/> to await</returns>
Task SetValue<T, TProperty>(string propertyName, TProperty value);
/// <summary> Task<bool> DeleteEntryFile<T>(T entry);
/// Remove the value for the given property
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param>
/// <returns>A <see cref="Task"/> to await</returns>
Task RemoveValue<T, TProperty>(string propertyName, TProperty value);
/// <summary> Task<IGBaseFile> RequestEntryFile<T>(T entry);
/// Get the value for the given property, if multiple values are set the first is returned
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="propertyName">The name of the property</param>
/// <returns>The value for the given property</returns>
Task<TProperty> GetValue<T, TProperty>(string propertyName);
/// <summary>
/// Get all the values that are set for the given property
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="propertyName">The name of the property</param>
/// <returns>An <see cref="IEnumerable{T}"/> with all the values for the property</returns>
Task<IEnumerable<TProperty>> GetValues<T, TProperty>(string propertyName);
} }
} }

@ -0,0 +1,19 @@
// Author: Gockner, Simon
// Created: 2020-11-10
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using System.IO;
namespace GBase.Interfaces.FileHandling
{
public interface IGBaseFile : IDisposable
{
object Entry { get; }
FileStream File { get; }
string FilePath { get; }
bool InUse { get; }
IGBaseFile UseFile();
}
}

@ -48,11 +48,19 @@ namespace GBase.Interfaces
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
bool AddTable(IGBaseTable table); bool AddTable(IGBaseTable table);
IGBaseTable<T> GetTable<T>();
/// <summary> /// <summary>
/// Removes a given <see cref="IGBaseTable"/> from this <see cref="IGBase"/> /// Removes a given <see cref="IGBaseTable"/> from this <see cref="IGBase"/>
/// </summary> /// </summary>
/// <param name="table">The given <see cref="IGBaseTable"/></param> /// <param name="table">The given <see cref="IGBaseTable"/></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
bool RemoveTable(IGBaseTable table); bool RemoveTable(IGBaseTable table);
Task<bool> AddEntry<T>(T entry, CancellationToken cancellationToken);
Task SetValue<T, TProperty>(T entry, string propertyName, TProperty value, CancellationToken cancellationToken);
Task<TProperty> GetValue<T, TProperty>(T entry, string propertyName, CancellationToken cancellationToken);
Task<IEnumerable<TProperty>> GetValues<T, TProperty>(T entry, string propertyName, CancellationToken cancellationToken);
} }
} }

@ -11,6 +11,6 @@ namespace GBase.Interfaces
/// </summary> /// </summary>
public interface IGBaseColumn : IAsyncDisposable //TODO: Make column generic (generic type is type of the value of the column?)? public interface IGBaseColumn : IAsyncDisposable //TODO: Make column generic (generic type is type of the value of the column?)?
{ {
string Name { get; }
} }
} }

@ -10,6 +10,38 @@ using GBase.Api;
namespace GBase.Interfaces namespace GBase.Interfaces
{ {
public interface IGBaseTable<T> : IGBaseTable
{
/// <summary>
/// The entries of this <see cref="IGBaseTable"/>
/// </summary>
List<T> Entries { get; }
/// <summary>
/// Add an entry that implements <see cref="INotifyGBaseEntryChanged"/> to this <see cref="IGBaseTable"/>
/// </summary>
/// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <param name="cancellationToken"></param>
/// <returns>True if successful, false if not</returns>
Task<bool> AddEntry(T entry, CancellationToken cancellationToken);
//T GetEntry(T entry); //TODO: This doesn't make sense... (passing instance of T to get the same instance back...)
/// <summary>
/// Remove an entry that implements <see cref="INotifyGBaseEntryChanged"/> from this <see cref="IGBaseTable"/>
/// </summary>
/// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <returns>True if successful, false if not</returns>
Task<bool> RemoveEntry(T entry);
Task SetValue<TProperty>(T entry, string propertyName, TProperty value, CancellationToken cancellationToken);
Task<TProperty> GetValue<TProperty>(T entry, string propertyName, CancellationToken cancellationToken);
Task<IEnumerable<TProperty>> GetValues<TProperty>(T entry, string propertyName, CancellationToken cancellationToken);
}
/// <summary> /// <summary>
/// A <see cref="IGBase"/> table /// A <see cref="IGBase"/> table
/// </summary> /// </summary>
@ -23,27 +55,23 @@ namespace GBase.Interfaces
/// <summary> /// <summary>
/// The name of this <see cref="IGBaseTable"/> /// The name of this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
string Name { get; } string FolderName { get; }
/// <summary> /// <summary>
/// The <see cref="IGBaseColumn"/>s of this <see cref="IGBaseTable"/> /// The <see cref="IGBaseColumn"/>s of this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
List<IGBaseColumn> Columns { get; } List<IGBaseColumn> Columns { get; }
/// <summary>
/// The entries of this <see cref="IGBaseTable"/>
/// </summary>
List<object> Entries { get; }
/// <summary> /// <summary>
/// Initialize this <see cref="IGBase"/> /// Initialize this <see cref="IGBase"/>
/// </summary> /// </summary>
/// <param name="type">The <see cref="System.Type"/> of the class that this <see cref="IGBaseTable"/> represents</param> /// <param name="type">The <see cref="System.Type"/> of the class that this <see cref="IGBaseTable"/> represents</param>
/// <param name="name">The name of this <see cref="IGBaseTable"/></param> /// <param name="databasePath">The path to the database files</param>
/// /// <param name="databasePath">The path to the database files</param> /// <param name="folderName"></param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the asynchronous operation</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the asynchronous operation</param>
/// ///
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
Task<bool> Init(Type type, string name, string databasePath, CancellationToken cancellationToken); Task<bool> Init(Type type, string databasePath, string folderName, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Add a given <see cref="IGBaseColumn"/> to this <see cref="IGBaseTable"/> /// Add a given <see cref="IGBaseColumn"/> to this <see cref="IGBaseTable"/>
@ -58,19 +86,5 @@ namespace GBase.Interfaces
/// <param name="column">The given <see cref="IGBaseColumn"/></param> /// <param name="column">The given <see cref="IGBaseColumn"/></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
bool RemoveColumn(IGBaseColumn column); bool RemoveColumn(IGBaseColumn column);
/// <summary>
/// Add an entry that implements <see cref="INotifyGBaseEntryChanged"/> to this <see cref="IGBaseTable"/>
/// </summary>
/// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <returns>True if successful, false if not</returns>
bool AddEntry(INotifyGBaseEntryChanged entry);
/// <summary>
/// Remove an entry that implements <see cref="INotifyGBaseEntryChanged"/> from this <see cref="IGBaseTable"/>
/// </summary>
/// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <returns>True if successful, false if not</returns>
bool RemoveEntry(INotifyGBaseEntryChanged entry);
} }
} }

@ -0,0 +1,41 @@
# GBase Structure
```md
- GBase
|
+-GBaseTable
|
|
+-GBaseTable
|
+-GBaseColumn--GBaseColumn--GBaseColumn
+-GBaseEntry
+-GBaseEntry
```
## Terminology
| GBase Terminology | C# equivalent |
|-------------------|---------------|
| GBaseTable | Type |
| GBaseColumn | Property |
| GBaseEntry | Instance |
## File Structure
```c#
public class Model
{
private readonly IGBase _gBase;
public
}
```
## Process
### StartUp
### GetValue
### SetValue

@ -3,6 +3,7 @@
// Copyright(c) 2020 SimonG. All Rights Reserved. // Copyright(c) 2020 SimonG. All Rights Reserved.
using System; using System;
using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.DataHandling; using GBase.DataHandling;
@ -27,12 +28,12 @@ namespace Test.GBase.DataHandling
Assert.Pass(); //Remove this assert.pass() if you want to run this test locally Assert.Pass(); //Remove this assert.pass() if you want to run this test locally
Mock<IXmlDataWriterFactory> dataWriterFactoryMock = new Mock<IXmlDataWriterFactory>(); Mock<IXmlDataWriterFactory> dataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
dataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())) dataWriterFactoryMock.Setup(w => w.Create())
.Returns((string path, string rootElementName) => new XmlDataWriter(path, rootElementName)); .Returns(new XmlDataWriter());
Mock<IXmlDataReaderFactory> dataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> dataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
dataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())) dataReaderFactoryMock.Setup(r => r.Create())
.Returns((string path) => new XmlDataReader(path)); .Returns(new XmlDataReader());
Mock<IXmlDataHandlerCachePropertyEntryFactory> dataHandlerCachePropertyEntryFactoryMock = new Mock<IXmlDataHandlerCachePropertyEntryFactory>(); Mock<IXmlDataHandlerCachePropertyEntryFactory> dataHandlerCachePropertyEntryFactoryMock = new Mock<IXmlDataHandlerCachePropertyEntryFactory>();
dataHandlerCachePropertyEntryFactoryMock.Setup(p => p.Create(It.IsAny<string>(), It.IsAny<object>())) dataHandlerCachePropertyEntryFactoryMock.Setup(p => p.Create(It.IsAny<string>(), It.IsAny<object>()))
@ -48,21 +49,22 @@ namespace Test.GBase.DataHandling
.Returns((IXmlDataReader xmlDataReader) => .Returns((IXmlDataReader xmlDataReader) =>
new XmlDataHandlerCache(xmlDataReader, dataHandlerCacheEntryFactoryMock.Object, dataHandlerCachePropertyEntryFactoryMock.Object)); new XmlDataHandlerCache(xmlDataReader, dataHandlerCacheEntryFactoryMock.Object, dataHandlerCachePropertyEntryFactoryMock.Object));
IXmlDataHandler xmlDataHandler = new XmlDataHandler("TestXml.xml", "Properties", dataReaderFactoryMock.Object, dataWriterFactoryMock.Object, IXmlDataHandler xmlDataHandler = new XmlDataHandler(dataReaderFactoryMock.Object, dataWriterFactoryMock.Object, dataHandlerCacheFactoryMock.Object);
dataHandlerCacheFactoryMock.Object);
xmlDataHandler.Init(false);
FileStream file = null; //FixMe: init this correctly if you want to run this test
await xmlDataHandler.Init(false, new CancellationToken());
//
//await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), TestProperty); //await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), TestProperty);
//await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), "empty"); //await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), "empty");
await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), "test"); await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(file, nameof(TestProperty), "test", new CancellationToken());
//await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), "OverwrittenString"); //await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), "OverwrittenString");
// //
await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt), 1); await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(file, nameof(TestInt), 1, new CancellationToken());
//await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt), 2); //await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt), 2);
//await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt), 3); //await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt), 3);
TestProperty = await xmlDataHandler.GetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty)); TestProperty = await xmlDataHandler.GetValue<XmlDataHandlerLocalIntegrationTest, string>(file, nameof(TestProperty), new CancellationToken());
TestInt = await xmlDataHandler.GetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt)); TestInt = await xmlDataHandler.GetValue<XmlDataHandlerLocalIntegrationTest, int>(file, nameof(TestInt), new CancellationToken());
} }
} }
} }

@ -19,104 +19,45 @@ namespace Test.GBase.DataHandling
public class XmlDataHandlerTest public class XmlDataHandlerTest
{ {
[Test] [Test]
public async Task TestInit() public void TestInit()
{ {
Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>(); Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>();
xmlDataReaderMock.Setup(r => r.Init(It.IsAny<CancellationToken>())).ReturnsAsync(true);
Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
xmlDataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())).Returns(xmlDataReaderMock.Object); xmlDataReaderFactoryMock.Setup(r => r.Create()).Returns(xmlDataReaderMock.Object);
Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>(); Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>();
xmlDataWriterMock.Setup(w => w.Init(It.IsAny<CancellationToken>())).ReturnsAsync(true);
Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
xmlDataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())).Returns(xmlDataWriterMock.Object);
Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>();
Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>();
xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object);
XmlDataHandler xmlDataHandler = new XmlDataHandler("path", "root", xmlDataReaderFactoryMock.Object,
xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
Assert.True(await xmlDataHandler.Init(false, CancellationToken.None));
}
[Test]
public async Task TestInitFailedTriedTwice()
{
Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>();
xmlDataReaderMock.Setup(r => r.Init(It.IsAny<CancellationToken>())).ReturnsAsync(true);
Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
xmlDataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())).Returns(xmlDataReaderMock.Object);
Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>();
xmlDataWriterMock.Setup(w => w.Init(It.IsAny<CancellationToken>())).ReturnsAsync(true);
Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>(); Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
xmlDataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())).Returns(xmlDataWriterMock.Object); xmlDataWriterFactoryMock.Setup(w => w.Create()).Returns(xmlDataWriterMock.Object);
Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>(); Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>();
Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>(); Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>();
xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object); xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object);
XmlDataHandler xmlDataHandler = new XmlDataHandler("path", "root", xmlDataReaderFactoryMock.Object, XmlDataHandler xmlDataHandler = new XmlDataHandler(xmlDataReaderFactoryMock.Object, xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
Assert.True(await xmlDataHandler.Init(false, CancellationToken.None)); Assert.True(xmlDataHandler.Init(false));
Assert.False(await xmlDataHandler.Init(false, CancellationToken.None));
} }
[Test] [Test]
public async Task TestInitFailedInitReaderFailed() public void TestInitFailedTriedTwice()
{ {
Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>(); Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>();
xmlDataReaderMock.Setup(r => r.Init(It.IsAny<CancellationToken>())).ReturnsAsync(false);
Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
xmlDataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())).Returns(xmlDataReaderMock.Object); xmlDataReaderFactoryMock.Setup(r => r.Create()).Returns(xmlDataReaderMock.Object);
Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>(); Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>();
xmlDataWriterMock.Setup(w => w.Init(It.IsAny<CancellationToken>())).ReturnsAsync(true);
Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
xmlDataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())).Returns(xmlDataWriterMock.Object);
Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>();
Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>();
xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object);
XmlDataHandler xmlDataHandler = new XmlDataHandler("path", "root", xmlDataReaderFactoryMock.Object,
xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
Assert.False(await xmlDataHandler.Init(false, CancellationToken.None));
}
[Test]
public async Task TestInitFailedInitWriterFailed()
{
Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>();
xmlDataReaderMock.Setup(r => r.Init(It.IsAny<CancellationToken>())).ReturnsAsync(true);
Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
xmlDataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())).Returns(xmlDataReaderMock.Object);
Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>();
xmlDataWriterMock.Setup(w => w.Init(It.IsAny<CancellationToken>())).ReturnsAsync(false);
Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>(); Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
xmlDataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())).Returns(xmlDataWriterMock.Object); xmlDataWriterFactoryMock.Setup(w => w.Create()).Returns(xmlDataWriterMock.Object);
Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>(); Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>();
Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>(); Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>();
xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object); xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object);
XmlDataHandler xmlDataHandler = new XmlDataHandler("path", "root", xmlDataReaderFactoryMock.Object, XmlDataHandler xmlDataHandler = new XmlDataHandler(xmlDataReaderFactoryMock.Object, xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
Assert.False(await xmlDataHandler.Init(false, CancellationToken.None)); Assert.True(xmlDataHandler.Init(false));
Assert.False(xmlDataHandler.Init(false));
} }
[Test] [Test]
@ -124,23 +65,22 @@ namespace Test.GBase.DataHandling
{ {
Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>(); Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>();
Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
xmlDataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())).Returns(xmlDataReaderMock.Object); xmlDataReaderFactoryMock.Setup(r => r.Create()).Returns(xmlDataReaderMock.Object);
Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>(); Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>();
Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>(); Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
xmlDataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())).Returns(xmlDataWriterMock.Object); xmlDataWriterFactoryMock.Setup(w => w.Create()).Returns(xmlDataWriterMock.Object);
Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>(); Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>();
Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>(); Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>();
xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object); xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object);
XmlDataHandler xmlDataHandler = new XmlDataHandler("path", "root", xmlDataReaderFactoryMock.Object, XmlDataHandler xmlDataHandler = new XmlDataHandler(xmlDataReaderFactoryMock.Object, xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
await xmlDataHandler.SetValue<XmlDataHandlerTest, string>("property", "SomeString"); await xmlDataHandler.SetValue<XmlDataHandlerTest, string>(null, "property", "SomeString", new CancellationToken());
xmlDataHandlerCacheMock.Verify(c => c.SetValue<XmlDataHandlerTest, string>("property", "SomeString", false), Times.Once); xmlDataHandlerCacheMock.Verify(c => c.SetValue<XmlDataHandlerTest, string>("property", "SomeString", false), Times.Once);
xmlDataWriterMock.Verify(w => w.Write<XmlDataHandlerTest, string>("property", "SomeString", false), Times.Once); xmlDataWriterMock.Verify(w => w.Write<XmlDataHandlerTest, string>(null, "property", "SomeString", false, It.IsAny<CancellationToken>()), Times.Once);
} }
[Test] [Test]
@ -148,24 +88,23 @@ namespace Test.GBase.DataHandling
{ {
Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>(); Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>();
Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
xmlDataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())).Returns(xmlDataReaderMock.Object); xmlDataReaderFactoryMock.Setup(r => r.Create()).Returns(xmlDataReaderMock.Object);
Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>(); Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>();
Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>(); Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
xmlDataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())).Returns(xmlDataWriterMock.Object); xmlDataWriterFactoryMock.Setup(w => w.Create()).Returns(xmlDataWriterMock.Object);
Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>(); Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>();
Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>(); Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>();
xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object); xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object);
XmlDataHandler xmlDataHandler = new XmlDataHandler("path", "root", xmlDataReaderFactoryMock.Object, XmlDataHandler xmlDataHandler = new XmlDataHandler(xmlDataReaderFactoryMock.Object, xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
List<string> stringList = new List<string>() {"string", "secondString", "thirdString"}; List<string> stringList = new List<string>() {"string", "secondString", "thirdString"};
await xmlDataHandler.SetValue<XmlDataHandlerTest, List<string>>("property", stringList); await xmlDataHandler.SetValue<XmlDataHandlerTest, List<string>>(null, "property", stringList, new CancellationToken());
xmlDataHandlerCacheMock.Verify(c => c.SetValue<XmlDataHandlerTest, List<string>>("property", stringList, false), Times.Once); xmlDataHandlerCacheMock.Verify(c => c.SetValue<XmlDataHandlerTest, List<string>>("property", stringList, false), Times.Once);
xmlDataWriterMock.Verify(w => w.Write<XmlDataHandlerTest, List<string>>("property", $"{stringList[0]},{stringList[1]},{stringList[2]}", false), Times.Once); xmlDataWriterMock.Verify(w => w.Write<XmlDataHandlerTest, List<string>>(null, "property", $"{stringList[0]},{stringList[1]},{stringList[2]}",false, It.IsAny<CancellationToken>()), Times.Once);
} }
[Test] [Test]
@ -173,23 +112,22 @@ namespace Test.GBase.DataHandling
{ {
Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>(); Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>();
Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
xmlDataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())).Returns(xmlDataReaderMock.Object); xmlDataReaderFactoryMock.Setup(r => r.Create()).Returns(xmlDataReaderMock.Object);
Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>(); Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>();
Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>(); Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
xmlDataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())).Returns(xmlDataWriterMock.Object); xmlDataWriterFactoryMock.Setup(w => w.Create()).Returns(xmlDataWriterMock.Object);
Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>(); Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>();
Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>(); Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>();
xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object); xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object);
XmlDataHandler xmlDataHandler = new XmlDataHandler("path", "root", xmlDataReaderFactoryMock.Object, XmlDataHandler xmlDataHandler = new XmlDataHandler(xmlDataReaderFactoryMock.Object, xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
await xmlDataHandler.SetValue<XmlDataHandlerTest, string>("property", null); await xmlDataHandler.SetValue<XmlDataHandlerTest, string>(null, "property", null, new CancellationToken());
xmlDataHandlerCacheMock.Verify(c => c.SetValue<It.IsValueType, It.IsValueType>(It.IsAny<string>(), It.IsAny<It.IsValueType>(), It.IsAny<bool>()), Times.Never); xmlDataHandlerCacheMock.Verify(c => c.SetValue<It.IsValueType, It.IsValueType>(It.IsAny<string>(), It.IsAny<It.IsValueType>(), It.IsAny<bool>()), Times.Never);
xmlDataWriterMock.Verify(w => w.Write<It.IsValueType, It.IsValueType>(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()), Times.Never); xmlDataWriterMock.Verify(w => w.Write<It.IsValueType, It.IsValueType>(null, It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
} }
[Test] [Test]
@ -197,23 +135,22 @@ namespace Test.GBase.DataHandling
{ {
Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>(); Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>();
Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
xmlDataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())).Returns(xmlDataReaderMock.Object); xmlDataReaderFactoryMock.Setup(r => r.Create()).Returns(xmlDataReaderMock.Object);
Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>(); Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>();
Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>(); Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
xmlDataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())).Returns(xmlDataWriterMock.Object); xmlDataWriterFactoryMock.Setup(w => w.Create()).Returns(xmlDataWriterMock.Object);
Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>(); Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>();
Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>(); Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>();
xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object); xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object);
XmlDataHandler xmlDataHandler = new XmlDataHandler("path", "root", xmlDataReaderFactoryMock.Object, XmlDataHandler xmlDataHandler = new XmlDataHandler(xmlDataReaderFactoryMock.Object, xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
await xmlDataHandler.RemoveValue<XmlDataHandlerTest, string>("property", "SomeString"); await xmlDataHandler.RemoveValue<XmlDataHandlerTest, string>(null, "property", "SomeString", new CancellationToken());
xmlDataHandlerCacheMock.Verify(c => c.TryRemoveValue<XmlDataHandlerTest, string>("property", "SomeString"), Times.Once); xmlDataHandlerCacheMock.Verify(c => c.TryRemoveValue<XmlDataHandlerTest, string>("property", "SomeString"), Times.Once);
xmlDataWriterMock.Verify(w => w.Remove<XmlDataHandlerTest, string>("property", "SomeString"), Times.Once); xmlDataWriterMock.Verify(w => w.Remove<XmlDataHandlerTest, string>(null, "property", "SomeString", It.IsAny<CancellationToken>()), Times.Once);
} }
[Test] [Test]
@ -221,24 +158,23 @@ namespace Test.GBase.DataHandling
{ {
Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>(); Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>();
Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
xmlDataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())).Returns(xmlDataReaderMock.Object); xmlDataReaderFactoryMock.Setup(r => r.Create()).Returns(xmlDataReaderMock.Object);
Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>(); Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>();
Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>(); Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
xmlDataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())).Returns(xmlDataWriterMock.Object); xmlDataWriterFactoryMock.Setup(w => w.Create()).Returns(xmlDataWriterMock.Object);
Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>(); Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>();
Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>(); Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>();
xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object); xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object);
XmlDataHandler xmlDataHandler = new XmlDataHandler("path", "root", xmlDataReaderFactoryMock.Object, XmlDataHandler xmlDataHandler = new XmlDataHandler(xmlDataReaderFactoryMock.Object, xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
List<string> stringList = new List<string>() { "string", "secondString", "thirdString" }; List<string> stringList = new List<string>() { "string", "secondString", "thirdString" };
await xmlDataHandler.RemoveValue<XmlDataHandlerTest, List<string>>("property", stringList); await xmlDataHandler.RemoveValue<XmlDataHandlerTest, List<string>>(null, "property", stringList, new CancellationToken());
xmlDataHandlerCacheMock.Verify(c => c.TryRemoveValue<XmlDataHandlerTest, List<string>>("property", stringList), Times.Once); xmlDataHandlerCacheMock.Verify(c => c.TryRemoveValue<XmlDataHandlerTest, List<string>>("property", stringList), Times.Once);
xmlDataWriterMock.Verify(w => w.Remove<XmlDataHandlerTest, List<string>>("property", $"{stringList[0]},{stringList[1]},{stringList[2]}"), Times.Once); xmlDataWriterMock.Verify(w => w.Remove<XmlDataHandlerTest, List<string>>(null, "property", $"{stringList[0]},{stringList[1]},{stringList[2]}", It.IsAny<CancellationToken>()), Times.Once);
} }
[Test] [Test]
@ -246,23 +182,22 @@ namespace Test.GBase.DataHandling
{ {
Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>(); Mock<IXmlDataReader> xmlDataReaderMock = new Mock<IXmlDataReader>();
Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
xmlDataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())).Returns(xmlDataReaderMock.Object); xmlDataReaderFactoryMock.Setup(r => r.Create()).Returns(xmlDataReaderMock.Object);
Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>(); Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>();
Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>(); Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
xmlDataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())).Returns(xmlDataWriterMock.Object); xmlDataWriterFactoryMock.Setup(w => w.Create()).Returns(xmlDataWriterMock.Object);
Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>(); Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>();
Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>(); Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>();
xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object); xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object);
XmlDataHandler xmlDataHandler = new XmlDataHandler("path", "root", xmlDataReaderFactoryMock.Object, XmlDataHandler xmlDataHandler = new XmlDataHandler(xmlDataReaderFactoryMock.Object, xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
await xmlDataHandler.RemoveValue<XmlDataHandlerTest, string>("property", null); await xmlDataHandler.RemoveValue<XmlDataHandlerTest, string>(null, "property", null, new CancellationToken());
xmlDataHandlerCacheMock.Verify(c => c.TryRemoveValue<It.IsValueType, It.IsValueType>(It.IsAny<string>(), It.IsAny<It.IsValueType>()), Times.Never); xmlDataHandlerCacheMock.Verify(c => c.TryRemoveValue<It.IsValueType, It.IsValueType>(It.IsAny<string>(), It.IsAny<It.IsValueType>()), Times.Never);
xmlDataWriterMock.Verify(w => w.Remove<It.IsValueType, It.IsValueType>(It.IsAny<string>(), It.IsAny<string>()), Times.Never); xmlDataWriterMock.Verify(w => w.Remove<It.IsValueType, It.IsValueType>(null, It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Never);
} }
[Test] [Test]
@ -274,18 +209,17 @@ namespace Test.GBase.DataHandling
//xmlDataReaderMock.Setup(r => r.Read<XmlDataHandlerTest, string>("property")).ReturnsAsync<List<string>>(values); //xmlDataReaderMock.Setup(r => r.Read<XmlDataHandlerTest, string>("property")).ReturnsAsync<List<string>>(values);
Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
xmlDataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())).Returns(xmlDataReaderMock.Object); xmlDataReaderFactoryMock.Setup(r => r.Create()).Returns(xmlDataReaderMock.Object);
Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>(); Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>();
Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>(); Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
xmlDataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())).Returns(xmlDataWriterMock.Object); xmlDataWriterFactoryMock.Setup(w => w.Create()).Returns(xmlDataWriterMock.Object);
Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>(); Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>();
Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>(); Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>();
xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object); xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object);
XmlDataHandler xmlDataHandler = new XmlDataHandler("path", "root", xmlDataReaderFactoryMock.Object, XmlDataHandler xmlDataHandler = new XmlDataHandler(xmlDataReaderFactoryMock.Object, xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
} }
[Test] [Test]
@ -297,20 +231,19 @@ namespace Test.GBase.DataHandling
//xmlDataReaderMock.Setup(r => r.Read<XmlDataHandlerTest, string>("property")).ReturnsAsync<List<string>>(values); //xmlDataReaderMock.Setup(r => r.Read<XmlDataHandlerTest, string>("property")).ReturnsAsync<List<string>>(values);
Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> xmlDataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
xmlDataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())).Returns(xmlDataReaderMock.Object); xmlDataReaderFactoryMock.Setup(r => r.Create()).Returns(xmlDataReaderMock.Object);
Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>(); Mock<IXmlDataWriter> xmlDataWriterMock = new Mock<IXmlDataWriter>();
Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>(); Mock<IXmlDataWriterFactory> xmlDataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
xmlDataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())).Returns(xmlDataWriterMock.Object); xmlDataWriterFactoryMock.Setup(w => w.Create()).Returns(xmlDataWriterMock.Object);
Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>(); Mock<IXmlDataHandlerCache> xmlDataHandlerCacheMock = new Mock<IXmlDataHandlerCache>();
Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>(); Mock<IXmlDataHandlerCacheFactory> xmlDataHandlerCacheFactoryMock = new Mock<IXmlDataHandlerCacheFactory>();
xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object); xmlDataHandlerCacheFactoryMock.Setup(c => c.Create(It.IsAny<IXmlDataReader>())).Returns(xmlDataHandlerCacheMock.Object);
XmlDataHandler xmlDataHandler = new XmlDataHandler("path", "root", xmlDataReaderFactoryMock.Object, XmlDataHandler xmlDataHandler = new XmlDataHandler(xmlDataReaderFactoryMock.Object, xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
xmlDataWriterFactoryMock.Object, xmlDataHandlerCacheFactoryMock.Object);
IEnumerable<List<string>> readValues = await xmlDataHandler.GetValues<XmlDataHandlerTest, List<string>>("property"); IEnumerable<List<string>> readValues = await xmlDataHandler.GetValues<XmlDataHandlerTest, List<string>>(null, "property", new CancellationToken());
} }
} }
} }

@ -0,0 +1,56 @@
// Author: Gockner, Simon
// Created: 2020-11-11
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System.Threading;
using System.Threading.Tasks;
using GBase.Factories;
using GBase.Installers;
using LightweightIocContainer;
using LightweightIocContainer.Interfaces;
using NUnit.Framework;
namespace Test.GBase.GBaseIntegrationTest
{
[TestFixture]
public class GBaseIntegrationTest
{
private CancellationTokenSource _cancellationTokenSource;
private IIocContainer _iocContainer;
[SetUp]
public void SetUp()
{
_cancellationTokenSource = new CancellationTokenSource();
_iocContainer = new IocContainer();
_iocContainer.Install(new GBaseInstaller(),
new DataHandlingInstaller(),
new FileHandlingInstaller());
}
[TearDown]
public void TearDown()
{
_cancellationTokenSource.Dispose();
_iocContainer.Dispose();
}
[Test]
public async Task TestGBase()
{
IGBaseFactory gBaseFactory = _iocContainer.Resolve<IGBaseFactory>();
Model model = new Model(gBaseFactory);
await model.Initialize(_cancellationTokenSource.Token);
await model.AddItem(new Item("Item 1", 1), _cancellationTokenSource.Token);
await model.AddItem(new Item("Item 2", 2), _cancellationTokenSource.Token);
await model.AddItem(new Item("Item 3", 3), _cancellationTokenSource.Token);
await model.AddGroup(new Group(1), _cancellationTokenSource.Token);
await model.AddGroup(new Group(2), _cancellationTokenSource.Token);
await model.AddGroup(new Group(3), _cancellationTokenSource.Token);
}
}
}

@ -0,0 +1,26 @@
// Author: Gockner, Simon
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System.Collections.Generic;
using GBase.Attributes;
namespace Test.GBase.GBaseIntegrationTest
{
[GBaseTable("Groups")]
public class Group : IGroup
{
public Group(int key)
{
Key = key;
Items = new List<IItem>();
}
[GBaseColumn]
public int Key { get; private set; }
public List<IItem> Items { get; }
public override string ToString() => $"{Key}";
public void InitializeFromString(string @string) => Key = int.Parse(@string);
}
}

@ -0,0 +1,15 @@
// Author: Gockner, Simon
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System.Collections.Generic;
using GBase.Api;
namespace Test.GBase.GBaseIntegrationTest
{
public interface IGroup : IGBaseObject //: INotifyGBaseEntryChanged
{
int Key { get; }
List<IItem> Items { get; }
}
}

@ -0,0 +1,14 @@
// Author: Gockner, Simon
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using GBase.Api;
namespace Test.GBase.GBaseIntegrationTest
{
public interface IItem : IGBaseObject //: INotifyGBaseEntryChanged
{
string Name { get; }
int Key { get; }
}
}

@ -0,0 +1,34 @@
// Author: Gockner, Simon
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using GBase.Attributes;
namespace Test.GBase.GBaseIntegrationTest
{
[GBaseTable("Items")]
public class Item : IItem
{
public Item(string name, int key)
{
Name = name;
Key = key;
}
[GBaseColumn]
public string Name { get; private set; }
[GBaseColumn]
public int Key { get; private set; }
public override string ToString() => $"{Name}";
public void InitializeFromString(string @string)
{
string[] properties = @string.Split('/');
Key = int.Parse(properties[0]);
Name = properties[1];
}
}
}

@ -0,0 +1,54 @@
// Author: Gockner, Simon
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using GBase.Factories;
using GBase.Interfaces;
namespace Test.GBase.GBaseIntegrationTest
{
public class Model
{
private readonly IGBase _gBase;
public Model(IGBaseFactory gBaseFactory)
{
_gBase = gBaseFactory.Create(new Settings());
Items = new List<IItem>();
Groups = new List<IGroup>();
}
public List<IItem> Items { get; private set; }
public List<IGroup> Groups { get; private set; }
public async Task Initialize(CancellationToken cancellationToken)
{
await _gBase.Init("DB", Assembly.GetExecutingAssembly(), cancellationToken);
// IGBaseTable<Item> itemsTable = _gBase.GetTable<Item>();
// Items = itemsTable.Entries.Cast<IItem>().ToList();
Items = (await _gBase.GetValues<Model, Item>(this, nameof(Items), cancellationToken)).Cast<IItem>().ToList();
// IGBaseTable<Group> groupsTable = _gBase.GetTable<Group>();
// Groups = groupsTable.Entries.Cast<IGroup>().ToList();
Groups = (await _gBase.GetValues<Model, Group>(this, nameof(Groups), cancellationToken)).Cast<IGroup>().ToList();
}
public async Task AddItem(Item item, CancellationToken cancellationToken)
{
Items.Add(item);
await _gBase.AddEntry(item, cancellationToken);
}
public async Task AddGroup(Group group, CancellationToken cancellationToken)
{
Groups.Add(group);
await _gBase.AddEntry(group, cancellationToken);
}
}
}

@ -0,0 +1,15 @@
// Author: Gockner, Simon
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using System.IO;
using GBase.Interfaces.Settings;
namespace Test.GBase.GBaseIntegrationTest
{
public class Settings : IGBaseSettings
{
public string DatabasePath => Path.Combine(Environment.CurrentDirectory, "DB");
}
}

@ -7,6 +7,7 @@ using GBase;
using GBase.Factories; using GBase.Factories;
using GBase.FileHandling.Factories; using GBase.FileHandling.Factories;
using GBase.Interfaces; using GBase.Interfaces;
using GBase.Interfaces.DataHandling.Pool;
using GBase.Interfaces.FileHandling; using GBase.Interfaces.FileHandling;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
@ -23,17 +24,24 @@ namespace Test.GBase
Mock<IFileHandlerFactory> fileHandlerFactoryMock = new Mock<IFileHandlerFactory>(); Mock<IFileHandlerFactory> fileHandlerFactoryMock = new Mock<IFileHandlerFactory>();
fileHandlerFactoryMock.Setup(f => f.Create()).Returns(new Mock<IFileHandler>().Object); fileHandlerFactoryMock.Setup(f => f.Create()).Returns(new Mock<IFileHandler>().Object);
IGBaseColumn gBaseColumn = null;
Mock<IGBaseColumnFactory> gBaseColumnFactoryMock = new Mock<IGBaseColumnFactory>(); Mock<IGBaseColumnFactory> gBaseColumnFactoryMock = new Mock<IGBaseColumnFactory>();
gBaseColumnFactoryMock.Setup(c => c.Create()).Returns(new GBaseColumn()); gBaseColumnFactoryMock.Setup(c => c.Create(It.IsAny<string>()))
.Callback<string>(name => { gBaseColumn = new GBaseColumn(name); })
.Returns(gBaseColumn);
IGBaseTable table = new GBaseTable(fileHandlerFactoryMock.Object, gBaseColumnFactoryMock.Object); Mock<IDataHandlerPool> dataHandlerPoolMock = new Mock<IDataHandlerPool>();
table.Init(typeof(Foo), nameof(Foo), "", CancellationToken.None);
IGBaseTable<Foo> table = new GBaseTable<Foo>(fileHandlerFactoryMock.Object, dataHandlerPoolMock.Object, gBaseColumnFactoryMock.Object);
table.Init(typeof(Foo), "", "", CancellationToken.None);
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
Foo foo = new Foo("Test"); Foo foo = new Foo("Test");
table.AddEntry(foo); table.AddEntry(foo, cancellationTokenSource.Token);
Foo foo2 = new Foo("Test2"); Foo foo2 = new Foo("Test2");
table.AddEntry(foo2); table.AddEntry(foo2, cancellationTokenSource.Token);
foo.Name = "Foo - ex Test"; foo.Name = "Foo - ex Test";
foo2.Name = "Some Name"; foo2.Name = "Some Name";

@ -7,7 +7,7 @@ using GBase.Attributes;
namespace Test.GBase.TestClasses namespace Test.GBase.TestClasses
{ {
[GBaseTable] [GBaseTable("Foo")]
public class Foo : NotifyGBaseEntryChanged public class Foo : NotifyGBaseEntryChanged
{ {
private string _name; private string _name;

Loading…
Cancel
Save