Compare commits

..

107 Commits

Author SHA1 Message Date
SimonG a972ed5464 - add drone build badge 5 years ago
SimonG d70d51421b - add empty line 5 years ago
SimonG b2dd4debca - add drone config 5 years ago
Simon G b629c628b5 - remove all implementations of InitializeFromString() 5 years ago
Simon G 4b2a361ff7 - update xml 5 years ago
Simon G cc6a0bd01c - add test for enumerables 5 years ago
Simon G b20c240b59 - adapt unit tests 5 years ago
Simon G b14099fb25 - use keys to convert a gBase string back to an enumerable 5 years ago
Simon G 9a058caade - inject GBase, prepare for new Enumerables 5 years ago
Simon G 700d71cc9d - remove old parameter comment 5 years ago
Simon G b6a4876bd6 - add GetEntryForKey() to GBase as well 5 years ago
Simon G 85dc6b0652 - add getEntryForKey 5 years ago
Simon G f186503536 - remove InitializeFromString() 5 years ago
Simon G 278ccce013 - add GetEntryForKey() method 5 years ago
Simon G 6cb926d6ef - set lifestyle singleton for GBase 5 years ago
Simon G 5f0dae02d9 - fix method comment 5 years ago
Simon G beed882e91 - refactoring 5 years ago
Simon G 7e929919ac - update xml 5 years ago
Simon G 6233491abd - reset stream to position 0 before loading 5 years ago
Simon G 11885d6345 - fix comment 5 years ago
Simon G 7d2b91701b - adapt to init and remove todo 5 years ago
Simon G 52aedb99a9 - remove todos 5 years ago
Simon G a29700e38b - remove bool return value and todo 5 years ago
Simon G 6b34b5ec06 - remove bool return value and todo 5 years ago
Simon G 9c160ef871 - remove todo and line that doesn't work 5 years ago
Simon G 6040e31891 - check if type inherits from IGBaseObject 5 years ago
Simon G 71b8840df6 - remove wrong comments about INotifyGBaseEntryChanged 5 years ago
Simon G 848733ce5b - remove todo and unused using 5 years ago
Simon G 39974b97ba - update resharper files 5 years ago
Simon G 9a495d0af3 - update xmls 5 years ago
Simon G fb3a515ba0 - fix factory call 5 years ago
Simon G 81309b9839 - adapt to changed IGBaseObject 5 years ago
Simon G 5929e13dca - handle Keys 5 years ago
Simon G f3be965879 - add Key 5 years ago
Simon G e29b7cbafd - add GBaseKey class that is only settable once 5 years ago
Simon G 168823cfde - add isKey Property 5 years ago
Simon G f1c89018ed - add invalid and missing key exception 5 years ago
Simon G 69c4b573a5 - add isKey property 5 years ago
Simon G 4b44358af6 - add method to get inherited attributes for properties 5 years ago
Simon G af2a5768e7 - introduce FileName property to IGBaseObject that returns the file name of an entry 5 years ago
Simon G 1b0610c514 - requestDataHandler now returns IPoolItem<IDataHandler> so that InUse can be set to false again 5 years ago
Simon G 1ea6d259bc - make IPoolItem disposable and add use method, can be used with using now 5 years ago
Simon G 7aa637deb3 - install IPoolRequest 5 years ago
Simon G af42ee3297
Merge pull request #29 from SimonG96/ImproveDataHandling_#25 5 years ago
Simon G eb9d714a12 Merge remote-tracking branch 'origin/ImproveDataHandling_#25' into ImproveDataHandling_#25 5 years ago
Simon G e7bd2206b4 - adapt test classes 5 years ago
Simon G 6b9c827717 - update xml 5 years ago
Simon G be4ccf97e5 - initialize entries from existing files 5 years ago
Simon G d4ab37de84 - initialize existing files 5 years ago
Simon G a949f786f8 - add initialize() method to IGBaseObject 5 years ago
Simon G f52ab833c1 - add setter of entry to interface 5 years ago
Simon G fababa96d7 - add type to interface as well 5 years ago
Simon G baa8acae60 - add type to factory as well 5 years ago
Simon G 8ac13bf6ec - add microsoft.csharp package 5 years ago
Simon G b693b100e8 - add type of property 5 years ago
Simon G 4ce5e0914e - add setter for entry 5 years ago
Simon G 614ad24b5c - add GenericMethodCaller and matching exception 5 years ago
Simon G 01132a3784
Merge pull request #28 from SimonG96/ImproveDataHandling_#25 5 years ago
Simon G 9cdbc9d46b - update xml file structure 5 years ago
Simon G 23317c098e
Merge pull request #27 from SimonG96/ImproveDataHandling_#25 5 years ago
Simon G 2897acbea0 #25: update xml 5 years ago
Simon G 90242543c7 #25: adapt integration test 5 years ago
Simon G 225f10d1a0 #25: return true if file isn't empty, think if bool return value makes sense here 5 years ago
Simon G 1df5d49287 #25: throw missingTableException when getTable() doesn't find a matching table 5 years ago
Simon G b671d30d1d #25: add TODO: need to init existing files 5 years ago
Simon G c4ed254aac #25: add dataHandlerPool to factory 5 years ago
Simon G 62f18c0038 #25: remove need to inherit INotifyGBaseEntryChanged 5 years ago
Simon G 0c334463ee remove unused code 5 years ago
Simon G 7b97b75fb6 #25: update xml 5 years ago
Simon G 3f891b45c9 #25: fix tests 5 years ago
Simon G bfda73950a #25: fix factories and ctors 5 years ago
Simon G 5d0e766a76 #25: remove unused using 5 years ago
Simon G 0a8c1aa549 #25: use new methods from IGBaseTable 5 years ago
Simon G 92c278319e #25: use MissingTableException instead of default exception 5 years ago
Simon G 7ab02d7d3a #25: GBase can now get and set values 5 years ago
Simon G 2d4b9c820d #25: adapt DataHandlerPool 5 years ago
Simon G 93e2a1fd8c #25: adapt cache 5 years ago
Simon G ca6c75be23 #25: file handler now only handles files 5 years ago
Simon G c433add6f0 #25: make test methods async 5 years ago
Simon G 6c5df6818e #25: adapt dataReader 5 years ago
Simon G c446babb05 #25: start adapting FileHandler, add todo for possibly a better usage 5 years ago
Simon G 1cfa80c199 #25: adapt XmlDataHandler 5 years ago
Simon G 84d98a5dee #25: adapt XmlDataWriter to one file per entry strategy 5 years ago
Simon G f0783df9c2 #25: start changing data writer 5 years ago
Simon G 11a1b9c828 - pass cancellationToken where needed 5 years ago
Simon G 688ae81330 - fix usage of GBaseTable attribute 5 years ago
Simon G 8d1b24c5a1 - add const naming rule 5 years ago
Simon G 1498a914df #25: start implementing addEntry 5 years ago
Simon G b10ce3d195 #25: use dataHandler pool 5 years ago
Simon G 641dbf5a52 #25: implement IAsyncDisposable, call DataHandler.Init() 5 years ago
Simon G d873ce20c9 #25: add DataHandlerPool 5 years ago
Simon G a5b6e31690 #25: add todo 5 years ago
Simon G 06f6a4381e #25: add IDataHandlerFactory 5 years ago
Simon G a854354e85 #25: implement workaround for missing open generic registration possibility 5 years ago
Simon G 781c6b3c03 - make methods async 5 years ago
Simon G 92cca71166 - add addEntry and removeEntry methods 5 years ago
Simon G 2e2c0f74c2 - start adding complete GBase integration 5 years ago
Simon G 488fad44a1 - add MissingTableException 5 years ago
Simon G 8299f48eb3 - adapt test to generic table 5 years ago
Simon G b69830fb41 - first try add base GBaseObject implementation 5 years ago
Simon G 7c2f52a265 - try adding generic GBaseTable 5 years ago
Simon G 893fdf33d3 - create structure of gBase, to understand it 5 years ago
Simon G 7c5aa03498 - add todos 5 years ago
Simon G dc5d57e48b - idea folder 5 years ago
Simon G aed5d84383 - add fix me 5 years ago
Simon G f29039c7ab - idea changes 5 years ago
Simon G fd367b6a38
Merge pull request #26 from SimonG96/master 5 years ago
  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. 73
      GBase/DataHandling/XmlDataReader.cs
  23. 152
      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. 131
      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. 26
      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

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

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

@ -2,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/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.GBase/riderModule.iml" /> <module fileurl="file://$PROJECT_DIR$/.idea/.idea.GBase/.idea/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.GBase/.idea/riderModule.iml" />
</modules> </modules>
</component> </component>
</project> </project>

@ -0,0 +1,14 @@
<?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,17 +102,6 @@
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

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

@ -13,6 +13,11 @@ namespace GBase.Attributes
[AttributeUsage(AttributeTargets.Property)] [AttributeUsage(AttributeTargets.Property)]
public class GBaseColumnAttribute : Attribute public class GBaseColumnAttribute : Attribute
{ {
public GBaseColumnAttribute(bool isKey = false)
{
IsKey = isKey;
}
public bool IsKey { get; }
} }
} }

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

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

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

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

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

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

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

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

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

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

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

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

@ -5,12 +5,15 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.DataHandling.Cache.Factories; using GBase.DataHandling.Cache.Factories;
using GBase.DataHandling.Factories; using GBase.DataHandling.Factories;
using GBase.Helpers; using GBase.Helpers;
using GBase.Interfaces;
using GBase.Interfaces.DataHandling; using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Xml; using GBase.Interfaces.DataHandling.Xml;
using GBase.Interfaces.DataHandling.Xml.Cache; using GBase.Interfaces.DataHandling.Xml.Cache;
@ -45,19 +48,15 @@ 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(string path, public XmlDataHandler(IXmlDataReaderFactory xmlDataReaderFactory,
string rootElementName,
IXmlDataReaderFactory xmlDataReaderFactory,
IXmlDataWriterFactory xmlDataWriterFactory, IXmlDataWriterFactory xmlDataWriterFactory,
IXmlDataHandlerCacheFactory xmlDataHandlerCacheFactory) IXmlDataHandlerCacheFactory xmlDataHandlerCacheFactory)
{ {
_xmlDataWriter = xmlDataWriterFactory.Create(path, rootElementName); _xmlDataWriter = xmlDataWriterFactory.Create();
_xmlDataReader = xmlDataReaderFactory.Create(path); _xmlDataReader = xmlDataReaderFactory.Create();
_cache = xmlDataHandlerCacheFactory.Create(_xmlDataReader); _cache = xmlDataHandlerCacheFactory.Create(_xmlDataReader);
} }
@ -66,35 +65,57 @@ namespace GBase.DataHandling
/// Initialize the <see cref="XmlDataHandler"/> /// Initialize the <see cref="XmlDataHandler"/>
/// </summary> /// </summary>
/// <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param> /// <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param>
/// <returns>Returns true if successful, false if not</returns> /// <returns>Returns true if successful, false if not</returns>
public async Task<bool> Init(bool overwrite, CancellationToken cancellationToken) public bool Init(bool overwrite)
{ {
if (_isInitialized) if (_isInitialized)
return false; return false;
_overwrite = overwrite; _overwrite = overwrite;
if (!await _xmlDataWriter.Init(cancellationToken)) _isInitialized = true;
return false; return true;
}
if (!await _xmlDataReader.Init(cancellationToken)) public async Task<bool> AddEntry<T>(T entry, IGBaseTable table, FileStream entryFile, CancellationToken cancellationToken)
return false; {
await _xmlDataWriter.InitFile(entryFile, table.Type.Name, cancellationToken);
_isInitialized = true; 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 (property.PropertyType != typeof(string) && property.GetValue(entry) is IEnumerable enumerable)
valueString = enumerable.ToGBaseString();
else
valueString = property.GetValue(entry).ToString();
await _xmlDataWriter.Write<T>(entryFile, property.Name, valueString, property.PropertyType, _overwrite, cancellationToken);
}
return true; return true;
} }
public Task<bool> RemoveEntry<T>(T entry)
{
throw new NotImplementedException();
}
/// <summary> /// <summary>
/// Set the value for the given property /// Set the value for the given property
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="entryFile"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param> /// <param name="value">The value to set</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns> /// <returns>A <see cref="Task"/> to await</returns>
public async Task SetValue<T, TProperty>(string propertyName, TProperty value) public async Task SetValue<T, TProperty>(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken)
{ {
if (value == null) if (value == null)
return; return;
@ -106,7 +127,7 @@ namespace GBase.DataHandling
valueString = value.ToString(); valueString = value.ToString();
await _cache.SetValue<T, TProperty>(propertyName, value, _overwrite); await _cache.SetValue<T, TProperty>(propertyName, value, _overwrite);
await _xmlDataWriter.Write<T, TProperty>(propertyName, valueString, _overwrite); await _xmlDataWriter.Write<T, TProperty>(entryFile, propertyName, valueString, _overwrite, cancellationToken);
} }
/// <summary> /// <summary>
@ -114,10 +135,12 @@ namespace GBase.DataHandling
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="entryFile"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param> /// <param name="value">The value to set</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns> /// <returns>A <see cref="Task"/> to await</returns>
public async Task RemoveValue<T, TProperty>(string propertyName, TProperty value) public async Task RemoveValue<T, TProperty>(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken)
{ {
if (value == null) if (value == null)
return; return;
@ -129,7 +152,7 @@ namespace GBase.DataHandling
valueString = value.ToString(); valueString = value.ToString();
await _cache.TryRemoveValue<T, TProperty>(propertyName, value); await _cache.TryRemoveValue<T, TProperty>(propertyName, value);
await _xmlDataWriter.Remove<T, TProperty>(propertyName, valueString); await _xmlDataWriter.Remove<T, TProperty>(entryFile, propertyName, valueString, cancellationToken);
} }
/// <summary> /// <summary>
@ -137,11 +160,13 @@ namespace GBase.DataHandling
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="cancellationToken"></param>
/// <returns>The value for the given property</returns> /// <returns>The value for the given property</returns>
public async Task<TProperty> GetValue<T, TProperty>(string propertyName) public async Task<TProperty> GetValue<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken)
{ {
IEnumerable<TProperty> enumerable = await GetValues<T, TProperty>(propertyName); IEnumerable<TProperty> enumerable = await GetValues<T, TProperty>(file, propertyName, cancellationToken);
return enumerable == null ? default : enumerable.FirstOrDefault(); return enumerable == null ? default : enumerable.FirstOrDefault();
} }
@ -150,25 +175,17 @@ namespace GBase.DataHandling
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam> /// <typeparam name="T">The <see cref="Type"/> that implements the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="cancellationToken"></param>
/// <returns>An <see cref="IEnumerable{T}"/> with all the values for the property</returns> /// <returns>An <see cref="IEnumerable{T}"/> with all the values for the property</returns>
public async Task<IEnumerable<TProperty>> GetValues<T, TProperty>(string propertyName) public async Task<IEnumerable<TProperty>> GetValues<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken)
{ {
IEnumerable<TProperty> cachedValues = await _cache.TryGetValues<T, TProperty>(propertyName); IEnumerable<TProperty> cachedValues = await _cache.TryGetValues<T, TProperty>(file, propertyName, cancellationToken);
if (cachedValues != null) if (cachedValues != null)
return cachedValues; return cachedValues;
return await _xmlDataReader.Read<T, TProperty>(propertyName); return await _xmlDataReader.Read<T, TProperty>(file, propertyName, cancellationToken);
}
/// <summary>
/// Dispose used resources asynchronously
/// </summary>
/// <returns>A <see cref="ValueTask"/> to await</returns>
public async ValueTask DisposeAsync()
{
await _xmlDataReader.DisposeAsync();
await _xmlDataWriter.DisposeAsync();
} }
} }
} }

@ -10,76 +10,56 @@ 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>
/// A <see cref="IDataReader"/> that reads from a xml file /// An <see cref="IDataReader"/> that reads from a xml file
/// </summary> /// </summary>
public class XmlDataReader : IXmlDataReader public class XmlDataReader : IXmlDataReader
{ {
private readonly FileStream _file; private readonly IGBase _gBase;
private XDocument _xmlDocument;
private XElement _rootElement;
private bool _isInitialized;
private CancellationToken _cancellationToken;
/// <summary> /// <summary>
/// A <see cref="IDataReader"/> that reads from a xml file /// An <see cref="IDataReader"/> that reads from a xml file
/// </summary> /// </summary>
/// <param name="path">The path to the xml file</param> /// <param name="gBase">The <see cref="IGBase"/></param>
public XmlDataReader(string path) public XmlDataReader(IGBase gBase) => _gBase = gBase;
{
_file = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
}
/// <summary>
/// Initialize the <see cref="XmlDataReader"/>
/// </summary>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param>
/// <returns>Returns true if successful, false if not</returns>
/// <exception cref="Exception">No root element found</exception>
public async Task<bool> Init(CancellationToken cancellationToken)
{
if (_isInitialized)
return false;
_cancellationToken = cancellationToken;
_xmlDocument = await XDocument.LoadAsync(_file, LoadOptions.None, _cancellationToken);
_rootElement = _xmlDocument.Root;
if (_rootElement == null)
throw new Exception("No root element found.");
_isInitialized = true;
return true;
}
/// <summary> /// <summary>
/// Read the data of a property /// Read the data of a property
/// </summary> /// </summary>
/// <typeparam name="T">The <see cref="Type"/></typeparam> /// <typeparam name="T">The <see cref="Type"/></typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam> /// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="file"></param>
/// <param name="propertyName">The name of the property</param> /// <param name="propertyName">The name of the property</param>
/// <param name="cancellationToken"></param>
/// <returns>The data of the given property, null if no data found</returns> /// <returns>The data of the given property, null if no data found</returns>
/// <exception cref="ArgumentNullException"><paramref name="propertyName"/></exception> /// <exception cref="ArgumentNullException"><paramref name="propertyName"/></exception>
/// <exception cref="InvalidOperationException">Invalid <see cref="Type"/> found for the read object</exception> /// <exception cref="InvalidOperationException">Invalid <see cref="Type"/> found for the read object</exception>
public async Task<IEnumerable<TProperty>> Read<T, TProperty>(string propertyName) public async Task<IEnumerable<TProperty>> Read<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken)
//TODO: Read currently doesn't work for newly added items -> probably because file was loaded before new items were added; is probably not a problem -> cache //TODO: Read currently doesn't work for newly added items -> probably because file was loaded before new items were added; is probably not a problem -> cache
{ {
string typeName = typeof(T).FullName; string typeName = typeof(T).FullName;
if (typeName == null) if (typeName == null)
throw new ArgumentNullException(nameof(typeName)); throw new ArgumentNullException(nameof(typeName));
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 typeElement = _rootElement.Element(typeName); XElement rootElement = xmlDocument.Root;
XElement propertyElement = typeElement?.Element(propertyName); if (rootElement == null)
throw new InvalidXmlFileException("No root element is set.");
XElement propertyElement = rootElement.Element(propertyName);
XAttribute propertyTypeAttribute = propertyElement?.Attribute(XmlDataHandler.VALUE_TYPE_ATTRIBUTE_NAME); XAttribute propertyTypeAttribute = propertyElement?.Attribute(XmlDataHandler.VALUE_TYPE_ATTRIBUTE_NAME);
if (propertyTypeAttribute == null) if (propertyTypeAttribute == null)
return null; return null;
@ -95,19 +75,10 @@ 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(Enumerables.ConvertToGBaseEnumerable<TProperty>).ToList(); return values.Select(s => Enumerables.ConvertToGBaseEnumerable<TProperty>(s, _gBase)).ToList();
return values.Select(value => (TProperty)Convert.ChangeType(value, typeof(TProperty))).ToList(); return values.Select(value => (TProperty) Convert.ChangeType(value, typeof(TProperty))).ToList();
}, _cancellationToken); }, cancellationToken);
}
/// <summary>
/// Dispose used resources asynchronously
/// </summary>
/// <returns>A <see cref="ValueTask"/> to await</returns>
public async ValueTask DisposeAsync()
{
await _file.DisposeAsync();
} }
} }
} }

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

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

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

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

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

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

@ -0,0 +1,49 @@
// 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,6 +3,7 @@
// Copyright(c) 2020 SimonG. All Rights Reserved. // Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using GBase.Interfaces; using GBase.Interfaces;
namespace GBase.Factories namespace GBase.Factories
@ -16,6 +17,6 @@ namespace GBase.Factories
/// Creates an <see cref="IGBaseColumn"/> /// Creates an <see cref="IGBaseColumn"/>
/// </summary> /// </summary>
/// <returns>A newly created instance of the implementation for <see cref="IGBaseColumn"/></returns> /// <returns>A newly created instance of the implementation for <see cref="IGBaseColumn"/></returns>
IGBaseColumn Create(); IGBaseColumn Create(string name, Type type, bool isKey);
} }
} }

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

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

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

@ -0,0 +1,32 @@
// Author: Gockner, Simon
// Created: 2020-11-10
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System.IO;
using GBase.Interfaces.FileHandling;
namespace GBase.FileHandling
{
public class GBaseFile : IGBaseFile
{
public GBaseFile(object entry, FileStream file, string filePath)
{
Entry = entry;
File = file;
FilePath = filePath;
}
public object Entry { get; 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,6 +9,7 @@ using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.Attributes; using GBase.Attributes;
using GBase.Exceptions;
using GBase.Factories; using GBase.Factories;
using GBase.Interfaces; using GBase.Interfaces;
using GBase.Interfaces.Settings; using GBase.Interfaces.Settings;
@ -20,11 +21,6 @@ namespace GBase
/// </summary> /// </summary>
public class GBase : IGBase public class GBase : IGBase
{ {
/// <summary>
/// The file extension for all GBase tables
/// </summary>
public const string GBASE_TABLE_FILE_EXTENSION = "gb"; //TODO: Find correct place for this const
private readonly IGBaseTableFactory _gBaseTableFactory; private readonly IGBaseTableFactory _gBaseTableFactory;
/// <summary> /// <summary>
@ -74,8 +70,8 @@ namespace GBase
if (gBaseTableAttribute == null) if (gBaseTableAttribute == null)
continue; continue;
IGBaseTable gBaseTable = _gBaseTableFactory.Create(); IGBaseTable gBaseTable = _gBaseTableFactory.Create(type);
await gBaseTable.Init(type, type.Name, Settings.DatabasePath, cancellationToken); await gBaseTable.Init(type, Settings.DatabasePath, gBaseTableAttribute.FolderName, cancellationToken);
AddTable(gBaseTable); AddTable(gBaseTable);
} }
@ -93,13 +89,21 @@ namespace GBase
if (Tables.Contains(table)) if (Tables.Contains(table))
return false; return false;
if (Tables.Any(t => t.Name.Equals(table.Name))) if (Tables.Any(t => t.FolderName.Equals(table.FolderName)))
return false; return false;
Tables.Add(table); Tables.Add(table);
return true; return true;
} }
public IGBaseTable<T> GetTable<T>() 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>
@ -113,6 +117,52 @@ 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,6 +24,7 @@
<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,13 +87,15 @@
<param name="value">The value to set</param> <param name="value">The value to set</param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.DataHandling.Cache.XmlDataHandlerCache.TryGetValues``2(System.String)"> <member name="M:GBase.DataHandling.Cache.XmlDataHandlerCache.TryGetValues``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Try to get values from the cache for the given property Try to get values from the cache for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns> <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns>
</member> </member>
<member name="T:GBase.DataHandling.Cache.XmlDataHandlerCacheEntry"> <member name="T:GBase.DataHandling.Cache.XmlDataHandlerCacheEntry">
@ -163,11 +165,10 @@
Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/> Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.DataHandling.Factories.IXmlDataReaderFactory.Create(System.String)"> <member name="M:GBase.DataHandling.Factories.IXmlDataReaderFactory.Create">
<summary> <summary>
Creates an <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/> Creates an <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/>
</summary> </summary>
<param name="path">The path to the xml file</param>
<returns>A newly created instance of the implementation for <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/></returns> <returns>A newly created instance of the implementation for <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/></returns>
</member> </member>
<member name="T:GBase.DataHandling.Factories.IXmlDataWriterFactory"> <member name="T:GBase.DataHandling.Factories.IXmlDataWriterFactory">
@ -175,12 +176,10 @@
Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/> Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.DataHandling.Factories.IXmlDataWriterFactory.Create(System.String,System.String)"> <member name="M:GBase.DataHandling.Factories.IXmlDataWriterFactory.Create">
<summary> <summary>
Creates an <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/> Creates an <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/>
</summary> </summary>
<param name="path">The path to the xml file</param>
<param name="rootElementName">The root element name of the xml file</param>
<returns>A newly created instance of the implementation for <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/></returns> <returns>A newly created instance of the implementation for <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/></returns>
</member> </member>
<member name="T:GBase.DataHandling.XmlDataHandler"> <member name="T:GBase.DataHandling.XmlDataHandler">
@ -198,152 +197,158 @@
The attribute name of the value <see cref="T:System.Type"/> attribute The attribute name of the value <see cref="T:System.Type"/> attribute
</summary> </summary>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.#ctor(System.String,System.String,GBase.DataHandling.Factories.IXmlDataReaderFactory,GBase.DataHandling.Factories.IXmlDataWriterFactory,GBase.DataHandling.Cache.Factories.IXmlDataHandlerCacheFactory)"> <member name="M:GBase.DataHandling.XmlDataHandler.#ctor(GBase.DataHandling.Factories.IXmlDataReaderFactory,GBase.DataHandling.Factories.IXmlDataWriterFactory,GBase.DataHandling.Cache.Factories.IXmlDataHandlerCacheFactory)">
<summary> <summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/> that handles its data in an xml file A <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/> that handles its data in an xml file
</summary> </summary>
<param name="path">The path to the xml file</param>
<param name="rootElementName">The root element name of the xml file</param>
<param name="xmlDataReaderFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/> factory</param> <param name="xmlDataReaderFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/> factory</param>
<param name="xmlDataWriterFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/> factory</param> <param name="xmlDataWriterFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/> factory</param>
<param name="xmlDataHandlerCacheFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.Cache.IXmlDataHandlerCache"/> factory</param> <param name="xmlDataHandlerCacheFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.Cache.IXmlDataHandlerCache"/> factory</param>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.Init(System.Boolean,System.Threading.CancellationToken)"> <member name="M:GBase.DataHandling.XmlDataHandler.Init(System.Boolean)">
<summary> <summary>
Initialize the <see cref="T:GBase.DataHandling.XmlDataHandler"/> Initialize the <see cref="T:GBase.DataHandling.XmlDataHandler"/>
</summary> </summary>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param> <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param>
<returns>Returns true if successful, false if not</returns> <returns>Returns true if successful, false if not</returns>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.SetValue``2(System.String,``1)"> <member name="M:GBase.DataHandling.XmlDataHandler.SetValue``2(System.IO.FileStream,System.String,``1,System.Threading.CancellationToken)">
<summary> <summary>
Set the value for the given property Set the value for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="entryFile"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value to set</param> <param name="value">The value to set</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.RemoveValue``2(System.String,``1)"> <member name="M:GBase.DataHandling.XmlDataHandler.RemoveValue``2(System.IO.FileStream,System.String,``1,System.Threading.CancellationToken)">
<summary> <summary>
Remove the value for the given property Remove the value for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="entryFile"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value to set</param> <param name="value">The value to set</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.GetValue``2(System.String)"> <member name="M:GBase.DataHandling.XmlDataHandler.GetValue``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Get the value for the given property, if multiple values are set the first is returned Get the value for the given property, if multiple values are set the first is returned
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>The value for the given property</returns> <returns>The value for the given property</returns>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.GetValues``2(System.String)"> <member name="M:GBase.DataHandling.XmlDataHandler.GetValues``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Get all the values that are set for the given property Get all the values that are set for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns> <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataHandler.DisposeAsync">
<summary>
Dispose used resources asynchronously
</summary>
<returns>A <see cref="T:System.Threading.Tasks.ValueTask"/> to await</returns>
</member>
<member name="T:GBase.DataHandling.XmlDataReader"> <member name="T:GBase.DataHandling.XmlDataReader">
<summary> <summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file An <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.Init(System.Threading.CancellationToken)"> <member name="M:GBase.DataHandling.XmlDataReader.#ctor(GBase.Interfaces.IGBase)">
<summary> <summary>
Initialize the <see cref="T:GBase.DataHandling.XmlDataReader"/> An <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file
</summary> </summary>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param> <param name="gBase">The <see cref="T:GBase.Interfaces.IGBase"/></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.String)"> <member name="M:GBase.DataHandling.XmlDataReader.Read``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Read the data of a property Read the data of a property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/></typeparam> <typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>The data of the given property, null if no data found</returns> <returns>The data of the given property, null if no data found</returns>
<exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception> <exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception>
<exception cref="T:System.InvalidOperationException">Invalid <see cref="T:System.Type"/> found for the read object</exception> <exception cref="T:System.InvalidOperationException">Invalid <see cref="T:System.Type"/> found for the read object</exception>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataReader.DisposeAsync">
<summary>
Dispose used resources asynchronously
</summary>
<returns>A <see cref="T:System.Threading.Tasks.ValueTask"/> to await</returns>
</member>
<member name="T:GBase.DataHandling.XmlDataWriter"> <member name="T:GBase.DataHandling.XmlDataWriter">
<summary> <summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataWriter"/> that writes to a xml file A <see cref="T:GBase.Interfaces.DataHandling.IDataWriter"/> that writes to a xml file
</summary> </summary>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataWriter.#ctor(System.String,System.String)"> <member name="M:GBase.DataHandling.XmlDataWriter.InitFile(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataWriter"/> that writes to an xml file
</summary>
<param name="path">The path to the xml file</param>
<param name="rootElementName">The root element name of the xml file</param>
</member>
<member name="M:GBase.DataHandling.XmlDataWriter.Init(System.Threading.CancellationToken)">
<summary> <summary>
Initialize the <see cref="T:GBase.DataHandling.XmlDataWriter"/> Initialize the <see cref="T:GBase.DataHandling.XmlDataWriter"/>
</summary> </summary>
<param name="file"></param>
<param name="rootElementName"></param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param> <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param>
<returns>Returns true if successful, false if not</returns> <returns>Returns true if successful, false if not</returns>
<exception cref="T:System.Exception">No root element found</exception> <exception cref="T:System.Exception">No root element found</exception>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataWriter.Write``2(System.String,System.String,System.Boolean)"> <member name="M:GBase.DataHandling.XmlDataWriter.Write``2(System.IO.FileStream,System.String,System.String,System.Boolean,System.Threading.CancellationToken)">
<summary> <summary>
Write the data of a property Write the data of a property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value of the property</param> <param name="value">The value of the property</param>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param> <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member>
<member name="M:GBase.DataHandling.XmlDataWriter.Write``1(System.IO.FileStream,System.String,System.String,System.Type,System.Boolean,System.Threading.CancellationToken)">
<summary>
Write the data of a property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param>
<param name="value">The value of the property</param>
<param name="propertyType"></param>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
<exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception> <exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception>
<exception cref="T:GBase.DataHandling.Exceptions.InvalidXmlFileException">No root element is set</exception>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataWriter.Remove``2(System.String,System.String)"> <member name="M:GBase.DataHandling.XmlDataWriter.Remove``2(System.IO.FileStream,System.String,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Remove the value for the given property Remove the value for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value to set</param> <param name="value">The value to set</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
<exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception> <exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception>
<exception cref="T:GBase.DataHandling.Exceptions.InvalidXmlFileException">No root element is set</exception>
</member> </member>
<member name="M:GBase.DataHandling.XmlDataWriter.DisposeAsync"> <member name="T:GBase.Exceptions.GenericMethodNotFoundException">
<summary> <summary>
Dispose used resources asynchronously Could not find generic method
</summary> </summary>
<returns>A <see cref="T:System.Threading.Tasks.ValueTask"/> to await</returns> </member>
<member name="M:GBase.Exceptions.GenericMethodNotFoundException.#ctor(System.String)">
<summary>
Could not find generic method
</summary>
<param name="functionName">The name of the generic method</param>
</member> </member>
<member name="T:GBase.Exceptions.InterfaceEnumerablePassedException"> <member name="T:GBase.Exceptions.InterfaceEnumerablePassedException">
<summary> <summary>
@ -361,12 +366,52 @@
The <see cref="T:System.Type"/> of the passed interface The <see cref="T:System.Type"/> of the passed interface
</summary> </summary>
</member> </member>
<member name="T:GBase.Exceptions.InvalidTableTypeException">
<summary>
<see cref="T:System.Exception"/> that the passed table type doesn't implement <see cref="T:GBase.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"> <member name="M:GBase.Factories.IGBaseColumnFactory.Create(System.String,System.Type,System.Boolean)">
<summary> <summary>
Creates an <see cref="T:GBase.Interfaces.IGBaseColumn"/> Creates an <see cref="T:GBase.Interfaces.IGBaseColumn"/>
</summary> </summary>
@ -389,7 +434,7 @@
Factory for the <see cref="T:GBase.Interfaces.IGBaseTable"/> Factory for the <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.Factories.IGBaseTableFactory.Create"> <member name="M:GBase.Factories.IGBaseTableFactory.Create(System.Type)">
<summary> <summary>
Creates an <see cref="T:GBase.Interfaces.IGBaseTable"/> Creates an <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
@ -411,63 +456,25 @@
Internal file handler Internal file handler
</summary> </summary>
</member> </member>
<member name="M:GBase.FileHandling.FileHandler.#ctor(GBase.DataHandling.Factories.IXmlDataHandlerFactory)"> <member name="F:GBase.FileHandling.FileHandler.GBASE_TABLE_FILE_EXTENSION">
<summary> <summary>
Internal file handler The file extension for all GBase tables
</summary> </summary>
<param name="xmlDataHandlerFactory">Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataHandler"/></param>
</member> </member>
<member name="P:GBase.FileHandling.FileHandler.DataHandler"> <member name="M:GBase.FileHandling.FileHandler.#ctor">
<summary> <summary>
The <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/> of this <see cref="T:GBase.Interfaces.FileHandling.IFileHandler"/> Internal file handler
</summary> </summary>
</member> </member>
<member name="M:GBase.FileHandling.FileHandler.Init(System.String,System.Threading.CancellationToken)"> <member name="M:GBase.FileHandling.FileHandler.Init(System.String,System.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
@ -479,11 +486,6 @@
The base class of the GBase database The base class of the GBase database
</summary> </summary>
</member> </member>
<member name="F:GBase.GBase.GBASE_TABLE_FILE_EXTENSION">
<summary>
The file extension for all GBase tables
</summary>
</member>
<member name="M:GBase.GBase.#ctor(GBase.Interfaces.Settings.IGBaseSettings,GBase.Factories.IGBaseTableFactory)"> <member name="M:GBase.GBase.#ctor(GBase.Interfaces.Settings.IGBaseSettings,GBase.Factories.IGBaseTableFactory)">
<summary> <summary>
The base class of the GBase database The base class of the GBase database
@ -540,7 +542,7 @@
A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/> A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.GBaseColumn.#ctor"> <member name="M:GBase.GBaseColumn.#ctor(System.String,System.Type,System.Boolean)">
<summary> <summary>
A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/> A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
@ -551,91 +553,96 @@
</summary> </summary>
<returns>A <see cref="T:System.Threading.Tasks.ValueTask"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.ValueTask"/> to await</returns>
</member> </member>
<member name="T:GBase.GBaseTable"> <member name="T:GBase.GBaseObject`1">
<summary>
GBase object that supplies inheriting classes with methods to get data from a <see cref="T:GBase.Interfaces.IGBase"/>
</summary>
</member>
<member name="M:GBase.GBaseObject`1.#ctor(GBase.Interfaces.IGBase)">
<summary>
GBase object that allows conversion from <see cref="T:System.String"/>
</summary>
<exception cref="T:GBase.Exceptions.MissingTableException`1">No table for <typeparamref name="T"/> is existing</exception>
</member>
<member name="M:GBase.GBaseObject`1.InitializeFromString(System.String)">
<summary>
Initialize this <see cref="T:GBase.GBaseObject`1"/> from a given <see cref="T:System.String"/>
</summary>
<param name="string">The given <see cref="T:System.String"/></param>
</member>
<member name="T:GBase.GBaseTable`1">
<summary> <summary>
A <see cref="T:GBase.Interfaces.IGBase"/> table A <see cref="T:GBase.Interfaces.IGBase"/> table
</summary> </summary>
</member> </member>
<member name="M:GBase.GBaseTable.#ctor(GBase.FileHandling.Factories.IFileHandlerFactory,GBase.Factories.IGBaseColumnFactory)"> <member name="M:GBase.GBaseTable`1.#ctor(GBase.FileHandling.Factories.IFileHandlerFactory,GBase.Interfaces.DataHandling.Pool.IDataHandlerPool,GBase.Factories.IGBaseColumnFactory)">
<summary> <summary>
A <see cref="T:GBase.Interfaces.IGBase"/> table A <see cref="T:GBase.Interfaces.IGBase"/> table
</summary> </summary>
<param name="fileHandlerFactory"></param>
<param name="dataHandlerPool">The <see cref="T:GBase.Interfaces.DataHandling.Pool.IDataHandlerPool"/></param>
<param name="gBaseColumnFactory"></param>
</member> </member>
<member name="P:GBase.GBaseTable.Type"> <member name="P:GBase.GBaseTable`1.Type">
<summary> <summary>
The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents
</summary> </summary>
</member> </member>
<member name="P:GBase.GBaseTable.Name"> <member name="P:GBase.GBaseTable`1.FolderName">
<summary> <summary>
The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/> The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="P:GBase.GBaseTable.Columns"> <member name="P:GBase.GBaseTable`1.Columns">
<summary> <summary>
The <see cref="T:GBase.Interfaces.IGBaseColumn"/>s of this <see cref="T:GBase.Interfaces.IGBaseTable"/> The <see cref="T:GBase.Interfaces.IGBaseColumn"/>s of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="P:GBase.GBaseTable.Entries"> <member name="P:GBase.GBaseTable`1.Entries">
<summary> <summary>
The entries of this <see cref="T:GBase.Interfaces.IGBaseTable"/> The entries of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.GBaseTable.Init(System.Type,System.String,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.GBaseTable`1.Init(System.Type,System.String,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Initialize this <see cref="T:GBase.Interfaces.IGBase"/> Initialize this <see cref="T:GBase.Interfaces.IGBase"/>
</summary> </summary>
<param name="type">The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents</param> <param name="type">The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents</param>
<param name="name">The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/></param>
<param name="databasePath">The path to the database files</param> <param name="databasePath">The path to the database files</param>
<param name="folderName"></param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the asynchronous operation</param> <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the asynchronous operation</param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.GBaseTable.AddColumn(GBase.Interfaces.IGBaseColumn)"> <member name="M:GBase.GBaseTable`1.AddColumn(GBase.Interfaces.IGBaseColumn)">
<summary> <summary>
Add a given <see cref="T:GBase.Interfaces.IGBaseColumn"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/> Add a given <see cref="T:GBase.Interfaces.IGBaseColumn"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
<param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param> <param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.GBaseTable.RemoveColumn(GBase.Interfaces.IGBaseColumn)"> <member name="M:GBase.GBaseTable`1.RemoveColumn(GBase.Interfaces.IGBaseColumn)">
<summary> <summary>
Remove a given <see cref="T:GBase.Interfaces.IGBaseColumn"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/> Remove a given <see cref="T:GBase.Interfaces.IGBaseColumn"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
<param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param> <param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.GBaseTable.AddEntry(GBase.Api.INotifyGBaseEntryChanged)"> <member name="M:GBase.GBaseTable`1.AddEntry(`0,System.Threading.CancellationToken)">
<summary> <summary>
Add an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/> Add an entry that implements <see cref="T:GBase.Interfaces.IGBaseObject"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
<param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param> <param name="entry">The entry implementing <see cref="T:GBase.Interfaces.IGBaseObject"/></param>
<param name="cancellationToken"></param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.GBaseTable.RemoveEntry(GBase.Api.INotifyGBaseEntryChanged)"> <member name="M:GBase.GBaseTable`1.RemoveEntry(`0)">
<summary> <summary>
Remove an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/> Remove an entry that implements <see cref="T:GBase.Interfaces.IGBaseObject"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
<param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param> <param name="entry">The entry implementing <see cref="T:GBase.Interfaces.IGBaseObject"/></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.OnGBaseEntryChanged(System.Object,GBase.Api.GBaseEntryChangedEventArgs)"> <member name="M:GBase.GBaseTable`1.DisposeAsync">
<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>
@ -646,17 +653,73 @@
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></returns> <returns>The converted <see cref="T:System.Collections.IEnumerable"/> as a GBase <see cref="T:System.String"/></returns>
</member> </member>
<member name="M:GBase.Helpers.Enumerables.ConvertToGBaseEnumerable``1(System.String)"> <member name="M:GBase.Helpers.Enumerables.ConvertToGBaseEnumerable``1(System.String,GBase.Interfaces.IGBase)">
<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
@ -707,13 +770,15 @@
<param name="value">The value to set</param> <param name="value">The value to set</param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.Cache.IDataHandlerCache.TryGetValues``2(System.String)"> <member name="M:GBase.Interfaces.DataHandling.Cache.IDataHandlerCache.TryGetValues``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Try to get values from the cache for the given property Try to get values from the cache for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns> <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns>
</member> </member>
<member name="T:GBase.Interfaces.DataHandling.Cache.IDataHandlerCacheEntry"> <member name="T:GBase.Interfaces.DataHandling.Cache.IDataHandlerCacheEntry">
@ -756,50 +821,57 @@
Interface for data handlers to implement Interface for data handlers to implement
</summary> </summary>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.Init(System.Boolean,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.Init(System.Boolean)">
<summary> <summary>
Initialize the <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/> Initialize the <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/>
</summary> </summary>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param> <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param>
<returns>Returns true if successful, false if not</returns> <returns>Returns true if successful, false if not</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.SetValue``2(System.String,``1)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.SetValue``2(System.IO.FileStream,System.String,``1,System.Threading.CancellationToken)">
<summary> <summary>
Set the value for the given property Set the value for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="entryFile"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value to set</param> <param name="value">The value to set</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.RemoveValue``2(System.String,``1)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.RemoveValue``2(System.IO.FileStream,System.String,``1,System.Threading.CancellationToken)">
<summary> <summary>
Remove the value for the given property Remove the value for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="entryFile"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value to set</param> <param name="value">The value to set</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValue``2(System.String)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValue``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Get the value for the given property, if multiple values are set the first is returned Get the value for the given property, if multiple values are set the first is returned
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>The value for the given property</returns> <returns>The value for the given property</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValues``2(System.String)"> <member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValues``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Get all the values that are set for the given property Get all the values that are set for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns> <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> with all the values for the property</returns>
</member> </member>
<member name="T:GBase.Interfaces.DataHandling.IDataReader"> <member name="T:GBase.Interfaces.DataHandling.IDataReader">
@ -807,20 +879,15 @@
Interface for data readers to implement Interface for data readers to implement
</summary> </summary>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataReader.Init(System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataReader.Read``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary>
Initialize the <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/>
</summary>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param>
<returns>Returns true if successful, false if not</returns>
</member>
<member name="M:GBase.Interfaces.DataHandling.IDataReader.Read``2(System.String)">
<summary> <summary>
Read the data of a property Read the data of a property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/></typeparam> <typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>The data of the given property, null if no data found</returns> <returns>The data of the given property, null if no data found</returns>
</member> </member>
<member name="T:GBase.Interfaces.DataHandling.IDataWriter"> <member name="T:GBase.Interfaces.DataHandling.IDataWriter">
@ -828,32 +895,51 @@
Interface for data writers to implement Interface for data writers to implement
</summary> </summary>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.Init(System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.DataHandling.IDataWriter.InitFile(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Initialize the <see cref="T:GBase.Interfaces.DataHandling.IDataWriter"/> Initialize the <see cref="T:GBase.Interfaces.DataHandling.IDataWriter"/>
</summary> </summary>
<param name="file"></param>
<param name="rootElementName"></param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param> <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param>
<returns>Returns true if successful, false if not</returns> <returns>Returns true if successful, false if not</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.Write``2(System.String,System.String,System.Boolean)"> <member name="M:GBase.Interfaces.DataHandling.IDataWriter.Write``2(System.IO.FileStream,System.String,System.String,System.Boolean,System.Threading.CancellationToken)">
<summary> <summary>
Write the data of a property Write the data of a property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/></typeparam> <typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value of the property</param> <param name="value">The value of the property</param>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param> <param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.Remove``2(System.String,System.String)"> <member name="M:GBase.Interfaces.DataHandling.IDataWriter.Write``1(System.IO.FileStream,System.String,System.String,System.Type,System.Boolean,System.Threading.CancellationToken)">
<summary>
Write the data of a property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param>
<param name="value">The value of the property</param>
<param name="propertyType"></param>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member>
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.Remove``2(System.IO.FileStream,System.String,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Remove the value for the given property Remove the value for the given property
</summary> </summary>
<typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="T">The <see cref="T:System.Type"/> of the property</typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam> <typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param> <param name="propertyName">The name of the property</param>
<param name="value">The value to set</param> <param name="value">The value to set</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns> <returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member> </member>
<member name="T:GBase.Interfaces.DataHandling.Xml.Cache.IXmlDataHandlerCache"> <member name="T:GBase.Interfaces.DataHandling.Xml.Cache.IXmlDataHandlerCache">
@ -891,52 +977,15 @@
Internal file handler Internal file handler
</summary> </summary>
</member> </member>
<member name="M:GBase.Interfaces.FileHandling.IFileHandler.Init(System.String,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.FileHandling.IFileHandler.Init(System.String,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
@ -985,6 +1034,47 @@
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
@ -995,7 +1085,7 @@
The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents
</summary> </summary>
</member> </member>
<member name="P:GBase.Interfaces.IGBaseTable.Name"> <member name="P:GBase.Interfaces.IGBaseTable.FolderName">
<summary> <summary>
The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/> The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
@ -1005,19 +1095,15 @@
The <see cref="T:GBase.Interfaces.IGBaseColumn"/>s of this <see cref="T:GBase.Interfaces.IGBaseTable"/> The <see cref="T:GBase.Interfaces.IGBaseColumn"/>s of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="P:GBase.Interfaces.IGBaseTable.Entries">
<summary>
The entries of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
</member>
<member name="M:GBase.Interfaces.IGBaseTable.Init(System.Type,System.String,System.String,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.IGBaseTable.Init(System.Type,System.String,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Initialize this <see cref="T:GBase.Interfaces.IGBase"/> Initialize this <see cref="T:GBase.Interfaces.IGBase"/>
</summary> </summary>
<param name="type">The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents</param> <param name="type">The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents</param>
<param name="name">The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/></param> <param name="databasePath">The path to the database files</param>
/// <param name="databasePath">The path to the database files</param> <param name="folderName"></param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the asynchronous operation</param> <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the asynchronous operation</param>
///
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.Interfaces.IGBaseTable.AddColumn(GBase.Interfaces.IGBaseColumn)"> <member name="M:GBase.Interfaces.IGBaseTable.AddColumn(GBase.Interfaces.IGBaseColumn)">
@ -1034,20 +1120,6 @@
<param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param> <param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.Interfaces.IGBaseTable.AddEntry(GBase.Api.INotifyGBaseEntryChanged)">
<summary>
Add an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<returns>True if successful, false if not</returns>
</member>
<member name="M:GBase.Interfaces.IGBaseTable.RemoveEntry(GBase.Api.INotifyGBaseEntryChanged)">
<summary>
Remove an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<returns>True if successful, false if not</returns>
</member>
<member name="T:GBase.Interfaces.Settings.IGBaseSettings"> <member name="T:GBase.Interfaces.Settings.IGBaseSettings">
<summary> <summary>
Settings of a <see cref="T:GBase.Interfaces.IGBase"/> instance Settings of a <see cref="T:GBase.Interfaces.IGBase"/> instance

@ -16,11 +16,17 @@ namespace GBase
/// <summary> /// <summary>
/// A column of a <see cref="IGBaseTable"/> /// A column of a <see cref="IGBaseTable"/>
/// </summary> /// </summary>
public GBaseColumn() public GBaseColumn(string name, Type type, bool isKey)
{ {
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
/// </summary> /// </summary>

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

@ -0,0 +1,45 @@
// 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,16 +4,18 @@
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
@ -21,21 +23,26 @@ namespace GBase
/// <summary> /// <summary>
/// A <see cref="IGBase"/> table /// A <see cref="IGBase"/> table
/// </summary> /// </summary>
public class GBaseTable : IGBaseTable public class GBaseTable<T> : IGBaseTable<T> where T : IGBaseObject, new()
{ {
private readonly IFileHandler _fileHandler; private readonly IFileHandler _fileHandler;
private readonly IDataHandlerPool _dataHandlerPool;
private readonly IGBaseColumnFactory _gBaseColumnFactory; private readonly IGBaseColumnFactory _gBaseColumnFactory;
/// <summary> /// <summary>
/// A <see cref="IGBase"/> table /// A <see cref="IGBase"/> table
/// </summary> /// </summary>
public GBaseTable(IFileHandlerFactory fileHandlerFactory, IGBaseColumnFactory gBaseColumnFactory) /// <param name="fileHandlerFactory"></param>
/// <param name="dataHandlerPool">The <see cref="IDataHandlerPool"/></param>
/// <param name="gBaseColumnFactory"></param>
public GBaseTable(IFileHandlerFactory fileHandlerFactory, IDataHandlerPool dataHandlerPool, IGBaseColumnFactory gBaseColumnFactory)
{ {
_fileHandler = fileHandlerFactory.Create(); _fileHandler = fileHandlerFactory.Create();
_dataHandlerPool = dataHandlerPool;
_gBaseColumnFactory = gBaseColumnFactory; _gBaseColumnFactory = gBaseColumnFactory;
Columns = new List<IGBaseColumn>(); Columns = new List<IGBaseColumn>();
Entries = new List<object>(); Entries = new List<T>();
} }
@ -47,7 +54,7 @@ namespace GBase
/// <summary> /// <summary>
/// The name of this <see cref="IGBaseTable"/> /// The name of this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
public string Name { get; private set; } public string FolderName { get; private set; }
/// <summary> /// <summary>
/// The <see cref="IGBaseColumn"/>s of this <see cref="IGBaseTable"/> /// The <see cref="IGBaseColumn"/>s of this <see cref="IGBaseTable"/>
@ -57,38 +64,85 @@ namespace GBase
/// <summary> /// <summary>
/// The entries of this <see cref="IGBaseTable"/> /// The entries of this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
public List<object> Entries { get; } public List<T> Entries { get; }
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<bool> Init(Type type, string name, string databasePath, CancellationToken cancellationToken) public async Task Init(Type type, string databasePath, string folderName, CancellationToken cancellationToken)
{ {
Type = type; Type = type;
Name = name; FolderName = folderName;
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(); IGBaseColumn gBaseColumn = _gBaseColumnFactory.Create(property.Name, property.PropertyType, gBaseColumnAttribute.IsKey);
AddColumn(gBaseColumn); AddColumn(gBaseColumn);
} }
return true; List<IGBaseFile> files = _fileHandler.Init(databasePath, FolderName, cancellationToken);
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>
@ -96,7 +150,7 @@ namespace GBase
/// </summary> /// </summary>
/// <param name="column">The given <see cref="IGBaseColumn"/></param> /// <param name="column">The given <see cref="IGBaseColumn"/></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
public bool AddColumn(IGBaseColumn column) public bool AddColumn(IGBaseColumn column) //TODO: if a column is added, it has to be added to every entry file as well
{ {
if (Columns.Contains(column)) if (Columns.Contains(column))
return false; return false;
@ -110,7 +164,7 @@ namespace GBase
/// </summary> /// </summary>
/// <param name="column">The given <see cref="IGBaseColumn"/></param> /// <param name="column">The given <see cref="IGBaseColumn"/></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
public bool RemoveColumn(IGBaseColumn column) public bool RemoveColumn(IGBaseColumn column) //TODO: if a column is removed, it has to be removed from every entry file as well
{ {
if (!Columns.Contains(column)) if (!Columns.Contains(column))
return false; return false;
@ -119,58 +173,65 @@ namespace GBase
} }
/// <summary> /// <summary>
/// Add an entry that implements <see cref="INotifyGBaseEntryChanged"/> to this <see cref="IGBaseTable"/> /// Add an entry that implements <see cref="IGBaseObject"/> to this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
/// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param> /// <param name="entry">The entry implementing <see cref="IGBaseObject"/></param>
/// <param name="cancellationToken"></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
public bool AddEntry(INotifyGBaseEntryChanged entry) //TODO: Write to file public async Task<bool> AddEntry(T entry, CancellationToken cancellationToken)
{ {
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="INotifyGBaseEntryChanged"/> from this <see cref="IGBaseTable"/> /// Remove an entry that implements <see cref="IGBaseObject"/> from this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
/// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param> /// <param name="entry">The entry implementing <see cref="IGBaseObject"/></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
public bool RemoveEntry(INotifyGBaseEntryChanged entry) //TODO: remove from file public async Task<bool> RemoveEntry(T entry)
{ {
if (!Entries.Contains(entry)) if (!Entries.Contains(entry))
return false; return false;
entry.GBaseEntryChanged -= OnGBaseEntryChanged; await _fileHandler.DeleteEntryFile(entry);
return Entries.Remove(entry); return Entries.Remove(entry);
} }
/// <summary> public async Task SetValue<TProperty>(T entry, string propertyName, TProperty value, CancellationToken cancellationToken)
/// Modify the property of a given entry with the given value
/// </summary>
/// <param name="entry">The entry</param>
/// <param name="propertyName">The name of the property</param>
/// <param name="value">The new value to set</param>
/// <returns>True if successful, false if not</returns>
private bool ModifyEntry(object entry, string propertyName, object value) //TODO: Write to file
{ {
//don't need to change value of property in `Entries` list, the instance is saved there, any property change is already changed there as well using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
return true; using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
await dataHandlerItem.Use().SetValue<T, TProperty>(file.File, propertyName, value, cancellationToken);
} }
/// <summary> public async Task<TProperty> GetValue<TProperty>(T entry, string propertyName, CancellationToken cancellationToken)
/// A <see cref="IGBase"/> entry changed
/// </summary>
/// <param name="entry">The entry (sender)</param>
/// <param name="args">The <see cref="GBaseEntryChangedEventArgs"/></param>
private void OnGBaseEntryChanged(object entry, GBaseEntryChangedEventArgs args)
{ {
//TODO: Might change, depending on #23 using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
bool success = ModifyEntry(entry, args.ColumnName, args.Value); using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
return await dataHandlerItem.Use().GetValue<T, TProperty>(file.File, propertyName, cancellationToken);
}
if (!success) public async Task<IEnumerable<TProperty>> GetValues<TProperty>(T entry, string propertyName, CancellationToken cancellationToken)
throw new Exception("Failed to handle EntryChanged"); //TODO: Decide what to do here {
using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
return await dataHandlerItem.Use().GetValues<T, TProperty>(file.File, propertyName, cancellationToken);
} }
/// <summary> /// <summary>
@ -180,6 +241,7 @@ namespace GBase
public async ValueTask DisposeAsync() public async ValueTask DisposeAsync()
{ {
await _fileHandler.DisposeAsync(); await _fileHandler.DisposeAsync();
await _dataHandlerPool.DisposeAsync();
foreach (var column in Columns) foreach (var column in Columns)
{ {
@ -188,9 +250,9 @@ namespace GBase
Columns.Clear(); Columns.Clear();
foreach (var entry in Entries.OfType<INotifyGBaseEntryChanged>().ToList()) foreach (var entry in Entries.ToList())
{ {
RemoveEntry(entry); await RemoveEntry(entry);
} }
Entries.Clear(); Entries.Clear();

@ -0,0 +1,19 @@
// 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,9 +6,10 @@ 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
{ {
@ -20,13 +21,16 @@ 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></returns> /// <returns>The converted <see cref="IEnumerable"/> as a GBase <see cref="string"/></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)
{ {
@string.Append($"{item}{ENUMERABLE_STRING_DIVIDER}"); if (item is IGBaseObject gBaseObject)
@string.Append($"{gBaseObject.Key}{ENUMERABLE_STRING_DIVIDER}");
else
@string.Append($"{item}{ENUMERABLE_STRING_DIVIDER}");
} }
char lastChar = @string[^1]; char lastChar = @string[^1];
@ -41,9 +45,10 @@ 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) public static TEnumerable ConvertToGBaseEnumerable<TEnumerable>(string @string, IGBase gBase)
{ {
//get generic type parameter of TEnumerable //get generic type parameter of TEnumerable
Type genericType = typeof(TEnumerable).GetGenericArguments()[0]; Type genericType = typeof(TEnumerable).GetGenericArguments()[0];
@ -61,9 +66,16 @@ namespace GBase.Helpers
if (genericType.IsInterface) if (genericType.IsInterface)
throw new InterfaceEnumerablePassedException(genericType); throw new InterfaceEnumerablePassedException(genericType);
IGBaseObject gBaseObject = (IGBaseObject) Activator.CreateInstance(genericType); if (!int.TryParse(value, out int key))
gBaseObject.InitializeFromString(value); throw new InvalidKeyException("Key is not an integer.");
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);

@ -0,0 +1,108 @@
// 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,8 +7,13 @@ using GBase.DataHandling;
using GBase.DataHandling.Cache; using GBase.DataHandling.Cache;
using GBase.DataHandling.Cache.Factories; using GBase.DataHandling.Cache.Factories;
using GBase.DataHandling.Factories; using GBase.DataHandling.Factories;
using GBase.DataHandling.Factories.Pool;
using GBase.DataHandling.Pool;
using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Pool;
using GBase.Interfaces.DataHandling.Xml; using GBase.Interfaces.DataHandling.Xml;
using GBase.Interfaces.DataHandling.Xml.Cache; using GBase.Interfaces.DataHandling.Xml.Cache;
using LightweightIocContainer;
using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Installers; using LightweightIocContainer.Interfaces.Installers;
@ -22,16 +27,23 @@ namespace GBase.Installers
/// <inheritdoc /> /// <inheritdoc />
public void Install(IIocContainer container) public void Install(IIocContainer container)
{ {
container.Register<IXmlDataHandler, XmlDataHandler>(); container.Register<IDataHandler, IXmlDataHandler, XmlDataHandler>();
container.Register<IXmlDataReader, XmlDataReader>(); container.Register<IDataReader, IXmlDataReader, XmlDataReader>();
container.Register<IXmlDataWriter, XmlDataWriter>(); container.Register<IDataWriter, IXmlDataWriter, XmlDataWriter>();
//cache //cache
container.Register<IXmlDataHandlerCache, XmlDataHandlerCache>(); container.Register<IXmlDataHandlerCache, XmlDataHandlerCache>();
container.Register<IXmlDataHandlerCacheEntry, XmlDataHandlerCacheEntry>(); container.Register<IXmlDataHandlerCacheEntry, XmlDataHandlerCacheEntry>();
container.Register<IXmlDataHandlerCachePropertyEntry, XmlDataHandlerCachePropertyEntry>(); container.Register<IXmlDataHandlerCachePropertyEntry, XmlDataHandlerCachePropertyEntry>();
//pool
container.Register<IDataHandlerPool, DataHandlerPool>(Lifestyle.Singleton).WithParameters(10);
container.Register<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,6 +5,7 @@
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;
@ -18,13 +19,12 @@ namespace GBase.Installers
/// <inheritdoc /> /// <inheritdoc />
public void Install(IIocContainer container) public void Install(IIocContainer container)
{ {
container.Register<IGBase, GBase>(); container.Register<IGBase, GBase>(Lifestyle.Singleton);
container.Register<IGBaseTable, GBaseTable>();
container.Register<IGBaseColumn, GBaseColumn>(); container.Register<IGBaseColumn, GBaseColumn>();
//factories //factories
container.RegisterFactory<IGBaseFactory>(); container.RegisterFactory<IGBaseFactory>();
container.RegisterFactory<IGBaseTableFactory>(); container.Register<IGBaseTableFactory, GBaseTableFactory>(); //TODO: Once LightweightIocContainer can handle open generic registrations this can be changed back again
container.RegisterFactory<IGBaseColumnFactory>(); container.RegisterFactory<IGBaseColumnFactory>();
} }
} }

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

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

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

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

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

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

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

@ -6,6 +6,7 @@ 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
{ {
@ -18,46 +19,15 @@ 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>
Task<bool> Init(string path, CancellationToken cancellationToken); List<IGBaseFile> Init(string path, string folderName, CancellationToken cancellationToken);
/// <summary> IGBaseFile CreateEntryFile<T>(T entry, IGBaseTable table) where T : IGBaseObject;
/// Set the value for the given property
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param>
/// <returns>A <see cref="Task"/> to await</returns>
Task SetValue<T, TProperty>(string propertyName, TProperty value);
/// <summary> Task<bool> DeleteEntryFile<T>(T entry);
/// Remove the value for the given property
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param>
/// <returns>A <see cref="Task"/> to await</returns>
Task RemoveValue<T, TProperty>(string propertyName, TProperty value);
/// <summary> Task<IGBaseFile> RequestEntryFile<T>(T entry);
/// Get the value for the given property, if multiple values are set the first is returned
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="propertyName">The name of the property</param>
/// <returns>The value for the given property</returns>
Task<TProperty> GetValue<T, TProperty>(string propertyName);
/// <summary>
/// Get all the values that are set for the given property
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="propertyName">The name of the property</param>
/// <returns>An <see cref="IEnumerable{T}"/> with all the values for the property</returns>
Task<IEnumerable<TProperty>> GetValues<T, TProperty>(string propertyName);
} }
} }

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

@ -48,11 +48,20 @@ 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,8 +9,10 @@ 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 //TODO: Make column generic (generic type is type of the value of the column?)? public interface IGBaseColumn : IAsyncDisposable
{ {
string Name { get; }
Type Type { get; }
bool IsKey { get; }
} }
} }

@ -0,0 +1,29 @@
// 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,14 +6,44 @@ 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 //TODO: make generic? public interface IGBaseTable : IAsyncDisposable
{ {
/// <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
@ -23,27 +53,23 @@ namespace GBase.Interfaces
/// <summary> /// <summary>
/// The name of this <see cref="IGBaseTable"/> /// The name of this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
string Name { get; } string FolderName { get; }
/// <summary> /// <summary>
/// The <see cref="IGBaseColumn"/>s of this <see cref="IGBaseTable"/> /// The <see cref="IGBaseColumn"/>s of this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
List<IGBaseColumn> Columns { get; } List<IGBaseColumn> Columns { get; }
/// <summary>
/// The entries of this <see cref="IGBaseTable"/>
/// </summary>
List<object> Entries { get; }
/// <summary> /// <summary>
/// Initialize this <see cref="IGBase"/> /// Initialize this <see cref="IGBase"/>
/// </summary> /// </summary>
/// <param name="type">The <see cref="System.Type"/> of the class that this <see cref="IGBaseTable"/> represents</param> /// <param name="type">The <see cref="System.Type"/> of the class that this <see cref="IGBaseTable"/> represents</param>
/// <param name="name">The name of this <see cref="IGBaseTable"/></param> /// <param name="databasePath">The path to the database files</param>
/// /// <param name="databasePath">The path to the database files</param> /// <param name="folderName"></param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the asynchronous operation</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the asynchronous operation</param>
/// ///
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
Task<bool> Init(Type type, string name, string databasePath, CancellationToken cancellationToken); Task Init(Type type, string databasePath, string folderName, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Add a given <see cref="IGBaseColumn"/> to this <see cref="IGBaseTable"/> /// Add a given <see cref="IGBaseColumn"/> to this <see cref="IGBaseTable"/>
@ -58,19 +84,5 @@ namespace GBase.Interfaces
/// <param name="column">The given <see cref="IGBaseColumn"/></param> /// <param name="column">The given <see cref="IGBaseColumn"/></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
bool RemoveColumn(IGBaseColumn column); bool RemoveColumn(IGBaseColumn column);
/// <summary>
/// Add an entry that implements <see cref="INotifyGBaseEntryChanged"/> to this <see cref="IGBaseTable"/>
/// </summary>
/// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <returns>True if successful, false if not</returns>
bool AddEntry(INotifyGBaseEntryChanged entry);
/// <summary>
/// Remove an entry that implements <see cref="INotifyGBaseEntryChanged"/> from this <see cref="IGBaseTable"/>
/// </summary>
/// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <returns>True if successful, false if not</returns>
bool RemoveEntry(INotifyGBaseEntryChanged entry);
} }
} }

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

@ -1,3 +1,5 @@
# 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,12 +3,14 @@
// 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;
@ -27,12 +29,12 @@ namespace Test.GBase.DataHandling
Assert.Pass(); //Remove this assert.pass() if you want to run this test locally Assert.Pass(); //Remove this assert.pass() if you want to run this test locally
Mock<IXmlDataWriterFactory> dataWriterFactoryMock = new Mock<IXmlDataWriterFactory>(); Mock<IXmlDataWriterFactory> dataWriterFactoryMock = new Mock<IXmlDataWriterFactory>();
dataWriterFactoryMock.Setup(w => w.Create(It.IsAny<string>(), It.IsAny<string>())) dataWriterFactoryMock.Setup(w => w.Create())
.Returns((string path, string rootElementName) => new XmlDataWriter(path, rootElementName)); .Returns(new XmlDataWriter());
Mock<IXmlDataReaderFactory> dataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> dataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
dataReaderFactoryMock.Setup(r => r.Create(It.IsAny<string>())) dataReaderFactoryMock.Setup(r => r.Create())
.Returns((string path) => new XmlDataReader(path)); .Returns(new XmlDataReader(Mock.Of<IGBase>()));
Mock<IXmlDataHandlerCachePropertyEntryFactory> dataHandlerCachePropertyEntryFactoryMock = new Mock<IXmlDataHandlerCachePropertyEntryFactory>(); Mock<IXmlDataHandlerCachePropertyEntryFactory> dataHandlerCachePropertyEntryFactoryMock = new Mock<IXmlDataHandlerCachePropertyEntryFactory>();
dataHandlerCachePropertyEntryFactoryMock.Setup(p => p.Create(It.IsAny<string>(), It.IsAny<object>())) dataHandlerCachePropertyEntryFactoryMock.Setup(p => p.Create(It.IsAny<string>(), It.IsAny<object>()))
@ -48,21 +50,22 @@ namespace Test.GBase.DataHandling
.Returns((IXmlDataReader xmlDataReader) => .Returns((IXmlDataReader xmlDataReader) =>
new XmlDataHandlerCache(xmlDataReader, dataHandlerCacheEntryFactoryMock.Object, dataHandlerCachePropertyEntryFactoryMock.Object)); new XmlDataHandlerCache(xmlDataReader, dataHandlerCacheEntryFactoryMock.Object, dataHandlerCachePropertyEntryFactoryMock.Object));
IXmlDataHandler xmlDataHandler = new XmlDataHandler("TestXml.xml", "Properties", dataReaderFactoryMock.Object, dataWriterFactoryMock.Object, IXmlDataHandler xmlDataHandler = new XmlDataHandler(dataReaderFactoryMock.Object, dataWriterFactoryMock.Object, dataHandlerCacheFactoryMock.Object);
dataHandlerCacheFactoryMock.Object);
xmlDataHandler.Init(false);
FileStream file = null; //FixMe: init this correctly if you want to run this test
await xmlDataHandler.Init(false, new CancellationToken());
//
//await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), TestProperty); //await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), TestProperty);
//await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), "empty"); //await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), "empty");
await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), "test"); await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(file, nameof(TestProperty), "test", new CancellationToken());
//await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), "OverwrittenString"); //await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty), "OverwrittenString");
// //
await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt), 1); await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(file, nameof(TestInt), 1, new CancellationToken());
//await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt), 2); //await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt), 2);
//await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt), 3); //await xmlDataHandler.SetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt), 3);
TestProperty = await xmlDataHandler.GetValue<XmlDataHandlerLocalIntegrationTest, string>(nameof(TestProperty)); TestProperty = await xmlDataHandler.GetValue<XmlDataHandlerLocalIntegrationTest, string>(file, nameof(TestProperty), new CancellationToken());
TestInt = await xmlDataHandler.GetValue<XmlDataHandlerLocalIntegrationTest, int>(nameof(TestInt)); TestInt = await xmlDataHandler.GetValue<XmlDataHandlerLocalIntegrationTest, int>(file, nameof(TestInt), new CancellationToken());
} }
} }
} }

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

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

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

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

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

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

@ -0,0 +1,54 @@
// Author: Gockner, Simon
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using GBase.Factories;
using GBase.Interfaces;
namespace Test.GBase.GBaseIntegrationTest
{
public class Model
{
private readonly IGBase _gBase;
public Model(IGBaseFactory gBaseFactory)
{
_gBase = gBaseFactory.Create(new Settings());
Items = new List<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);
}
}
}

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

@ -2,11 +2,13 @@
// 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;
@ -23,17 +25,24 @@ namespace Test.GBase
Mock<IFileHandlerFactory> fileHandlerFactoryMock = new Mock<IFileHandlerFactory>(); Mock<IFileHandlerFactory> fileHandlerFactoryMock = new Mock<IFileHandlerFactory>();
fileHandlerFactoryMock.Setup(f => f.Create()).Returns(new Mock<IFileHandler>().Object); fileHandlerFactoryMock.Setup(f => f.Create()).Returns(new Mock<IFileHandler>().Object);
IGBaseColumn gBaseColumn = null;
Mock<IGBaseColumnFactory> gBaseColumnFactoryMock = new Mock<IGBaseColumnFactory>(); Mock<IGBaseColumnFactory> gBaseColumnFactoryMock = new Mock<IGBaseColumnFactory>();
gBaseColumnFactoryMock.Setup(c => c.Create()).Returns(new GBaseColumn()); gBaseColumnFactoryMock.Setup(c => c.Create(It.IsAny<string>(), It.IsAny<Type>(), It.IsAny<bool>()))
.Callback<string, Type, bool>((name, type, isKey) => { gBaseColumn = new GBaseColumn(name, type, isKey); })
.Returns(gBaseColumn);
IGBaseTable table = new GBaseTable(fileHandlerFactoryMock.Object, gBaseColumnFactoryMock.Object); Mock<IDataHandlerPool> dataHandlerPoolMock = new Mock<IDataHandlerPool>();
table.Init(typeof(Foo), nameof(Foo), "", CancellationToken.None);
IGBaseTable<Foo> table = new GBaseTable<Foo>(fileHandlerFactoryMock.Object, dataHandlerPoolMock.Object, gBaseColumnFactoryMock.Object);
table.Init(typeof(Foo), "", "", CancellationToken.None);
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
Foo foo = new Foo("Test"); Foo foo = new Foo("Test");
table.AddEntry(foo); table.AddEntry(foo, cancellationTokenSource.Token);
Foo foo2 = new Foo("Test2"); Foo foo2 = new Foo("Test2");
table.AddEntry(foo2); table.AddEntry(foo2, cancellationTokenSource.Token);
foo.Name = "Foo - ex Test"; foo.Name = "Foo - ex Test";
foo2.Name = "Some Name"; foo2.Name = "Some Name";

@ -5,6 +5,8 @@
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;
@ -85,7 +87,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)); Assert.AreEqual(list, Enumerables.ConvertToGBaseEnumerable<List<string>>(@string, Mock.Of<IGBase>()));
} }
[Test] [Test]
@ -100,7 +102,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)); Assert.AreEqual(list, Enumerables.ConvertToGBaseEnumerable<List<int>>(@string, Mock.Of<IGBase>()));
} }
[Test] [Test]
@ -115,7 +117,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)); Assert.AreEqual(list, Enumerables.ConvertToGBaseEnumerable<List<UserType>>(@string, Mock.Of<IGBase>()));
} }
[Test] [Test]
@ -130,7 +132,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)); InterfaceEnumerablePassedException exception = Assert.Throws<InterfaceEnumerablePassedException>(() => Enumerables.ConvertToGBaseEnumerable<List<IUserType>>(@string, Mock.Of<IGBase>()));
Assert.AreEqual(typeof(IUserType), exception.InterfaceType); Assert.AreEqual(typeof(IUserType), exception.InterfaceType);
} }
} }

@ -2,16 +2,25 @@
// 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] [GBaseTable("Foo")]
public class Foo : NotifyGBaseEntryChanged public class Foo : NotifyGBaseEntryChanged, IGBaseObject
{ {
private string _name; private string _name;
public Foo()
{
}
public Foo(string name) public Foo(string name)
{ {
Name = name; Name = name;
@ -27,5 +36,13 @@ 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,6 +3,7 @@
// 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,7 +3,9 @@
// 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
{ {
@ -21,10 +23,12 @@ namespace Test.GBase.TestClasses
private int Number { get; set; } private int Number { get; set; }
public void InitializeFromString(string @string) public GBaseKey Key { get; set; }
public string FileName { get; }
public void Initialize(GBaseKey key, List<object> parameters)
{ {
string numberString = @string.Split('_').Last(); throw new NotImplementedException();
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