Compare commits

..

No commits in common. 'master' and 'OldDataHandling' have entirely different histories.

  1. 14
      .drone.yml
  2. 4
      .idea/.idea.GBase/.idea/encodings.xml
  3. 2
      .idea/.idea.GBase/.idea/modules.xml
  4. 14
      .idea/.idea.GBase/.idea/riderModule.iml
  5. 11
      GBase.Api/GBase.Api.xml
  6. 18
      GBase.Api/IGBaseObject.cs
  7. 1
      GBase.sln.DotSettings
  8. 5
      GBase/Attributes/GBaseColumnAttribute.cs
  9. 5
      GBase/Attributes/GBaseTableAttribute.cs
  10. 8
      GBase/DataHandling/Cache/XmlDataHandlerCache.cs
  11. 17
      GBase/DataHandling/Exceptions/InvalidXmlFileException.cs
  12. 13
      GBase/DataHandling/Factories/IDataHandlerFactory.cs
  13. 3
      GBase/DataHandling/Factories/IXmlDataReaderFactory.cs
  14. 4
      GBase/DataHandling/Factories/IXmlDataWriterFactory.cs
  15. 13
      GBase/DataHandling/Factories/Pool/IPoolItemFactory.cs
  16. 13
      GBase/DataHandling/Factories/Pool/IPoolRequestFactory.cs
  17. 14
      GBase/DataHandling/Factories/Pool/PoolItemFactory.cs
  18. 94
      GBase/DataHandling/Pool/DataHandlerPool.cs
  19. 27
      GBase/DataHandling/Pool/PoolItem.cs
  20. 18
      GBase/DataHandling/Pool/PoolRequest.cs
  21. 83
      GBase/DataHandling/XmlDataHandler.cs
  22. 71
      GBase/DataHandling/XmlDataReader.cs
  23. 126
      GBase/DataHandling/XmlDataWriter.cs
  24. 24
      GBase/Exceptions/GenericMethodNotFoundException.cs
  25. 17
      GBase/Exceptions/InvalidKeyException.cs
  26. 27
      GBase/Exceptions/InvalidTableTypeException.cs
  27. 17
      GBase/Exceptions/MissingKeyColumnException.cs
  28. 23
      GBase/Exceptions/MissingTableException.cs
  29. 49
      GBase/Factories/GBaseTableFactory.cs
  30. 3
      GBase/Factories/IGBaseColumnFactory.cs
  31. 3
      GBase/Factories/IGBaseTableFactory.cs
  32. 17
      GBase/FileHandling/Exceptions/FileNotExistingException.cs
  33. 129
      GBase/FileHandling/FileHandler.cs
  34. 32
      GBase/FileHandling/GBaseFile.cs
  35. 66
      GBase/GBase.cs
  36. 1
      GBase/GBase.csproj
  37. 512
      GBase/GBase.xml
  38. 10
      GBase/GBaseColumn.cs
  39. 30
      GBase/GBaseKey.cs
  40. 45
      GBase/GBaseObject.cs
  41. 160
      GBase/GBaseTable.cs
  42. 19
      GBase/Helpers/Attributes.cs
  43. 24
      GBase/Helpers/Enumerables.cs
  44. 108
      GBase/Helpers/GenericMethodCaller.cs
  45. 18
      GBase/Installers/DataHandlingInstaller.cs
  46. 6
      GBase/Installers/GBaseInstaller.cs
  47. 6
      GBase/Interfaces/DataHandling/Cache/IDataHandlerCache.cs
  48. 26
      GBase/Interfaces/DataHandling/IDataHandler.cs
  49. 14
      GBase/Interfaces/DataHandling/IDataReader.cs
  50. 28
      GBase/Interfaces/DataHandling/IDataWriter.cs
  51. 15
      GBase/Interfaces/DataHandling/Pool/IDataHandlerPool.cs
  52. 16
      GBase/Interfaces/DataHandling/Pool/IPoolItem.cs
  53. 14
      GBase/Interfaces/DataHandling/Pool/IPoolRequest.cs
  54. 42
      GBase/Interfaces/FileHandling/IFileHandler.cs
  55. 19
      GBase/Interfaces/FileHandling/IGBaseFile.cs
  56. 9
      GBase/Interfaces/IGBase.cs
  57. 6
      GBase/Interfaces/IGBaseColumn.cs
  58. 29
      GBase/Interfaces/IGBaseObject.cs
  59. 62
      GBase/Interfaces/IGBaseTable.cs
  60. 41
      GBaseStructure.md
  61. 2
      README.md
  62. 27
      Test.GBase/DataHandling/XmlDataHandlerLocalIntegrationTest.cs
  63. 163
      Test.GBase/DataHandling/XmlDataHandlerTest.cs
  64. 56
      Test.GBase/GBaseIntegrationTest/GBaseIntegrationTest.cs
  65. 41
      Test.GBase/GBaseIntegrationTest/Group.cs
  66. 16
      Test.GBase/GBaseIntegrationTest/IGroup.cs
  67. 14
      Test.GBase/GBaseIntegrationTest/IItem.cs
  68. 43
      Test.GBase/GBaseIntegrationTest/Item.cs
  69. 54
      Test.GBase/GBaseIntegrationTest/Model.cs
  70. 15
      Test.GBase/GBaseIntegrationTest/Settings.cs
  71. 19
      Test.GBase/GBaseTableIntegrationTest.cs
  72. 10
      Test.GBase/Helpers/EnumerablesTest.cs
  73. 21
      Test.GBase/TestClasses/Foo.cs
  74. 1
      Test.GBase/TestClasses/IUserType.cs
  75. 10
      Test.GBase/TestClasses/UserType.cs

@ -1,14 +0,0 @@
kind: pipeline
type: docker
name: CI
steps:
- name: Build
image: mcr.microsoft.com/dotnet/sdk:5.0
commands:
- dotnet build
- name: Test
image: mcr.microsoft.com/dotnet/sdk:5.0
commands:
- dotnet test

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

@ -2,7 +2,7 @@
<project version="4"> <project version="4">
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.GBase/.idea/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.GBase/.idea/riderModule.iml" /> <module fileurl="file://$PROJECT_DIR$/.idea/.idea.GBase/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.GBase/riderModule.iml" />
</modules> </modules>
</component> </component>
</project> </project>

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="RIDER_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$USER_HOME$/.nuget/packages/microsoft.net.test.sdk/16.5.0/build/netcoreapp2.1" />
<content url="file://$USER_HOME$/.nuget/packages/microsoft.testplatform.testhost/16.5.0/build/netcoreapp2.1/x64/testhost.dll" />
<content url="file://$USER_HOME$/.nuget/packages/microsoft.testplatform.testhost/16.5.0/build/netcoreapp2.1/x64/testhost.exe" />
<content url="file://$USER_HOME$/.nuget/packages/nunit3testadapter/3.16.1/build/netcoreapp2.1/NUnit3.TestAdapter.dll" />
<content url="file://$USER_HOME$/.nuget/packages/nunit3testadapter/3.16.1/build/netcoreapp2.1/NUnit3.TestAdapter.pdb" />
<content url="file://$USER_HOME$/.nuget/packages/nunit3testadapter/3.16.1/build/netcoreapp2.1/nunit.engine.api.dll" />
<content url="file://$USER_HOME$/.nuget/packages/nunit3testadapter/3.16.1/build/netcoreapp2.1/nunit.engine.dll" />
<content url="file://$MODULE_DIR$/../.." />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -102,6 +102,17 @@
The new value The new value
</summary> </summary>
</member> </member>
<member name="T:GBase.Api.IGBaseObject">
<summary>
GBase object that allows conversion from <see cref="T:System.String"/>
</summary>
</member>
<member name="M:GBase.Api.IGBaseObject.InitializeFromString(System.String)">
<summary>
Initialize this <see cref="T:GBase.Api.IGBaseObject"/> 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.Api.INotifyGBaseEntryChanged"> <member name="T:GBase.Api.INotifyGBaseEntryChanged">
<summary> <summary>
Notify the GBase that an entry has changed Notify the GBase that an entry has changed

@ -0,0 +1,18 @@
// Author: Gockner, Simon
// Created: 2020-02-14
// Copyright(c) 2020 SimonG. All Rights Reserved.
namespace GBase.Api
{
/// <summary>
/// GBase object that allows conversion from <see cref="string"/>
/// </summary>
public interface IGBaseObject
{
/// <summary>
/// Initialize this <see cref="IGBaseObject"/> from a given <see cref="string"/>
/// </summary>
/// <param name="string">The given <see cref="string"/></param>
void InitializeFromString(string @string);
}
}

@ -2,6 +2,5 @@
<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,11 +13,6 @@ namespace GBase.Attributes
[AttributeUsage(AttributeTargets.Property)] [AttributeUsage(AttributeTargets.Property)]
public class GBaseColumnAttribute : Attribute public class GBaseColumnAttribute : Attribute
{ {
public GBaseColumnAttribute(bool isKey = false)
{
IsKey = isKey;
}
public bool IsKey { get; }
} }
} }

@ -13,11 +13,6 @@ 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,9 +4,7 @@
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;
@ -105,11 +103,9 @@ 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>(FileStream file, string propertyName, CancellationToken cancellationToken) public async Task<IEnumerable<TProperty>> TryGetValues<T, TProperty>(string propertyName)
{ {
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));
@ -118,7 +114,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>(file, propertyName, cancellationToken))?.ToList(); List<TProperty> values = (await _xmlDataReader.Read<T, TProperty>(propertyName))?.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))))

@ -1,17 +0,0 @@
// 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)
{
}
}
}

@ -1,13 +0,0 @@
// 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,7 +14,8 @@ 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(); IXmlDataReader Create(string path);
} }
} }

@ -14,7 +14,9 @@ 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(); IXmlDataWriter Create(string path, string rootElementName);
} }
} }

@ -1,13 +0,0 @@
// 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);
}
}

@ -1,13 +0,0 @@
// 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);
}
}

@ -1,14 +0,0 @@
// 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);
}
}

@ -1,94 +0,0 @@
// 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<IPoolItem<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<IPoolItem<IDataHandler>> WaitForDataHandler(object requester, CancellationToken cancellationToken)
{
IPoolItem<IDataHandler> dataHandlerItem = null;
IPoolRequest request = _poolRequestFactory.Create(requester);
while (dataHandlerItem == null)
{
if (_waitingRequesters.Contains(request) && _waitingRequesters.IndexOf(request) == 0) //request is in list and is first
{
if (_pool.Any(i => !i.InUse))
dataHandlerItem = 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 dataHandlerItem;
}
private IPoolItem<IDataHandler> CreateDataHandler(bool overwrite)
{
IPoolItem<IDataHandler> item = _poolItemFactory.Create(_dataHandlerFactory.Create());
item.Item.Init(overwrite);
_pool.Add(item);
return item;
}
private IPoolItem<IDataHandler> GetDataHandler() => _pool.First(i => !i.InUse);
public async ValueTask DisposeAsync()
{
while (_waitingRequesters.Any())
{
await Task.Delay(1000);
}
}
}
}

@ -1,27 +0,0 @@
// 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; private set; }
public T Use()
{
InUse = true;
return Item;
}
public void Dispose() => InUse = false;
}
}

@ -1,18 +0,0 @@
// 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,15 +5,12 @@
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;
@ -48,15 +45,19 @@ namespace GBase.DataHandling
/// <summary> /// <summary>
/// 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="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(IXmlDataReaderFactory xmlDataReaderFactory, public XmlDataHandler(string path,
string rootElementName,
IXmlDataReaderFactory xmlDataReaderFactory,
IXmlDataWriterFactory xmlDataWriterFactory, IXmlDataWriterFactory xmlDataWriterFactory,
IXmlDataHandlerCacheFactory xmlDataHandlerCacheFactory) IXmlDataHandlerCacheFactory xmlDataHandlerCacheFactory)
{ {
_xmlDataWriter = xmlDataWriterFactory.Create(); _xmlDataWriter = xmlDataWriterFactory.Create(path, rootElementName);
_xmlDataReader = xmlDataReaderFactory.Create(); _xmlDataReader = xmlDataReaderFactory.Create(path);
_cache = xmlDataHandlerCacheFactory.Create(_xmlDataReader); _cache = xmlDataHandlerCacheFactory.Create(_xmlDataReader);
} }
@ -65,57 +66,35 @@ 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 bool Init(bool overwrite) public async Task<bool> Init(bool overwrite, CancellationToken cancellationToken)
{ {
if (_isInitialized) if (_isInitialized)
return false; return false;
_overwrite = overwrite; _overwrite = overwrite;
_isInitialized = true; if (!await _xmlDataWriter.Init(cancellationToken))
return true; return false;
}
public async Task<bool> AddEntry<T>(T entry, IGBaseTable table, FileStream entryFile, CancellationToken cancellationToken)
{
await _xmlDataWriter.InitFile(entryFile, table.Type.Name, cancellationToken);
foreach (var column in table.Columns)
{
//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 (!await _xmlDataReader.Init(cancellationToken))
if (property.PropertyType != typeof(string) && property.GetValue(entry) is IEnumerable enumerable) return false;
valueString = enumerable.ToGBaseString();
else
valueString = property.GetValue(entry).ToString();
await _xmlDataWriter.Write<T>(entryFile, property.Name, valueString, property.PropertyType, _overwrite, cancellationToken); _isInitialized = true;
}
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>(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken) public async Task SetValue<T, TProperty>(string propertyName, TProperty value)
{ {
if (value == null) if (value == null)
return; return;
@ -127,7 +106,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>(entryFile, propertyName, valueString, _overwrite, cancellationToken); await _xmlDataWriter.Write<T, TProperty>(propertyName, valueString, _overwrite);
} }
/// <summary> /// <summary>
@ -135,12 +114,10 @@ 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>(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken) public async Task RemoveValue<T, TProperty>(string propertyName, TProperty value)
{ {
if (value == null) if (value == null)
return; return;
@ -152,7 +129,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>(entryFile, propertyName, valueString, cancellationToken); await _xmlDataWriter.Remove<T, TProperty>(propertyName, valueString);
} }
/// <summary> /// <summary>
@ -160,13 +137,11 @@ 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>(FileStream file, string propertyName, CancellationToken cancellationToken) public async Task<TProperty> GetValue<T, TProperty>(string propertyName)
{ {
IEnumerable<TProperty> enumerable = await GetValues<T, TProperty>(file, propertyName, cancellationToken); IEnumerable<TProperty> enumerable = await GetValues<T, TProperty>(propertyName);
return enumerable == null ? default : enumerable.FirstOrDefault(); return enumerable == null ? default : enumerable.FirstOrDefault();
} }
@ -175,17 +150,25 @@ 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>(FileStream file, string propertyName, CancellationToken cancellationToken) public async Task<IEnumerable<TProperty>> GetValues<T, TProperty>(string propertyName)
{ {
IEnumerable<TProperty> cachedValues = await _cache.TryGetValues<T, TProperty>(file, propertyName, cancellationToken); IEnumerable<TProperty> cachedValues = await _cache.TryGetValues<T, TProperty>(propertyName);
if (cachedValues != null) if (cachedValues != null)
return cachedValues; return cachedValues;
return await _xmlDataReader.Read<T, TProperty>(file, propertyName, cancellationToken); return await _xmlDataReader.Read<T, TProperty>(propertyName);
}
/// <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,56 +10,76 @@ 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;
using GBase.Interfaces.DataHandling; using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Xml; using GBase.Interfaces.DataHandling.Xml;
namespace GBase.DataHandling namespace GBase.DataHandling
{ {
/// <summary> /// <summary>
/// An <see cref="IDataReader"/> that reads from a xml file /// A <see cref="IDataReader"/> that reads from a xml file
/// </summary> /// </summary>
public class XmlDataReader : IXmlDataReader public class XmlDataReader : IXmlDataReader
{ {
private readonly IGBase _gBase; private readonly FileStream _file;
private XDocument _xmlDocument;
private XElement _rootElement;
private bool _isInitialized;
private CancellationToken _cancellationToken;
/// <summary> /// <summary>
/// An <see cref="IDataReader"/> that reads from a xml file /// A <see cref="IDataReader"/> that reads from a xml file
/// </summary> /// </summary>
/// <param name="gBase">The <see cref="IGBase"/></param> /// <param name="path">The path to the xml file</param>
public XmlDataReader(IGBase gBase) => _gBase = gBase; 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>(FileStream file, string propertyName, CancellationToken cancellationToken) public async Task<IEnumerable<TProperty>> Read<T, TProperty>(string propertyName)
//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));
file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to load 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
return await Task.Run(() => return await Task.Run(() =>
{ {
XElement rootElement = xmlDocument.Root; XElement typeElement = _rootElement.Element(typeName);
if (rootElement == null) XElement propertyElement = typeElement?.Element(propertyName);
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;
@ -75,10 +95,19 @@ namespace GBase.DataHandling
IEnumerable<string> values = valueElements.Select(v => v.Value); IEnumerable<string> values = valueElements.Select(v => v.Value);
if (typeof(TProperty) != typeof(string) && typeof(TProperty).GetInterfaces().Contains(typeof(IEnumerable))) //read property is an IEnumerable if (typeof(TProperty) != typeof(string) && typeof(TProperty).GetInterfaces().Contains(typeof(IEnumerable))) //read property is an IEnumerable
return values.Select(s => Enumerables.ConvertToGBaseEnumerable<TProperty>(s, _gBase)).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,7 +8,6 @@ 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;
@ -19,68 +18,81 @@ 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 InitFile(FileStream file, string rootElementName, CancellationToken cancellationToken) public async Task<bool> Init(CancellationToken cancellationToken)
{ {
//if the xml file isn't empty, return if (_isInitialized)
if (file.Length > 3) //> 3 because of BOM return false;
return;
XDocument xmlDocument = new XDocument(); _cancellationToken = cancellationToken;
xmlDocument.Add(new XElement(rootElementName)); //if the xml file is empty, write the root element
file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it if (_file.Length <= 3) //<= 3 because of BOM
await xmlDocument.SaveAsync(file, SaveOptions.OmitDuplicateNamespaces, cancellationToken); {
_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);
} }
/// <summary> _rootElement = _xmlDocument.Root;//?.Element(_rootElementName);
/// Write the data of a property if (_rootElement == null)
/// </summary> throw new Exception("No root element found.");
/// <typeparam name="T">The <see cref="Type"/></typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> _isInitialized = true;
/// <param name="file"></param> return true;
/// <param name="propertyName">The name 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="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> /// <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"/> that implements the property</typeparam>
/// <param name="file"></param> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <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="propertyType"></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>
/// <exception cref="ArgumentNullException"><paramref name="propertyName"/></exception> /// <exception cref="ArgumentNullException"><paramref name="propertyName"/></exception>
/// <exception cref="InvalidXmlFileException">No root element is set</exception> public async Task Write<T, TProperty>(string propertyName, string value, bool overwrite)
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 load 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 rootElement = xmlDocument.Root; XElement typeElement = _rootElement.Element(typeName);
if (rootElement == null) if (typeElement != null) //type element already exists
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);
@ -100,13 +112,21 @@ 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, propertyType.FullName); //add the property type attribute propertyElement.SetAttributeValue(XmlDataHandler.VALUE_TYPE_ATTRIBUTE_NAME, typeof(TProperty).FullName); //add the property type attribute
rootElement.Add(propertyElement); //create new property element with the value element typeElement.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>
@ -114,27 +134,19 @@ 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>
/// <exception cref="InvalidXmlFileException">No root element is set</exception> public async Task Remove<T, TProperty>(string propertyName, string value)
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));
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
file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
XElement rootElement = xmlDocument.Root; XElement typeElement = _rootElement.Element(typeName);
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)
@ -143,7 +155,17 @@ 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();
} }
} }
} }

@ -1,24 +0,0 @@
// Author: Gockner, Simon
// Created: 2020-11-13
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
namespace GBase.Exceptions
{
/// <summary>
/// Could not find generic method
/// </summary>
internal class GenericMethodNotFoundException : Exception
{
/// <summary>
/// Could not find generic method
/// </summary>
/// <param name="functionName">The name of the generic method</param>
public GenericMethodNotFoundException(string functionName)
: base($"Could not find function {functionName}")
{
}
}
}

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

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

@ -1,17 +0,0 @@
// Author: Gockner, Simon
// Created: 2020-11-13
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
namespace GBase.Exceptions
{
public class MissingKeyColumnException<T> : Exception
{
public MissingKeyColumnException()
: base($"Type {typeof(T)} is missing a key column.")
{
}
}
}

@ -1,23 +0,0 @@
// 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)}.")
{
}
}
}

@ -1,49 +0,0 @@
// Author: Simon Gockner
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using GBase.Exceptions;
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)
{
if (!typeof(IGBaseObject).IsAssignableFrom(type))
throw new InvalidTableTypeException(type);
Type gBaseTableType = typeof(GBaseTable<>).MakeGenericType(type);
return (IGBaseTable) Activator.CreateInstance(gBaseTableType, _fileHandlerFactory, _dataHandlerPool, _gBaseColumnFactory);
}
}
}

@ -3,7 +3,6 @@
// 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
@ -17,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(string name, Type type, bool isKey); IGBaseColumn Create();
} }
} }

@ -3,7 +3,6 @@
// 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
@ -17,6 +16,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(Type type); IGBaseTable Create();
} }
} }

@ -1,17 +0,0 @@
// 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.FileHandling.Exceptions; using GBase.DataHandling.Factories;
using GBase.Interfaces; using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Xml;
using GBase.Interfaces.FileHandling; using GBase.Interfaces.FileHandling;
namespace GBase.FileHandling namespace GBase.FileHandling
@ -18,91 +18,84 @@ namespace GBase.FileHandling
/// </summary> /// </summary>
public class FileHandler : IFileHandler public class FileHandler : IFileHandler
{ {
/// <summary> private readonly IXmlDataHandlerFactory _dataHandlerFactory;
/// 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>
public FileHandler() /// <param name="xmlDataHandlerFactory">Factory for the <see cref="IXmlDataHandler"/></param>
public FileHandler(IXmlDataHandlerFactory xmlDataHandlerFactory)
{ {
_files = new List<IGBaseFile>(); _dataHandlerFactory = xmlDataHandlerFactory;
} }
/// <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>
/// <param name="path">The path of the database</param> /// <param name="path">The path of the database</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 List<IGBaseFile> Init(string path, string folderName, CancellationToken cancellationToken) public async Task<bool> Init(string path, CancellationToken cancellationToken)
{ {
_path = path; DataHandler = _dataHandlerFactory.Create();
string directoryPath = Path.Combine(_path, folderName);
if (!Directory.Exists(directoryPath))
return null;
string[] files = Directory.GetFiles(directoryPath, $"*.{GBASE_TABLE_FILE_EXTENSION}");
foreach (var file in files) bool success = await DataHandler.Init(false, cancellationToken);
{ return success;
FileStream entryFile = File.Open(file, FileMode.OpenOrCreate, FileAccess.ReadWrite);
_files.Add(new GBaseFile(null, entryFile, file));
} }
return _files; /// <summary>
/// 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);
} }
public IGBaseFile CreateEntryFile<T>(T entry, IGBaseTable table) where T : IGBaseObject /// <summary>
/// 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>
public async Task RemoveValue<T, TProperty>(string propertyName, TProperty value)
{ {
string directoryPath = Path.Combine(_path, table.FolderName); await DataHandler.RemoveValue<T, TProperty>(propertyName, value);
//create directory if it doesn't exist
Directory.CreateDirectory(directoryPath);
//create new entry file
string filePath = $"{Path.Combine(directoryPath, entry.FileName)}.{GBASE_TABLE_FILE_EXTENSION}";
//check if file is already opened
IGBaseFile file = _files.FirstOrDefault(f => f.FilePath.Equals(filePath));
if (file != null)
return file.UseFile();
FileStream entryFile = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
file = new GBaseFile(entry, entryFile, filePath);
_files.Add(file);
return file.UseFile();
} }
public async Task<bool> DeleteEntryFile<T>(T entry) /// <summary>
/// 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)
{ {
IGBaseFile file = _files.FirstOrDefault(f => f.Entry.Equals(entry)); return await DataHandler.GetValue<T, TProperty>(propertyName);
if (file == default)
return false;
await file.File.DisposeAsync();
File.Delete(file.FilePath);
return true;
} }
public async Task<IGBaseFile> RequestEntryFile<T>(T entry) /// <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>
public async Task<IEnumerable<TProperty>> GetValues<T, TProperty>(string propertyName)
{ {
IGBaseFile file = _files.FirstOrDefault(f => f.Entry.Equals(entry)); return await DataHandler.GetValues<T, TProperty>(propertyName);
if (file == default)
throw new FileNotExistingException<T>();
if (file.InUse)
await Task.Delay(1000);
return file.UseFile();
} }
/// <summary> /// <summary>
@ -111,15 +104,7 @@ 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()
{ {
while (_files.Any(f => f.InUse)) await DataHandler.DisposeAsync();
{
await Task.Delay(1000);
}
foreach (var file in _files)
{
await file.File.DisposeAsync();
}
} }
} }
} }

@ -1,32 +0,0 @@
// 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; set; }
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,7 +9,6 @@ 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;
@ -21,6 +20,11 @@ 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>
@ -70,8 +74,8 @@ namespace GBase
if (gBaseTableAttribute == null) if (gBaseTableAttribute == null)
continue; continue;
IGBaseTable gBaseTable = _gBaseTableFactory.Create(type); IGBaseTable gBaseTable = _gBaseTableFactory.Create();
await gBaseTable.Init(type, Settings.DatabasePath, gBaseTableAttribute.FolderName, cancellationToken); await gBaseTable.Init(type, type.Name, Settings.DatabasePath, cancellationToken);
AddTable(gBaseTable); AddTable(gBaseTable);
} }
@ -89,21 +93,13 @@ namespace GBase
if (Tables.Contains(table)) if (Tables.Contains(table))
return false; return false;
if (Tables.Any(t => t.FolderName.Equals(table.FolderName))) if (Tables.Any(t => t.Name.Equals(table.Name)))
return false; return false;
Tables.Add(table); Tables.Add(table);
return true; return true;
} }
public IGBaseTable<T> GetTable<T>() where T : IGBaseObject, new()
{
if (Tables.OfType<IGBaseTable<T>>().Any())
return Tables.OfType<IGBaseTable<T>>().First();
throw new MissingTableException<T>();
}
/// <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>
@ -117,52 +113,6 @@ namespace GBase
return Tables.Remove(table); return Tables.Remove(table);
} }
public async Task<bool> AddEntry<T>(T entry, CancellationToken cancellationToken) where T : IGBaseObject, new()
{
IGBaseTable<T> table = GetTable<T>();
if (table == null)
throw new MissingTableException<T>();
return await table.AddEntry(entry, cancellationToken);
}
public T GetEntryForKey<T>(int key) where T : IGBaseObject, new()
{
IGBaseTable<T> table = GetTable<T>();
if (table == null)
throw new MissingTableException<T>();
return table.GetEntryForKey(key);
}
public async Task SetValue<T, TProperty>(T entry, string propertyName, TProperty value, CancellationToken cancellationToken) where T : IGBaseObject, new()
{
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) where T : IGBaseObject, new()
{
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) where T : IGBaseObject, new()
{
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>

@ -24,7 +24,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="LightweightIocContainer" Version="2.1.0" /> <PackageReference Include="LightweightIocContainer" Version="2.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.5.0-beta2-final" /> <PackageReference Include="Microsoft.CodeAnalysis" Version="3.5.0-beta2-final" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

@ -87,15 +87,13 @@
<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.IO.FileStream,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.DataHandling.Cache.XmlDataHandlerCache.TryGetValues``2(System.String)">
<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">
@ -165,10 +163,11 @@
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"> <member name="M:GBase.DataHandling.Factories.IXmlDataReaderFactory.Create(System.String)">
<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">
@ -176,10 +175,12 @@
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"> <member name="M:GBase.DataHandling.Factories.IXmlDataWriterFactory.Create(System.String,System.String)">
<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">
@ -197,158 +198,152 @@
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(GBase.DataHandling.Factories.IXmlDataReaderFactory,GBase.DataHandling.Factories.IXmlDataWriterFactory,GBase.DataHandling.Cache.Factories.IXmlDataHandlerCacheFactory)"> <member name="M:GBase.DataHandling.XmlDataHandler.#ctor(System.String,System.String,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="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)"> <member name="M:GBase.DataHandling.XmlDataHandler.Init(System.Boolean,System.Threading.CancellationToken)">
<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.IO.FileStream,System.String,``1,System.Threading.CancellationToken)"> <member name="M:GBase.DataHandling.XmlDataHandler.SetValue``2(System.String,``1)">
<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.IO.FileStream,System.String,``1,System.Threading.CancellationToken)"> <member name="M:GBase.DataHandling.XmlDataHandler.RemoveValue``2(System.String,``1)">
<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.IO.FileStream,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.DataHandling.XmlDataHandler.GetValue``2(System.String)">
<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.IO.FileStream,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.DataHandling.XmlDataHandler.GetValues``2(System.String)">
<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>
An <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>
</member>
<member name="M:GBase.DataHandling.XmlDataReader.#ctor(System.String)">
<summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file
</summary> </summary>
<param name="path">The path to the xml file</param>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataReader.#ctor(GBase.Interfaces.IGBase)"> <member name="M:GBase.DataHandling.XmlDataReader.Init(System.Threading.CancellationToken)">
<summary> <summary>
An <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file Initialize the <see cref="T:GBase.DataHandling.XmlDataReader"/>
</summary> </summary>
<param name="gBase">The <see cref="T:GBase.Interfaces.IGBase"/></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>
<exception cref="T:System.Exception">No root element found</exception>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataReader.Read``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)"> <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.InitFile(System.IO.FileStream,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.DataHandling.XmlDataWriter.#ctor(System.String,System.String)">
<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.IO.FileStream,System.String,System.String,System.Boolean,System.Threading.CancellationToken)"> <member name="M:GBase.DataHandling.XmlDataWriter.Write``2(System.String,System.String,System.Boolean)">
<summary>
Write the data of a property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/></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="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="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> <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"/> that implements the property</typeparam>
<param name="file"></param> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<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="propertyType"></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>
<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.IO.FileStream,System.String,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.DataHandling.XmlDataWriter.Remove``2(System.String,System.String)">
<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>
<exception cref="T:GBase.DataHandling.Exceptions.InvalidXmlFileException">No root element is set</exception>
</member> </member>
<member name="T:GBase.Exceptions.GenericMethodNotFoundException"> <member name="M:GBase.DataHandling.XmlDataWriter.DisposeAsync">
<summary> <summary>
Could not find generic method Dispose used resources asynchronously
</summary>
</member>
<member name="M:GBase.Exceptions.GenericMethodNotFoundException.#ctor(System.String)">
<summary>
Could not find generic method
</summary> </summary>
<param name="functionName">The name of the generic method</param> <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>
@ -366,52 +361,12 @@
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.Interfaces.IGBaseObject"/>"/>
</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.Interfaces.IGBaseObject"/>"/>
</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(System.String,System.Type,System.Boolean)"> <member name="M:GBase.Factories.IGBaseColumnFactory.Create">
<summary> <summary>
Creates an <see cref="T:GBase.Interfaces.IGBaseColumn"/> Creates an <see cref="T:GBase.Interfaces.IGBaseColumn"/>
</summary> </summary>
@ -434,7 +389,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(System.Type)"> <member name="M:GBase.Factories.IGBaseTableFactory.Create">
<summary> <summary>
Creates an <see cref="T:GBase.Interfaces.IGBaseTable"/> Creates an <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
@ -456,25 +411,63 @@
Internal file handler Internal file handler
</summary> </summary>
</member> </member>
<member name="F:GBase.FileHandling.FileHandler.GBASE_TABLE_FILE_EXTENSION"> <member name="M:GBase.FileHandling.FileHandler.#ctor(GBase.DataHandling.Factories.IXmlDataHandlerFactory)">
<summary> <summary>
The file extension for all GBase tables Internal file handler
</summary> </summary>
<param name="xmlDataHandlerFactory">Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataHandler"/></param>
</member> </member>
<member name="M:GBase.FileHandling.FileHandler.#ctor"> <member name="P:GBase.FileHandling.FileHandler.DataHandler">
<summary> <summary>
Internal file handler The <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/> of this <see cref="T:GBase.Interfaces.FileHandling.IFileHandler"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.FileHandling.FileHandler.Init(System.String,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.FileHandling.FileHandler.Init(System.String,System.Threading.CancellationToken)">
<summary> <summary>
Initialize this <see cref="T:GBase.Interfaces.FileHandling.IFileHandler"/> Initialize this <see cref="T:GBase.Interfaces.FileHandling.IFileHandler"/>
</summary> </summary>
<param name="path">The path of the database</param> <param name="path">The path of the database</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.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
@ -486,6 +479,11 @@
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
@ -542,7 +540,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(System.String,System.Type,System.Boolean)"> <member name="M:GBase.GBaseColumn.#ctor">
<summary> <summary>
A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/> A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
@ -553,96 +551,91 @@
</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.GBaseObject`1"> <member name="T:GBase.GBaseTable">
<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`1.#ctor(GBase.FileHandling.Factories.IFileHandlerFactory,GBase.Interfaces.DataHandling.Pool.IDataHandlerPool,GBase.Factories.IGBaseColumnFactory)"> <member name="M:GBase.GBaseTable.#ctor(GBase.FileHandling.Factories.IFileHandlerFactory,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`1.Type"> <member name="P:GBase.GBaseTable.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`1.FolderName"> <member name="P:GBase.GBaseTable.Name">
<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`1.Columns"> <member name="P:GBase.GBaseTable.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`1.Entries"> <member name="P:GBase.GBaseTable.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`1.Init(System.Type,System.String,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.GBaseTable.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`1.AddColumn(GBase.Interfaces.IGBaseColumn)"> <member name="M:GBase.GBaseTable.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`1.RemoveColumn(GBase.Interfaces.IGBaseColumn)"> <member name="M:GBase.GBaseTable.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`1.AddEntry(`0,System.Threading.CancellationToken)"> <member name="M:GBase.GBaseTable.AddEntry(GBase.Api.INotifyGBaseEntryChanged)">
<summary> <summary>
Add an entry that implements <see cref="T:GBase.Interfaces.IGBaseObject"/> 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.Interfaces.IGBaseObject"/></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`1.RemoveEntry(`0)"> <member name="M:GBase.GBaseTable.RemoveEntry(GBase.Api.INotifyGBaseEntryChanged)">
<summary> <summary>
Remove an entry that implements <see cref="T:GBase.Interfaces.IGBaseObject"/> 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.Interfaces.IGBaseObject"/></param> <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.GBaseTable.ModifyEntry(System.Object,System.String,System.Object)">
<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> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.GBaseTable`1.DisposeAsync"> <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>
@ -653,73 +646,17 @@
Convert an <see cref="T:System.Collections.IEnumerable"/> to a GBase <see cref="T:System.String"/> Convert an <see cref="T:System.Collections.IEnumerable"/> to a GBase <see cref="T:System.String"/>
</summary> </summary>
<param name="enumerable">The <see cref="T:System.Collections.IEnumerable"/></param> <param name="enumerable">The <see cref="T:System.Collections.IEnumerable"/></param>
<returns>The converted <see cref="T:System.Collections.IEnumerable"/> as a GBase <see cref="T:System.String"/></returns> <returns></returns>
</member> </member>
<member name="M:GBase.Helpers.Enumerables.ConvertToGBaseEnumerable``1(System.String,GBase.Interfaces.IGBase)"> <member name="M:GBase.Helpers.Enumerables.ConvertToGBaseEnumerable``1(System.String)">
<summary> <summary>
Convert a given <see cref="T:System.String"/> to an <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:System.Type"/> <typeparamref name="TEnumerable"/> Convert a given <see cref="T:System.String"/> to an <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:System.Type"/> <typeparamref name="TEnumerable"/>
</summary> </summary>
<typeparam name="TEnumerable">The <see cref="T:System.Collections.Generic.IEnumerable`1"/> <see cref="T:System.Type"/></typeparam> <typeparam name="TEnumerable">The <see cref="T:System.Collections.Generic.IEnumerable`1"/> <see cref="T:System.Type"/></typeparam>
<typeparam name="T"></typeparam>
<param name="string">The given <see cref="T:System.String"/></param> <param name="string">The given <see cref="T:System.String"/></param>
<param name="gBase"></param>
<returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:System.Type"/> <typeparamref name="TEnumerable"/></returns> <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:System.Type"/> <typeparamref name="TEnumerable"/></returns>
<exception cref="T:GBase.Exceptions.InterfaceEnumerablePassedException">Interface was passed to an <see cref="T:System.Collections.Generic.IEnumerable`1"/></exception> <exception cref="T:GBase.Exceptions.InterfaceEnumerablePassedException">Interface was passed to an <see cref="T:System.Collections.Generic.IEnumerable`1"/></exception>
</member> </member>
<member name="M:GBase.Helpers.GenericMethodCaller.Call(System.Object,System.String,System.Reflection.BindingFlags,System.Type,System.Object[])">
<summary>
Call a generic method without generic type parameters
</summary>
<param name="caller">The caller of the method</param>
<param name="functionName">The name of the method to call</param>
<param name="bindingFlags">The <see cref="T:System.Reflection.BindingFlags"/> to find the method</param>
<param name="genericParameter">The generic parameter as <see cref="T:System.Type"/> parameter</param>
<param name="parameters">The parameters of the method</param>
<returns>The result of invoking the method</returns>
<exception cref="T:GBase.Exceptions.GenericMethodNotFoundException">Could not find the generic method</exception>
<exception cref="T:System.Exception">Any <see cref="T:System.Exception"/> thrown after invoking the generic method</exception>
</member>
<member name="M:GBase.Helpers.GenericMethodCaller.Call(System.Object,System.String,System.Reflection.BindingFlags,System.Type,System.Type,System.Object[])">
<summary>
Call a generic method without generic type parameters
</summary>
<param name="caller">The caller of the method</param>
<param name="functionName">The name of the method to call</param>
<param name="bindingFlags">The <see cref="T:System.Reflection.BindingFlags"/> to find the method</param>
<param name="genericParameter">The generic parameter as <see cref="T:System.Type"/> parameter</param>
<param name="secondGenericParameter"></param>
<param name="parameters">The parameters of the method</param>
<returns>The result of invoking the method</returns>
<exception cref="T:GBase.Exceptions.GenericMethodNotFoundException">Could not find the generic method</exception>
<exception cref="T:System.Exception">Any <see cref="T:System.Exception"/> thrown after invoking the generic method</exception>
</member>
<member name="M:GBase.Helpers.GenericMethodCaller.CallAsync(System.Object,System.String,System.Reflection.BindingFlags,System.Type,System.Object[])">
<summary>
Call a generic method asynchronously without generic type parameters
</summary>
<param name="caller">The caller of the method</param>
<param name="functionName">The name of the method to call</param>
<param name="bindingFlags">The <see cref="T:System.Reflection.BindingFlags"/> to find the method</param>
<param name="genericParameter">The generic parameter as <see cref="T:System.Type"/> parameter</param>
<param name="parameters">The parameters of the method</param>
<returns>The result of invoking the method</returns>
<exception cref="T:GBase.Exceptions.GenericMethodNotFoundException">Could not find the generic method</exception>
<exception cref="T:System.Exception">Any <see cref="T:System.Exception"/> thrown after invoking the generic method</exception>
</member>
<member name="M:GBase.Helpers.GenericMethodCaller.CallAsync(System.Object,System.String,System.Reflection.BindingFlags,System.Type,System.Type,System.Object[])">
<summary>
Call a generic method asynchronously without generic type parameters
</summary>
<param name="caller">The caller of the method</param>
<param name="functionName">The name of the method to call</param>
<param name="bindingFlags">The <see cref="T:System.Reflection.BindingFlags"/> to find the method</param>
<param name="genericParameter">The generic parameter as <see cref="T:System.Type"/> parameter</param>
<param name="secondGenericParameter"></param>
<param name="parameters">The parameters of the method</param>
<returns>The result of invoking the method</returns>
<exception cref="T:GBase.Exceptions.GenericMethodNotFoundException">Could not find the generic method</exception>
<exception cref="T:System.Exception">Any <see cref="T:System.Exception"/> thrown after invoking the generic method</exception>
</member>
<member name="T:GBase.Installers.DataHandlingInstaller"> <member name="T:GBase.Installers.DataHandlingInstaller">
<summary> <summary>
<see cref="T:LightweightIocContainer.Interfaces.Installers.IIocInstaller"/> for the data handling <see cref="T:LightweightIocContainer.Interfaces.Installers.IIocInstaller"/> for the data handling
@ -770,15 +707,13 @@
<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.IO.FileStream,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.Cache.IDataHandlerCache.TryGetValues``2(System.String)">
<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">
@ -821,57 +756,50 @@
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)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.Init(System.Boolean,System.Threading.CancellationToken)">
<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.IO.FileStream,System.String,``1,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.SetValue``2(System.String,``1)">
<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.IO.FileStream,System.String,``1,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.RemoveValue``2(System.String,``1)">
<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.IO.FileStream,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValue``2(System.String)">
<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.IO.FileStream,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValues``2(System.String)">
<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">
@ -879,15 +807,20 @@
Interface for data readers to implement Interface for data readers to implement
</summary> </summary>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataReader.Read``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataReader.Init(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">
@ -895,51 +828,32 @@
Interface for data writers to implement Interface for data writers to implement
</summary> </summary>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.InitFile(System.IO.FileStream,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataWriter.Init(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.IO.FileStream,System.String,System.String,System.Boolean,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataWriter.Write``2(System.String,System.String,System.Boolean)">
<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.Write``1(System.IO.FileStream,System.String,System.String,System.Type,System.Boolean,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataWriter.Remove``2(System.String,System.String)">
<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">
@ -977,15 +891,52 @@
Internal file handler Internal file handler
</summary> </summary>
</member> </member>
<member name="M:GBase.Interfaces.FileHandling.IFileHandler.Init(System.String,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.FileHandling.IFileHandler.Init(System.String,System.Threading.CancellationToken)">
<summary> <summary>
Initialize this <see cref="T:GBase.Interfaces.FileHandling.IFileHandler"/> Initialize this <see cref="T:GBase.Interfaces.FileHandling.IFileHandler"/>
</summary> </summary>
<param name="path">The path of the database</param> <param name="path">The path of the database</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.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
@ -1034,47 +985,6 @@
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="T:GBase.Interfaces.IGBaseObject">
<summary>
GBase object that allows conversion from <see cref="T:System.String"/>
</summary>
</member>
<member name="P:GBase.Interfaces.IGBaseObject.Key">
<summary>
<see cref="T:GBase.Interfaces.IGBase"/> Key
</summary>
</member>
<member name="P:GBase.Interfaces.IGBaseObject.FileName">
<summary>
The FileName of the GBase file for an entry of this object
</summary>
</member>
<member name="M:GBase.Interfaces.IGBaseObject.InitializeFromString(System.String)">
<summary>
Initialize this <see cref="T:GBase.Interfaces.IGBaseObject"/> from a given <see cref="T:System.String"/>
</summary>
<param name="string">The given <see cref="T:System.String"/></param>
</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.Interfaces.IGBaseObject"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<param name="entry">The entry implementing <see cref="T:GBase.Interfaces.IGBaseObject"/></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.Interfaces.IGBaseObject"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<param name="entry">The entry implementing <see cref="T:GBase.Interfaces.IGBaseObject"/></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
@ -1085,7 +995,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.FolderName"> <member name="P:GBase.Interfaces.IGBaseTable.Name">
<summary> <summary>
The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/> The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
@ -1095,15 +1005,19 @@
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="databasePath">The path to the database files</param> <param name="name">The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/></param>
<param name="folderName"></param> /// <param name="databasePath">The path to the database files</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)">
@ -1120,6 +1034,20 @@
<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,16 +16,10 @@ namespace GBase
/// <summary> /// <summary>
/// A column of a <see cref="IGBaseTable"/> /// A column of a <see cref="IGBaseTable"/>
/// </summary> /// </summary>
public GBaseColumn(string name, Type type, bool isKey) public GBaseColumn()
{ {
Name = name;
Type = type;
IsKey = isKey;
}
public string Name { get; } }
public Type Type { get; }
public bool IsKey { get; }
/// <summary> /// <summary>
/// The <see cref="IAsyncDisposable.DisposeAsync"/> method /// The <see cref="IAsyncDisposable.DisposeAsync"/> method

@ -1,30 +0,0 @@
// Author: Gockner, Simon
// Created: 2020-11-13
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
namespace GBase
{
public class GBaseKey
{
private int _key = -1;
private bool _isSet;
public int Key
{
get => _key;
internal set
{
if (_isSet)
throw new InvalidOperationException("Key is already set.");
_key = value;
_isSet = true;
}
}
public override string ToString() => $"{Key}";
public static implicit operator int(GBaseKey key) => key.Key;
}
}

@ -1,45 +0,0 @@
// 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.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 where T : IGBaseObject, new()
{
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>();
}
public GBaseKey Key { get; set; }
public abstract string FileName { get; }
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);
public abstract void Initialize(GBaseKey key, List<object> parameters);
}
}

@ -4,18 +4,16 @@
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;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.Api;
using GBase.Attributes; using GBase.Attributes;
using GBase.Exceptions;
using GBase.Factories; using GBase.Factories;
using GBase.FileHandling.Factories; using GBase.FileHandling.Factories;
using GBase.Helpers;
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
@ -23,26 +21,21 @@ namespace GBase
/// <summary> /// <summary>
/// A <see cref="IGBase"/> table /// A <see cref="IGBase"/> table
/// </summary> /// </summary>
public class GBaseTable<T> : IGBaseTable<T> where T : IGBaseObject, new() public class GBaseTable : IGBaseTable
{ {
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>
/// <param name="fileHandlerFactory"></param> public GBaseTable(IFileHandlerFactory fileHandlerFactory, IGBaseColumnFactory gBaseColumnFactory)
/// <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<T>(); Entries = new List<object>();
} }
@ -54,7 +47,7 @@ namespace GBase
/// <summary> /// <summary>
/// The name of this <see cref="IGBaseTable"/> /// The name of this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
public string FolderName { get; private set; } public string Name { 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"/>
@ -64,85 +57,38 @@ namespace GBase
/// <summary> /// <summary>
/// The entries of this <see cref="IGBaseTable"/> /// The entries of this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
public List<T> Entries { get; } public List<object> Entries { get; }
private int CurrentLastKey
{
get
{
T lastEntry = Entries.LastOrDefault();
if (lastEntry == null)
return -1;
return lastEntry.Key;
}
}
/// <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 Init(Type type, string databasePath, string folderName, CancellationToken cancellationToken) public async Task<bool> Init(Type type, string name, string databasePath, CancellationToken cancellationToken)
{ {
Type = type; Type = type;
FolderName = folderName; Name = name;
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())
{ {
GBaseColumnAttribute gBaseColumnAttribute = property.GetCustomAttribute<GBaseColumnAttribute>() ?? GBaseColumnAttribute gBaseColumnAttribute = property.GetCustomAttribute<GBaseColumnAttribute>();
property.GetAttributeFromInheritedInterfaces<GBaseColumnAttribute>();
if (gBaseColumnAttribute == null) if (gBaseColumnAttribute == null)
continue; continue;
IGBaseColumn gBaseColumn = _gBaseColumnFactory.Create(property.Name, property.PropertyType, gBaseColumnAttribute.IsKey); IGBaseColumn gBaseColumn = _gBaseColumnFactory.Create();
AddColumn(gBaseColumn); AddColumn(gBaseColumn);
} }
List<IGBaseFile> files = _fileHandler.Init(databasePath, FolderName, cancellationToken); return true;
if (files == null)
return;
foreach (var file in files) //create entries for existing files
{
using (file.UseFile())
{
T entry = new T();
List<object> parameters = new List<object>();
foreach (var column in Columns.Where(c => !c.IsKey))
{
using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
parameters.Add(await GenericMethodCaller.CallAsync(dataHandlerItem.Use(),
nameof(IDataHandler.GetValue),
BindingFlags.Public | BindingFlags.Instance,
typeof(T), column.Type,
file.File, column.Name, cancellationToken));
}
IGBaseColumn keyColumn = Columns.FirstOrDefault(c => c.IsKey);
if (keyColumn == null)
throw new MissingKeyColumnException<T>();
GBaseKey key = new GBaseKey();
using (IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken))
{
key.Key = await dataHandlerItem.Use().GetValue<T, int>(file.File, keyColumn.Name, cancellationToken);
}
entry.Initialize(key, parameters);
file.Entry = entry;
Entries.Add(entry);
}
}
} }
/// <summary> /// <summary>
@ -150,7 +96,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) //TODO: if a column is added, it has to be added to every entry file as well public bool AddColumn(IGBaseColumn column)
{ {
if (Columns.Contains(column)) if (Columns.Contains(column))
return false; return false;
@ -164,7 +110,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) //TODO: if a column is removed, it has to be removed from every entry file as well public bool RemoveColumn(IGBaseColumn column)
{ {
if (!Columns.Contains(column)) if (!Columns.Contains(column))
return false; return false;
@ -173,65 +119,58 @@ namespace GBase
} }
/// <summary> /// <summary>
/// Add an entry that implements <see cref="IGBaseObject"/> 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="IGBaseObject"/></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 async Task<bool> AddEntry(T entry, CancellationToken cancellationToken) public bool AddEntry(INotifyGBaseEntryChanged entry) //TODO: Write to file
{ {
entry.Key ??= new GBaseKey();
if (entry.Key != -1)
throw new InvalidKeyException("Key of entry is already set. Make sure it is -1 when initializing.");
entry.Key.Key = CurrentLastKey + 1; //set next possible key
Entries.Add(entry); Entries.Add(entry);
entry.GBaseEntryChanged += OnGBaseEntryChanged;
using IGBaseFile file = _fileHandler.CreateEntryFile(entry, this);
using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
await dataHandlerItem.Use().AddEntry(entry, this, file.File, cancellationToken);
return true; return true;
} }
public T GetEntryForKey(int key) => Entries.FirstOrDefault(e => e.Key == key);
/// <summary> /// <summary>
/// Remove an entry that implements <see cref="IGBaseObject"/> from this <see cref="IGBaseTable"/> /// Remove an entry that implements <see cref="INotifyGBaseEntryChanged"/> from this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
/// <param name="entry">The entry implementing <see cref="IGBaseObject"/></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 async Task<bool> RemoveEntry(T entry) public bool RemoveEntry(INotifyGBaseEntryChanged entry) //TODO: remove from file
{ {
if (!Entries.Contains(entry)) if (!Entries.Contains(entry))
return false; return false;
await _fileHandler.DeleteEntryFile(entry); entry.GBaseEntryChanged -= OnGBaseEntryChanged;
return Entries.Remove(entry); return Entries.Remove(entry);
} }
public async Task SetValue<TProperty>(T entry, string propertyName, TProperty value, CancellationToken cancellationToken) /// <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>
private bool ModifyEntry(object entry, string propertyName, object value) //TODO: Write to file
{ {
using IGBaseFile file = await _fileHandler.RequestEntryFile(entry); //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 IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken); return true;
await dataHandlerItem.Use().SetValue<T, TProperty>(file.File, propertyName, value, cancellationToken);
} }
public async Task<TProperty> GetValue<TProperty>(T entry, string propertyName, CancellationToken cancellationToken) /// <summary>
/// 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)
{ {
using IGBaseFile file = await _fileHandler.RequestEntryFile(entry); //TODO: Might change, depending on #23
using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken); bool success = ModifyEntry(entry, args.ColumnName, args.Value);
return await dataHandlerItem.Use().GetValue<T, TProperty>(file.File, propertyName, cancellationToken);
}
public async Task<IEnumerable<TProperty>> GetValues<TProperty>(T entry, string propertyName, CancellationToken cancellationToken) if (!success)
{ throw new Exception("Failed to handle EntryChanged"); //TODO: Decide what to do here
using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
return await dataHandlerItem.Use().GetValues<T, TProperty>(file.File, propertyName, cancellationToken);
} }
/// <summary> /// <summary>
@ -241,7 +180,6 @@ 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)
{ {
@ -250,9 +188,9 @@ namespace GBase
Columns.Clear(); Columns.Clear();
foreach (var entry in Entries.ToList()) foreach (var entry in Entries.OfType<INotifyGBaseEntryChanged>().ToList())
{ {
await RemoveEntry(entry); RemoveEntry(entry);
} }
Entries.Clear(); Entries.Clear();

@ -1,19 +0,0 @@
// Author: Gockner, Simon
// Created: 2020-11-13
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using System.Linq;
using System.Reflection;
namespace GBase.Helpers
{
internal static class Attributes
{
public static T GetAttributeFromInheritedInterfaces<T>(this PropertyInfo propertyInfo) where T : Attribute =>
propertyInfo.DeclaringType?.GetInterfaces()
.SelectMany(i => i.GetProperties().Where(p => p.Name.Equals(propertyInfo.Name)))
.Select(p => p.GetCustomAttribute<T>())
.FirstOrDefault();
}
}

@ -6,10 +6,9 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using GBase.Api;
using GBase.Exceptions; using GBase.Exceptions;
using GBase.Interfaces;
namespace GBase.Helpers namespace GBase.Helpers
{ {
@ -21,15 +20,12 @@ namespace GBase.Helpers
/// Convert an <see cref="IEnumerable"/> to a GBase <see cref="string"/> /// Convert an <see cref="IEnumerable"/> to a GBase <see cref="string"/>
/// </summary> /// </summary>
/// <param name="enumerable">The <see cref="IEnumerable"/></param> /// <param name="enumerable">The <see cref="IEnumerable"/></param>
/// <returns>The converted <see cref="IEnumerable"/> as a GBase <see cref="string"/></returns> /// <returns></returns>
public static string ToGBaseString(this IEnumerable enumerable) public static string ToGBaseString(this IEnumerable enumerable)
{ {
StringBuilder @string = new StringBuilder(); StringBuilder @string = new StringBuilder();
foreach (var item in enumerable) foreach (var item in enumerable)
{ {
if (item is IGBaseObject gBaseObject)
@string.Append($"{gBaseObject.Key}{ENUMERABLE_STRING_DIVIDER}");
else
@string.Append($"{item}{ENUMERABLE_STRING_DIVIDER}"); @string.Append($"{item}{ENUMERABLE_STRING_DIVIDER}");
} }
@ -45,10 +41,9 @@ namespace GBase.Helpers
/// </summary> /// </summary>
/// <typeparam name="TEnumerable">The <see cref="IEnumerable{T}"/> <see cref="Type"/></typeparam> /// <typeparam name="TEnumerable">The <see cref="IEnumerable{T}"/> <see cref="Type"/></typeparam>
/// <param name="string">The given <see cref="string"/></param> /// <param name="string">The given <see cref="string"/></param>
/// <param name="gBase"></param>
/// <returns>An <see cref="IEnumerable{T}"/> of <see cref="Type"/> <typeparamref name="TEnumerable"/></returns> /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="Type"/> <typeparamref name="TEnumerable"/></returns>
/// <exception cref="InterfaceEnumerablePassedException">Interface was passed to an <see cref="IEnumerable{T}"/></exception> /// <exception cref="InterfaceEnumerablePassedException">Interface was passed to an <see cref="IEnumerable{T}"/></exception>
public static TEnumerable ConvertToGBaseEnumerable<TEnumerable>(string @string, IGBase gBase) public static TEnumerable ConvertToGBaseEnumerable<TEnumerable>(string @string)
{ {
//get generic type parameter of TEnumerable //get generic type parameter of TEnumerable
Type genericType = typeof(TEnumerable).GetGenericArguments()[0]; Type genericType = typeof(TEnumerable).GetGenericArguments()[0];
@ -66,16 +61,9 @@ namespace GBase.Helpers
if (genericType.IsInterface) if (genericType.IsInterface)
throw new InterfaceEnumerablePassedException(genericType); throw new InterfaceEnumerablePassedException(genericType);
if (!int.TryParse(value, out int key)) IGBaseObject gBaseObject = (IGBaseObject) Activator.CreateInstance(genericType);
throw new InvalidKeyException("Key is not an integer."); gBaseObject.InitializeFromString(value);
item = gBaseObject;
//TODO: What to do when this table isn't initialized yet?
item = GenericMethodCaller.Call(gBase, nameof(IGBase.GetEntryForKey),
BindingFlags.Public | BindingFlags.Instance, genericType, key);
// IGBaseObject gBaseObject = (IGBaseObject) Activator.CreateInstance(genericType);
// gBaseObject.InitializeFromString(value);
// item = gBaseObject;
} }
else else
item = Convert.ChangeType(value, genericType); item = Convert.ChangeType(value, genericType);

@ -1,108 +0,0 @@
// Author: Gockner, Simon
// Created: 2020-11-13
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using System.Reflection;
using System.Threading.Tasks;
using GBase.Exceptions;
namespace GBase.Helpers
{
internal static class GenericMethodCaller
{
/// <summary>
/// Call a generic method without generic type parameters
/// </summary>
/// <param name="caller">The caller of the method</param>
/// <param name="functionName">The name of the method to call</param>
/// <param name="bindingFlags">The <see cref="BindingFlags"/> to find the method</param>
/// <param name="genericParameter">The generic parameter as <see cref="Type"/> parameter</param>
/// <param name="parameters">The parameters of the method</param>
/// <returns>The result of invoking the method</returns>
/// <exception cref="GenericMethodNotFoundException">Could not find the generic method</exception>
/// <exception cref="Exception">Any <see cref="Exception"/> thrown after invoking the generic method</exception>
public static object Call(object caller, string functionName, BindingFlags bindingFlags, Type genericParameter, params object[] parameters) =>
GetGenericMethod(caller, functionName, bindingFlags, genericParameter).InvokeGenericMethod(caller, parameters);
/// <summary>
/// Call a generic method without generic type parameters
/// </summary>
/// <param name="caller">The caller of the method</param>
/// <param name="functionName">The name of the method to call</param>
/// <param name="bindingFlags">The <see cref="BindingFlags"/> to find the method</param>
/// <param name="genericParameter">The generic parameter as <see cref="Type"/> parameter</param>
/// <param name="secondGenericParameter"></param>
/// <param name="parameters">The parameters of the method</param>
/// <returns>The result of invoking the method</returns>
/// <exception cref="GenericMethodNotFoundException">Could not find the generic method</exception>
/// <exception cref="Exception">Any <see cref="Exception"/> thrown after invoking the generic method</exception>
public static object Call(object caller, string functionName, BindingFlags bindingFlags, Type genericParameter, Type secondGenericParameter,params object[] parameters) =>
GetGenericMethod(caller, functionName, bindingFlags, genericParameter, secondGenericParameter).InvokeGenericMethod(caller, parameters);
/// <summary>
/// Call a generic method asynchronously without generic type parameters
/// </summary>
/// <param name="caller">The caller of the method</param>
/// <param name="functionName">The name of the method to call</param>
/// <param name="bindingFlags">The <see cref="BindingFlags"/> to find the method</param>
/// <param name="genericParameter">The generic parameter as <see cref="Type"/> parameter</param>
/// <param name="parameters">The parameters of the method</param>
/// <returns>The result of invoking the method</returns>
/// <exception cref="GenericMethodNotFoundException">Could not find the generic method</exception>
/// <exception cref="Exception">Any <see cref="Exception"/> thrown after invoking the generic method</exception>
public static async Task<object> CallAsync(object caller, string functionName, BindingFlags bindingFlags, Type genericParameter, params object[] parameters) =>
await GetGenericMethod(caller, functionName, bindingFlags, genericParameter).InvokeGenericMethodAsync(caller, parameters);
/// <summary>
/// Call a generic method asynchronously without generic type parameters
/// </summary>
/// <param name="caller">The caller of the method</param>
/// <param name="functionName">The name of the method to call</param>
/// <param name="bindingFlags">The <see cref="BindingFlags"/> to find the method</param>
/// <param name="genericParameter">The generic parameter as <see cref="Type"/> parameter</param>
/// <param name="secondGenericParameter"></param>
/// <param name="parameters">The parameters of the method</param>
/// <returns>The result of invoking the method</returns>
/// <exception cref="GenericMethodNotFoundException">Could not find the generic method</exception>
/// <exception cref="Exception">Any <see cref="Exception"/> thrown after invoking the generic method</exception>
public static async Task<object> CallAsync(object caller, string functionName, BindingFlags bindingFlags, Type genericParameter, Type secondGenericParameter, params object[] parameters) =>
await GetGenericMethod(caller, functionName, bindingFlags, genericParameter, secondGenericParameter).InvokeGenericMethodAsync(caller, parameters);
private static MethodInfo GetGenericMethod(object caller, string functionName, BindingFlags bindingFlags, params Type[] genericParameters)
{
MethodInfo genericMethod = caller.GetType().GetMethod(functionName, bindingFlags)?.MakeGenericMethod(genericParameters);
if (genericMethod == null)
throw new GenericMethodNotFoundException(functionName);
return genericMethod;
}
private static object InvokeGenericMethod(this MethodInfo genericMethod, object caller, params object[] parameters)
{
try //exceptions thrown by methods called with invoke are wrapped into another exception, the exception thrown by the invoked method can be returned by `Exception.GetBaseException()`
{
return genericMethod.Invoke(caller, parameters);
}
catch (Exception ex)
{
throw ex.GetBaseException();
}
}
private static async Task<object> InvokeGenericMethodAsync(this MethodInfo genericMethod, object caller, params object[] parameters)
{
try //exceptions thrown by methods called with invoke are wrapped into another exception, the exception thrown by the invoked method can be returned by `Exception.GetBaseException()`
{
dynamic awaitable = genericMethod.Invoke(caller, parameters);
await awaitable;
return awaitable.GetAwaiter().GetResult();
}
catch (Exception ex)
{
throw ex.GetBaseException();
}
}
}
}

@ -7,13 +7,8 @@ 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;
@ -27,23 +22,16 @@ namespace GBase.Installers
/// <inheritdoc /> /// <inheritdoc />
public void Install(IIocContainer container) public void Install(IIocContainer container)
{ {
container.Register<IDataHandler, IXmlDataHandler, XmlDataHandler>(); container.Register<IXmlDataHandler, XmlDataHandler>();
container.Register<IDataReader, IXmlDataReader, XmlDataReader>(); container.Register<IXmlDataReader, XmlDataReader>();
container.Register<IDataWriter, IXmlDataWriter, XmlDataWriter>(); container.Register<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<IPoolRequest, PoolRequest>();
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>();

@ -5,7 +5,6 @@
using GBase.Factories; using GBase.Factories;
using GBase.Interfaces; using GBase.Interfaces;
using LightweightIocContainer;
using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Installers; using LightweightIocContainer.Interfaces.Installers;
@ -19,12 +18,13 @@ namespace GBase.Installers
/// <inheritdoc /> /// <inheritdoc />
public void Install(IIocContainer container) public void Install(IIocContainer container)
{ {
container.Register<IGBase, GBase>(Lifestyle.Singleton); 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.Register<IGBaseTableFactory, GBaseTableFactory>(); //TODO: Once LightweightIocContainer can handle open generic registrations this can be changed back again container.RegisterFactory<IGBaseTableFactory>();
container.RegisterFactory<IGBaseColumnFactory>(); container.RegisterFactory<IGBaseColumnFactory>();
} }
} }

@ -4,8 +4,6 @@
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
@ -41,10 +39,8 @@ 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>(FileStream file, string propertyName, CancellationToken cancellationToken); Task<IEnumerable<TProperty>> TryGetValues<T, TProperty>(string propertyName);
} }
} }

@ -4,7 +4,6 @@
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;
@ -13,63 +12,52 @@ namespace GBase.Interfaces.DataHandling
/// <summary> /// <summary>
/// Interface for data handlers to implement /// Interface for data handlers to implement
/// </summary> /// </summary>
public interface IDataHandler public interface IDataHandler : IAsyncDisposable
{ {
/// <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>
bool Init(bool overwrite); Task<bool> Init(bool overwrite, CancellationToken cancellationToken);
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>(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken); Task SetValue<T, TProperty>(string propertyName, TProperty value);
/// <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>(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken); Task RemoveValue<T, TProperty>(string propertyName, TProperty value);
/// <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>(FileStream file, string propertyName, CancellationToken cancellationToken); Task<TProperty> GetValue<T, TProperty>(string propertyName);
/// <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>(FileStream file, string propertyName, CancellationToken cancellationToken); Task<IEnumerable<TProperty>> GetValues<T, TProperty>(string propertyName);
} }
} }

@ -4,7 +4,6 @@
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;
@ -13,17 +12,22 @@ namespace GBase.Interfaces.DataHandling
/// <summary> /// <summary>
/// Interface for data readers to implement /// Interface for data readers to implement
/// </summary> /// </summary>
public interface IDataReader public interface IDataReader : IAsyncDisposable
{ {
/// <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>(FileStream file, string propertyName, CancellationToken cancellationToken); Task<IEnumerable<TProperty>> Read<T, TProperty>(string propertyName);
} }
} }

@ -3,7 +3,6 @@
// 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;
@ -12,53 +11,34 @@ namespace GBase.Interfaces.DataHandling
/// <summary> /// <summary>
/// Interface for data writers to implement /// Interface for data writers to implement
/// </summary> /// </summary>
public interface IDataWriter public interface IDataWriter : IAsyncDisposable
{ {
/// <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 InitFile(FileStream file, string rootElementName, CancellationToken cancellationToken); Task<bool> Init(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>(FileStream file, string propertyName, string value, bool overwrite, CancellationToken cancellationToken); Task Write<T, TProperty>(string propertyName, string value, bool overwrite);
/// <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>(FileStream file, string propertyName, string value, CancellationToken cancellationToken); Task Remove<T, TProperty>(string propertyName, string value);
} }
} }

@ -1,15 +0,0 @@
// 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<IPoolItem<IDataHandler>> RequestDataHandler(object requester, bool overwrite, CancellationToken cancellationToken);
}
}

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

@ -1,14 +0,0 @@
// 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; }
}
}

@ -6,7 +6,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.Api;
namespace GBase.Interfaces.FileHandling namespace GBase.Interfaces.FileHandling
{ {
@ -19,15 +18,46 @@ namespace GBase.Interfaces.FileHandling
/// Initialize this <see cref="IFileHandler"/> /// Initialize this <see cref="IFileHandler"/>
/// </summary> /// </summary>
/// <param name="path">The path of the database</param> /// <param name="path">The path of the database</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>
List<IGBaseFile> Init(string path, string folderName, CancellationToken cancellationToken); Task<bool> Init(string path, CancellationToken cancellationToken);
IGBaseFile CreateEntryFile<T>(T entry, IGBaseTable table) where T : IGBaseObject; /// <summary>
/// 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);
Task<bool> DeleteEntryFile<T>(T entry); /// <summary>
/// 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);
Task<IGBaseFile> RequestEntryFile<T>(T entry); /// <summary>
/// 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);
} }
} }

@ -1,19 +0,0 @@
// 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; set; }
FileStream File { get; }
string FilePath { get; }
bool InUse { get; }
IGBaseFile UseFile();
}
}

@ -48,20 +48,11 @@ 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>() where T : IGBaseObject, new();
/// <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) where T : IGBaseObject, new();
T GetEntryForKey<T>(int key) where T : IGBaseObject, new();
Task SetValue<T, TProperty>(T entry, string propertyName, TProperty value, CancellationToken cancellationToken) where T : IGBaseObject, new();
Task<TProperty> GetValue<T, TProperty>(T entry, string propertyName, CancellationToken cancellationToken) where T : IGBaseObject, new();
Task<IEnumerable<TProperty>> GetValues<T, TProperty>(T entry, string propertyName, CancellationToken cancellationToken) where T : IGBaseObject, new();
} }
} }

@ -9,10 +9,8 @@ namespace GBase.Interfaces
/// <summary> /// <summary>
/// A column of a <see cref="IGBaseTable"/> /// A column of a <see cref="IGBaseTable"/>
/// </summary> /// </summary>
public interface IGBaseColumn : IAsyncDisposable public interface IGBaseColumn : IAsyncDisposable //TODO: Make column generic (generic type is type of the value of the column?)?
{ {
string Name { get; }
Type Type { get; }
bool IsKey { get; }
} }
} }

@ -1,29 +0,0 @@
// Author: Gockner, Simon
// Created: 2020-02-14
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using System.Collections.Generic;
using GBase.Attributes;
namespace GBase.Interfaces
{
/// <summary>
/// GBase object that allows conversion from <see cref="string"/>
/// </summary>
public interface IGBaseObject
{
/// <summary>
/// <see cref="IGBase"/> Key
/// </summary>
[GBaseColumn(true)]
GBaseKey Key { get; set; }
/// <summary>
/// The FileName of the GBase file for an entry of this object
/// </summary>
string FileName { get; }
void Initialize(GBaseKey key, List<object> parameters);
}
}

@ -6,44 +6,14 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.Api;
namespace GBase.Interfaces namespace GBase.Interfaces
{ {
public interface IGBaseTable<T> : IGBaseTable where T : IGBaseObject, new()
{
/// <summary>
/// The entries of this <see cref="IGBaseTable"/>
/// </summary>
List<T> Entries { get; }
/// <summary>
/// Add an entry that implements <see cref="IGBaseObject"/> to this <see cref="IGBaseTable"/>
/// </summary>
/// <param name="entry">The entry implementing <see cref="IGBaseObject"/></param>
/// <param name="cancellationToken"></param>
/// <returns>True if successful, false if not</returns>
Task<bool> AddEntry(T entry, CancellationToken cancellationToken);
T GetEntryForKey(int key);
/// <summary>
/// Remove an entry that implements <see cref="IGBaseObject"/> from this <see cref="IGBaseTable"/>
/// </summary>
/// <param name="entry">The entry implementing <see cref="IGBaseObject"/></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>
public interface IGBaseTable : IAsyncDisposable public interface IGBaseTable : IAsyncDisposable //TODO: make generic?
{ {
/// <summary> /// <summary>
/// The <see cref="System.Type"/> of the class that this <see cref="IGBaseTable"/> represents /// The <see cref="System.Type"/> of the class that this <see cref="IGBaseTable"/> represents
@ -53,23 +23,27 @@ namespace GBase.Interfaces
/// <summary> /// <summary>
/// The name of this <see cref="IGBaseTable"/> /// The name of this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
string FolderName { get; } string Name { 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="databasePath">The path to the database files</param> /// <param name="name">The name of this <see cref="IGBaseTable"/></param>
/// <param name="folderName"></param> /// /// <param name="databasePath">The path to the database files</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 Init(Type type, string databasePath, string folderName, CancellationToken cancellationToken); Task<bool> Init(Type type, string name, string databasePath, 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"/>
@ -84,5 +58,19 @@ 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);
} }
} }

@ -1,41 +0,0 @@
# GBase Structure
```md
- GBase
|
+-GBaseTable
|
|
+-GBaseTable
|
+-GBaseColumn--GBaseColumn--GBaseColumn
+-GBaseEntry
+-GBaseEntry
```
## Terminology
| GBase Terminology | C# equivalent |
|-------------------|---------------|
| GBaseTable | Type |
| GBaseColumn | Property |
| GBaseEntry | Instance |
## Xml File Structure
```xml
<Table>
<Column>
<Value >
<Value >
</Column>
</Table>
```
## Process
### StartUp
### GetValue
### SetValue

@ -1,5 +1,3 @@
# GBase # GBase
A database based on .net A database based on .net
[![Build Status](https://drone.gockn3r.com/api/badges/SimonG/GBase/status.svg)](https://drone.gockn3r.com/SimonG/GBase)

@ -3,14 +3,12 @@
// 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;
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.Interfaces;
using GBase.Interfaces.DataHandling.Xml; using GBase.Interfaces.DataHandling.Xml;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
@ -29,12 +27,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()) dataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>()))
.Returns(new XmlDataWriter()); .Returns((string path, string rootElementName) => new XmlDataWriter(path, rootElementName));
Mock<IXmlDataReaderFactory> dataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> dataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
dataReaderFactoryMock.Setup(r => r.Create()) dataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>()))
.Returns(new XmlDataReader(Mock.Of<IGBase>())); .Returns((string path) => new XmlDataReader(path));
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>()))
@ -50,22 +48,21 @@ 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(dataReaderFactoryMock.Object, dataWriterFactoryMock.Object, dataHandlerCacheFactoryMock.Object); IXmlDataHandler xmlDataHandler = new XmlDataHandler("TestXml.xml", "Properties", dataReaderFactoryMock.Object, dataWriterFactoryMock.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>(file, nameof(TestProperty), "test", new CancellationToken()); await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), "test");
//await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), "OverwrittenString"); //await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), "OverwrittenString");
// //
await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(file, nameof(TestInt), 1, new CancellationToken()); await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt), 1);
//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>(file, nameof(TestProperty), new CancellationToken()); TestProperty = await xmlDataHandler.GetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty));
TestInt = await xmlDataHandler.GetValue<XmlDataHandlerLocalIntegrationTest, int>(file, nameof(TestInt), new CancellationToken()); TestInt = await xmlDataHandler.GetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt));
} }
} }
} }

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

@ -1,56 +0,0 @@
// 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) {Items = { model.Items[0], model.Items[1] }}, _cancellationTokenSource.Token);
await model.AddGroup(new Group(2) {Items = { model.Items[1], model.Items[2] }}, _cancellationTokenSource.Token);
await model.AddGroup(new Group(3) {Items = { model.Items[0], model.Items[2] }}, _cancellationTokenSource.Token);
}
}
}

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

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

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

@ -1,43 +0,0 @@
// Author: Gockner, Simon
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System.Collections.Generic;
using GBase;
using GBase.Attributes;
namespace Test.GBase.GBaseIntegrationTest
{
[GBaseTable("Items")]
public class Item : IItem
{
public Item()
{
}
public Item(string name, int number)
{
Name = name;
Number = number;
}
[GBaseColumn]
public string Name { get; private set; }
[GBaseColumn]
public int Number { get; private set; }
public GBaseKey Key { get; set; }
public string FileName => Name;
public override string ToString() => $"{Number}/{Name}";
public void Initialize(GBaseKey key, List<object> parameters)
{
Key = key;
Name = (string) parameters[0];
Number = (int) parameters[1];
}
}
}

@ -1,54 +0,0 @@
// 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<Item>();
Groups = new List<Group>();
}
public List<Item> Items { get; private set; }
public List<Group> 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.ToList();
//Items = (await _gBase.GetValues<Model, Item>(this, nameof(Items), cancellationToken)).Cast<IItem>().ToList();
IGBaseTable<Group> groupsTable = _gBase.GetTable<Group>();
Groups = groupsTable.Entries.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);
}
}
}

@ -1,15 +0,0 @@
// 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");
}
}

@ -2,13 +2,11 @@
// Created: 2020-03-09 // Created: 2020-03-09
// Copyright(c) 2020 SimonG. All Rights Reserved. // Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using System.Threading; using System.Threading;
using GBase; 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;
@ -25,24 +23,17 @@ 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(It.IsAny<string>(), It.IsAny<Type>(), It.IsAny<bool>())) gBaseColumnFactoryMock.Setup(c => c.Create()).Returns(new GBaseColumn());
.Callback<string, Type, bool>((name, type, isKey) => { gBaseColumn = new GBaseColumn(name, type, isKey); })
.Returns(gBaseColumn);
Mock<IDataHandlerPool> dataHandlerPoolMock = new Mock<IDataHandlerPool>(); IGBaseTable table = new GBaseTable(fileHandlerFactoryMock.Object, gBaseColumnFactoryMock.Object);
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, cancellationTokenSource.Token); table.AddEntry(foo);
Foo foo2 = new Foo("Test2"); Foo foo2 = new Foo("Test2");
table.AddEntry(foo2, cancellationTokenSource.Token); table.AddEntry(foo2);
foo.Name = "Foo - ex Test"; foo.Name = "Foo - ex Test";
foo2.Name = "Some Name"; foo2.Name = "Some Name";

@ -5,8 +5,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using GBase.Exceptions; using GBase.Exceptions;
using GBase.Helpers; using GBase.Helpers;
using GBase.Interfaces;
using Moq;
using NUnit.Framework; using NUnit.Framework;
using Test.GBase.TestClasses; using Test.GBase.TestClasses;
@ -87,7 +85,7 @@ namespace Test.GBase.Helpers
string @string = $"{list[0]},{list[1]},{list[2]}"; string @string = $"{list[0]},{list[1]},{list[2]}";
Assert.AreEqual(list, Enumerables.ConvertToGBaseEnumerable<List<string>>(@string, Mock.Of<IGBase>())); Assert.AreEqual(list, Enumerables.ConvertToGBaseEnumerable<List<string>>(@string));
} }
[Test] [Test]
@ -102,7 +100,7 @@ namespace Test.GBase.Helpers
string @string = $"{list[0]},{list[1]},{list[2]}"; string @string = $"{list[0]},{list[1]},{list[2]}";
Assert.AreEqual(list, Enumerables.ConvertToGBaseEnumerable<List<int>>(@string, Mock.Of<IGBase>())); Assert.AreEqual(list, Enumerables.ConvertToGBaseEnumerable<List<int>>(@string));
} }
[Test] [Test]
@ -117,7 +115,7 @@ namespace Test.GBase.Helpers
string @string = $"{list[0]},{list[1]},{list[2]}"; string @string = $"{list[0]},{list[1]},{list[2]}";
Assert.AreEqual(list, Enumerables.ConvertToGBaseEnumerable<List<UserType>>(@string, Mock.Of<IGBase>())); Assert.AreEqual(list, Enumerables.ConvertToGBaseEnumerable<List<UserType>>(@string));
} }
[Test] [Test]
@ -132,7 +130,7 @@ namespace Test.GBase.Helpers
string @string = $"{list[0]},{list[1]},{list[2]}"; string @string = $"{list[0]},{list[1]},{list[2]}";
InterfaceEnumerablePassedException exception = Assert.Throws<InterfaceEnumerablePassedException>(() => Enumerables.ConvertToGBaseEnumerable<List<IUserType>>(@string, Mock.Of<IGBase>())); InterfaceEnumerablePassedException exception = Assert.Throws<InterfaceEnumerablePassedException>(() => Enumerables.ConvertToGBaseEnumerable<List<IUserType>>(@string));
Assert.AreEqual(typeof(IUserType), exception.InterfaceType); Assert.AreEqual(typeof(IUserType), exception.InterfaceType);
} }
} }

@ -2,25 +2,16 @@
// Created: 2020-01-27 // Created: 2020-01-27
// Copyright(c) 2020 SimonG. All Rights Reserved. // Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using System.Collections.Generic;
using GBase;
using GBase.Api; using GBase.Api;
using GBase.Attributes; using GBase.Attributes;
using GBase.Interfaces;
namespace Test.GBase.TestClasses namespace Test.GBase.TestClasses
{ {
[GBaseTable("Foo")] [GBaseTable]
public class Foo : NotifyGBaseEntryChanged, IGBaseObject public class Foo : NotifyGBaseEntryChanged
{ {
private string _name; private string _name;
public Foo()
{
}
public Foo(string name) public Foo(string name)
{ {
Name = name; Name = name;
@ -36,13 +27,5 @@ namespace Test.GBase.TestClasses
RaiseGBaseEntryChanged(this, nameof(Name), _name); RaiseGBaseEntryChanged(this, nameof(Name), _name);
} }
} }
public GBaseKey Key { get; set; }
public string FileName => Name;
public void Initialize(GBaseKey key, List<object> parameters)
{
throw new NotImplementedException();
}
} }
} }

@ -3,7 +3,6 @@
// Copyright(c) 2020 SimonG. All Rights Reserved. // Copyright(c) 2020 SimonG. All Rights Reserved.
using GBase.Api; using GBase.Api;
using GBase.Interfaces;
namespace Test.GBase.TestClasses namespace Test.GBase.TestClasses
{ {

@ -3,9 +3,7 @@
// Copyright(c) 2020 SimonG. All Rights Reserved. // Copyright(c) 2020 SimonG. All Rights Reserved.
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using GBase;
namespace Test.GBase.TestClasses namespace Test.GBase.TestClasses
{ {
@ -23,12 +21,10 @@ namespace Test.GBase.TestClasses
private int Number { get; set; } private int Number { get; set; }
public GBaseKey Key { get; set; } public void InitializeFromString(string @string)
public string FileName { get; }
public void Initialize(GBaseKey key, List<object> parameters)
{ {
throw new NotImplementedException(); string numberString = @string.Split('_').Last();
Number = Convert.ToInt32(numberString);
} }
public override string ToString() => $"{nameof(UserType)}_{nameof(Number)}_{Number}"; public override string ToString() => $"{nameof(UserType)}_{nameof(Number)}_{Number}";

Loading…
Cancel
Save