Compare commits

..

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

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

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

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

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

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

@ -102,6 +102,17 @@
The new value
</summary>
</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">
<summary>
Notify the GBase that an entry has changed

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

@ -2,6 +2,5 @@
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Author: $USER_NAME$&#xD;
Created: $CREATED_YEAR$-$CREATED_MONTH$-$CREATED_DAY$&#xD;
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/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String></wpf:ResourceDictionary>

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

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

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

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

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

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

@ -14,7 +14,9 @@ namespace GBase.DataHandling.Factories
/// <summary>
/// Creates an <see cref="IXmlDataWriter"/>
/// </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>
IXmlDataWriter Create();
IXmlDataWriter Create(string path, string rootElementName);
}
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -9,7 +9,6 @@ using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using GBase.Attributes;
using GBase.Exceptions;
using GBase.Factories;
using GBase.Interfaces;
using GBase.Interfaces.Settings;
@ -21,6 +20,11 @@ namespace GBase
/// </summary>
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;
/// <summary>
@ -70,8 +74,8 @@ namespace GBase
if (gBaseTableAttribute == null)
continue;
IGBaseTable gBaseTable = _gBaseTableFactory.Create(type);
await gBaseTable.Init(type, Settings.DatabasePath, gBaseTableAttribute.FolderName, cancellationToken);
IGBaseTable gBaseTable = _gBaseTableFactory.Create();
await gBaseTable.Init(type, type.Name, Settings.DatabasePath, cancellationToken);
AddTable(gBaseTable);
}
@ -89,21 +93,13 @@ namespace GBase
if (Tables.Contains(table))
return false;
if (Tables.Any(t => t.FolderName.Equals(table.FolderName)))
if (Tables.Any(t => t.Name.Equals(table.Name)))
return false;
Tables.Add(table);
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>
/// Removes a given <see cref="IGBaseTable"/> from this <see cref="GBase"/>
/// </summary>
@ -117,52 +113,6 @@ namespace GBase
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>
/// Dispose used resources asynchronously
/// </summary>

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

@ -87,15 +87,13 @@
<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.DataHandling.Cache.XmlDataHandlerCache.TryGetValues``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.DataHandling.Cache.XmlDataHandlerCache.TryGetValues``2(System.String)">
<summary>
Try to get values from the cache for the given property
</summary>
<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>
<param name="file"></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>
</member>
<member name="T:GBase.DataHandling.Cache.XmlDataHandlerCacheEntry">
@ -165,10 +163,11 @@
Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/>
</summary>
</member>
<member name="M:GBase.DataHandling.Factories.IXmlDataReaderFactory.Create">
<member name="M:GBase.DataHandling.Factories.IXmlDataReaderFactory.Create(System.String)">
<summary>
Creates an <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/>
</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>
</member>
<member name="T:GBase.DataHandling.Factories.IXmlDataWriterFactory">
@ -176,10 +175,12 @@
Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/>
</summary>
</member>
<member name="M:GBase.DataHandling.Factories.IXmlDataWriterFactory.Create">
<member name="M:GBase.DataHandling.Factories.IXmlDataWriterFactory.Create(System.String,System.String)">
<summary>
Creates an <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/>
</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>
</member>
<member name="T:GBase.DataHandling.XmlDataHandler">
@ -197,158 +198,152 @@
The attribute name of the value <see cref="T:System.Type"/> attribute
</summary>
</member>
<member name="M:GBase.DataHandling.XmlDataHandler.#ctor(GBase.DataHandling.Factories.IXmlDataReaderFactory,GBase.DataHandling.Factories.IXmlDataWriterFactory,GBase.DataHandling.Cache.Factories.IXmlDataHandlerCacheFactory)">
<member name="M:GBase.DataHandling.XmlDataHandler.#ctor(System.String,System.String,GBase.DataHandling.Factories.IXmlDataReaderFactory,GBase.DataHandling.Factories.IXmlDataWriterFactory,GBase.DataHandling.Cache.Factories.IXmlDataHandlerCacheFactory)">
<summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/> that handles its data in 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>
<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="xmlDataHandlerCacheFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.Cache.IXmlDataHandlerCache"/> factory</param>
</member>
<member name="M:GBase.DataHandling.XmlDataHandler.Init(System.Boolean)">
<member name="M:GBase.DataHandling.XmlDataHandler.Init(System.Boolean,System.Threading.CancellationToken)">
<summary>
Initialize the <see cref="T:GBase.DataHandling.XmlDataHandler"/>
</summary>
<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>
</member>
<member name="M:GBase.DataHandling.XmlDataHandler.SetValue``2(System.IO.FileStream,System.String,``1,System.Threading.CancellationToken)">
<member name="M:GBase.DataHandling.XmlDataHandler.SetValue``2(System.String,``1)">
<summary>
Set the value for the given property
</summary>
<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>
<param name="entryFile"></param>
<param name="propertyName">The name of the property</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>
</member>
<member name="M:GBase.DataHandling.XmlDataHandler.RemoveValue``2(System.IO.FileStream,System.String,``1,System.Threading.CancellationToken)">
<member name="M:GBase.DataHandling.XmlDataHandler.RemoveValue``2(System.String,``1)">
<summary>
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="entryFile"></param>
<param name="propertyName">The name of the property</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>
</member>
<member name="M:GBase.DataHandling.XmlDataHandler.GetValue``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.DataHandling.XmlDataHandler.GetValue``2(System.String)">
<summary>
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"/> that implements 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="cancellationToken"></param>
<returns>The value for the given property</returns>
</member>
<member name="M:GBase.DataHandling.XmlDataHandler.GetValues``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.DataHandling.XmlDataHandler.GetValues``2(System.String)">
<summary>
Get all the values that are set for the given property
</summary>
<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>
<param name="file"></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>
</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">
<summary>
An <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file
A <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file
</summary>
</member>
<member name="M:GBase.DataHandling.XmlDataReader.#ctor(System.String)">
<summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file
</summary>
<param name="path">The path to the xml file</param>
</member>
<member name="M:GBase.DataHandling.XmlDataReader.#ctor(GBase.Interfaces.IGBase)">
<member name="M:GBase.DataHandling.XmlDataReader.Init(System.Threading.CancellationToken)">
<summary>
An <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file
Initialize the <see cref="T:GBase.DataHandling.XmlDataReader"/>
</summary>
<param name="gBase">The <see cref="T:GBase.Interfaces.IGBase"/></param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param>
<returns>Returns true if successful, false if not</returns>
<exception cref="T:System.Exception">No root element found</exception>
</member>
<member name="M:GBase.DataHandling.XmlDataReader.Read``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.DataHandling.XmlDataReader.Read``2(System.String)">
<summary>
Read the data of a property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<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.InvalidOperationException">Invalid <see cref="T:System.Type"/> found for the read object</exception>
</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">
<summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataWriter"/> that writes to a xml file
</summary>
</member>
<member name="M:GBase.DataHandling.XmlDataWriter.InitFile(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.DataHandling.XmlDataWriter.#ctor(System.String,System.String)">
<summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataWriter"/> that writes to an xml file
</summary>
<param name="path">The path to the xml file</param>
<param name="rootElementName">The root element name of the xml file</param>
</member>
<member name="M:GBase.DataHandling.XmlDataWriter.Init(System.Threading.CancellationToken)">
<summary>
Initialize the <see cref="T:GBase.DataHandling.XmlDataWriter"/>
</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>
<returns>Returns true if successful, false if not</returns>
<exception cref="T:System.Exception">No root element found</exception>
</member>
<member name="M:GBase.DataHandling.XmlDataWriter.Write``2(System.IO.FileStream,System.String,System.String,System.Boolean,System.Threading.CancellationToken)">
<summary>
Write the data of a property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param>
<param name="value">The value of the property</param>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member>
<member name="M:GBase.DataHandling.XmlDataWriter.Write``1(System.IO.FileStream,System.String,System.String,System.Type,System.Boolean,System.Threading.CancellationToken)">
<member name="M:GBase.DataHandling.XmlDataWriter.Write``2(System.String,System.String,System.Boolean)">
<summary>
Write the data of a property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/> that implements the property</typeparam>
<param name="file"></param>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="propertyName">The name of the property</param>
<param name="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>
<exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception>
<exception cref="T:GBase.DataHandling.Exceptions.InvalidXmlFileException">No root element is set</exception>
</member>
<member name="M:GBase.DataHandling.XmlDataWriter.Remove``2(System.IO.FileStream,System.String,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.DataHandling.XmlDataWriter.Remove``2(System.String,System.String)">
<summary>
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="file"></param>
<param name="propertyName">The name of the property</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>
<exception cref="T:System.ArgumentNullException"><paramref name="propertyName"/></exception>
<exception cref="T:GBase.DataHandling.Exceptions.InvalidXmlFileException">No root element is set</exception>
</member>
<member name="T:GBase.Exceptions.GenericMethodNotFoundException">
<member name="M:GBase.DataHandling.XmlDataWriter.DisposeAsync">
<summary>
Could not find generic method
</summary>
</member>
<member name="M:GBase.Exceptions.GenericMethodNotFoundException.#ctor(System.String)">
<summary>
Could not find generic method
Dispose used resources asynchronously
</summary>
<param name="functionName">The name of the generic method</param>
<returns>A <see cref="T:System.Threading.Tasks.ValueTask"/> to await</returns>
</member>
<member name="T:GBase.Exceptions.InterfaceEnumerablePassedException">
<summary>
@ -366,52 +361,12 @@
The <see cref="T:System.Type"/> of the passed interface
</summary>
</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">
<summary>
Factory for the <see cref="T:GBase.Interfaces.IGBaseColumn"/>
</summary>
</member>
<member name="M:GBase.Factories.IGBaseColumnFactory.Create(System.String,System.Type,System.Boolean)">
<member name="M:GBase.Factories.IGBaseColumnFactory.Create">
<summary>
Creates an <see cref="T:GBase.Interfaces.IGBaseColumn"/>
</summary>
@ -434,7 +389,7 @@
Factory for the <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
</member>
<member name="M:GBase.Factories.IGBaseTableFactory.Create(System.Type)">
<member name="M:GBase.Factories.IGBaseTableFactory.Create">
<summary>
Creates an <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
@ -456,25 +411,63 @@
Internal file handler
</summary>
</member>
<member name="F:GBase.FileHandling.FileHandler.GBASE_TABLE_FILE_EXTENSION">
<member name="M:GBase.FileHandling.FileHandler.#ctor(GBase.DataHandling.Factories.IXmlDataHandlerFactory)">
<summary>
The file extension for all GBase tables
Internal file handler
</summary>
<param name="xmlDataHandlerFactory">Factory for the <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataHandler"/></param>
</member>
<member name="M:GBase.FileHandling.FileHandler.#ctor">
<member name="P:GBase.FileHandling.FileHandler.DataHandler">
<summary>
Internal file handler
The <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/> of this <see cref="T:GBase.Interfaces.FileHandling.IFileHandler"/>
</summary>
</member>
<member name="M:GBase.FileHandling.FileHandler.Init(System.String,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.FileHandling.FileHandler.Init(System.String,System.Threading.CancellationToken)">
<summary>
Initialize this <see cref="T:GBase.Interfaces.FileHandling.IFileHandler"/>
</summary>
<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>
<returns>True if successful, false if not</returns>
</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">
<summary>
Dispose used resources asynchronously
@ -486,6 +479,11 @@
The base class of the GBase database
</summary>
</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)">
<summary>
The base class of the GBase database
@ -542,7 +540,7 @@
A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
</member>
<member name="M:GBase.GBaseColumn.#ctor(System.String,System.Type,System.Boolean)">
<member name="M:GBase.GBaseColumn.#ctor">
<summary>
A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
@ -553,96 +551,91 @@
</summary>
<returns>A <see cref="T:System.Threading.Tasks.ValueTask"/> to await</returns>
</member>
<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">
<member name="T:GBase.GBaseTable">
<summary>
A <see cref="T:GBase.Interfaces.IGBase"/> table
</summary>
</member>
<member name="M:GBase.GBaseTable`1.#ctor(GBase.FileHandling.Factories.IFileHandlerFactory,GBase.Interfaces.DataHandling.Pool.IDataHandlerPool,GBase.Factories.IGBaseColumnFactory)">
<member name="M:GBase.GBaseTable.#ctor(GBase.FileHandling.Factories.IFileHandlerFactory,GBase.Factories.IGBaseColumnFactory)">
<summary>
A <see cref="T:GBase.Interfaces.IGBase"/> table
</summary>
<param name="fileHandlerFactory"></param>
<param name="dataHandlerPool">The <see cref="T:GBase.Interfaces.DataHandling.Pool.IDataHandlerPool"/></param>
<param name="gBaseColumnFactory"></param>
</member>
<member name="P:GBase.GBaseTable`1.Type">
<member name="P:GBase.GBaseTable.Type">
<summary>
The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents
</summary>
</member>
<member name="P:GBase.GBaseTable`1.FolderName">
<member name="P:GBase.GBaseTable.Name">
<summary>
The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
</member>
<member name="P:GBase.GBaseTable`1.Columns">
<member name="P:GBase.GBaseTable.Columns">
<summary>
The <see cref="T:GBase.Interfaces.IGBaseColumn"/>s of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
</member>
<member name="P:GBase.GBaseTable`1.Entries">
<member name="P:GBase.GBaseTable.Entries">
<summary>
The entries of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
</member>
<member name="M:GBase.GBaseTable`1.Init(System.Type,System.String,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.GBaseTable.Init(System.Type,System.String,System.String,System.Threading.CancellationToken)">
<summary>
Initialize this <see cref="T:GBase.Interfaces.IGBase"/>
</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="name">The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/></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>
<returns>True if successful, false if not</returns>
</member>
<member name="M:GBase.GBaseTable`1.AddColumn(GBase.Interfaces.IGBaseColumn)">
<member name="M:GBase.GBaseTable.AddColumn(GBase.Interfaces.IGBaseColumn)">
<summary>
Add a given <see cref="T:GBase.Interfaces.IGBaseColumn"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param>
<returns>True if successful, false if not</returns>
</member>
<member name="M:GBase.GBaseTable`1.RemoveColumn(GBase.Interfaces.IGBaseColumn)">
<member name="M:GBase.GBaseTable.RemoveColumn(GBase.Interfaces.IGBaseColumn)">
<summary>
Remove a given <see cref="T:GBase.Interfaces.IGBaseColumn"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param>
<returns>True if successful, false if not</returns>
</member>
<member name="M:GBase.GBaseTable`1.AddEntry(`0,System.Threading.CancellationToken)">
<member name="M:GBase.GBaseTable.AddEntry(GBase.Api.INotifyGBaseEntryChanged)">
<summary>
Add an entry that implements <see cref="T:GBase.Interfaces.IGBaseObject"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/>
Add an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<param name="entry">The entry implementing <see cref="T:GBase.Interfaces.IGBaseObject"/></param>
<param name="cancellationToken"></param>
<param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<returns>True if successful, false if not</returns>
</member>
<member name="M:GBase.GBaseTable`1.RemoveEntry(`0)">
<member name="M:GBase.GBaseTable.RemoveEntry(GBase.Api.INotifyGBaseEntryChanged)">
<summary>
Remove an entry that implements <see cref="T:GBase.Interfaces.IGBaseObject"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/>
Remove an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
<param name="entry">The entry implementing <see cref="T:GBase.Interfaces.IGBaseObject"/></param>
<param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<returns>True if successful, false if not</returns>
</member>
<member name="M:GBase.GBaseTable.ModifyEntry(System.Object,System.String,System.Object)">
<summary>
Modify the property of a given entry with the given value
</summary>
<param name="entry">The entry</param>
<param name="propertyName">The name of the property</param>
<param name="value">The new value to set</param>
<returns>True if successful, false if not</returns>
</member>
<member name="M:GBase.GBaseTable`1.DisposeAsync">
<member name="M:GBase.GBaseTable.OnGBaseEntryChanged(System.Object,GBase.Api.GBaseEntryChangedEventArgs)">
<summary>
A <see cref="T:GBase.Interfaces.IGBase"/> entry changed
</summary>
<param name="entry">The entry (sender)</param>
<param name="args">The <see cref="T:GBase.Api.GBaseEntryChangedEventArgs"/></param>
</member>
<member name="M:GBase.GBaseTable.DisposeAsync">
<summary>
The <see cref="M:System.IAsyncDisposable.DisposeAsync"/> method
</summary>
@ -653,73 +646,17 @@
Convert an <see cref="T:System.Collections.IEnumerable"/> to a GBase <see cref="T:System.String"/>
</summary>
<param name="enumerable">The <see cref="T:System.Collections.IEnumerable"/></param>
<returns>The converted <see cref="T:System.Collections.IEnumerable"/> as a GBase <see cref="T:System.String"/></returns>
<returns></returns>
</member>
<member name="M:GBase.Helpers.Enumerables.ConvertToGBaseEnumerable``1(System.String,GBase.Interfaces.IGBase)">
<member name="M:GBase.Helpers.Enumerables.ConvertToGBaseEnumerable``1(System.String)">
<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"/>
</summary>
<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="gBase"></param>
<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>
</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">
<summary>
<see cref="T:LightweightIocContainer.Interfaces.Installers.IIocInstaller"/> for the data handling
@ -770,15 +707,13 @@
<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.DataHandling.Cache.IDataHandlerCache.TryGetValues``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.Interfaces.DataHandling.Cache.IDataHandlerCache.TryGetValues``2(System.String)">
<summary>
Try to get values from the cache for the given property
</summary>
<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>
<param name="file"></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>
</member>
<member name="T:GBase.Interfaces.DataHandling.Cache.IDataHandlerCacheEntry">
@ -821,57 +756,50 @@
Interface for data handlers to implement
</summary>
</member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.Init(System.Boolean)">
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.Init(System.Boolean,System.Threading.CancellationToken)">
<summary>
Initialize the <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/>
</summary>
<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>
</member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.SetValue``2(System.IO.FileStream,System.String,``1,System.Threading.CancellationToken)">
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.SetValue``2(System.String,``1)">
<summary>
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="entryFile"></param>
<param name="propertyName">The name of the property</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>
</member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.RemoveValue``2(System.IO.FileStream,System.String,``1,System.Threading.CancellationToken)">
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.RemoveValue``2(System.String,``1)">
<summary>
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="entryFile"></param>
<param name="propertyName">The name of the property</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>
</member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValue``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValue``2(System.String)">
<summary>
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="file"></param>
<param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>The value for the given property</returns>
</member>
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValues``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.Interfaces.DataHandling.IDataHandler.GetValues``2(System.String)">
<summary>
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="file"></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>
</member>
<member name="T:GBase.Interfaces.DataHandling.IDataReader">
@ -879,15 +807,20 @@
Interface for data readers to implement
</summary>
</member>
<member name="M:GBase.Interfaces.DataHandling.IDataReader.Read``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.Interfaces.DataHandling.IDataReader.Init(System.Threading.CancellationToken)">
<summary>
Initialize the <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/>
</summary>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the async operation</param>
<returns>Returns true if successful, false if not</returns>
</member>
<member name="M:GBase.Interfaces.DataHandling.IDataReader.Read``2(System.String)">
<summary>
Read the data of a property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param>
<param name="cancellationToken"></param>
<returns>The data of the given property, null if no data found</returns>
</member>
<member name="T:GBase.Interfaces.DataHandling.IDataWriter">
@ -895,51 +828,32 @@
Interface for data writers to implement
</summary>
</member>
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.InitFile(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.Init(System.Threading.CancellationToken)">
<summary>
Initialize the <see cref="T:GBase.Interfaces.DataHandling.IDataWriter"/>
</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>
<returns>Returns true if successful, false if not</returns>
</member>
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.Write``2(System.IO.FileStream,System.String,System.String,System.Boolean,System.Threading.CancellationToken)">
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.Write``2(System.String,System.String,System.Boolean)">
<summary>
Write the data of a property
</summary>
<typeparam name="T">The <see cref="T:System.Type"/></typeparam>
<typeparam name="TProperty">The <see cref="T:System.Type"/> of the property</typeparam>
<param name="file"></param>
<param name="propertyName">The name of the property</param>
<param name="value">The value of the property</param>
<param name="overwrite">If true an existing value is overwritten, if false an additional value is added</param>
<param name="cancellationToken"></param>
<returns>A <see cref="T:System.Threading.Tasks.Task"/> to await</returns>
</member>
<member name="M:GBase.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)">
<member name="M:GBase.Interfaces.DataHandling.IDataWriter.Remove``2(System.String,System.String)">
<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="file"></param>
<param name="propertyName">The name of the property</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>
</member>
<member name="T:GBase.Interfaces.DataHandling.Xml.Cache.IXmlDataHandlerCache">
@ -977,15 +891,52 @@
Internal file handler
</summary>
</member>
<member name="M:GBase.Interfaces.FileHandling.IFileHandler.Init(System.String,System.String,System.Threading.CancellationToken)">
<member name="M:GBase.Interfaces.FileHandling.IFileHandler.Init(System.String,System.Threading.CancellationToken)">
<summary>
Initialize this <see cref="T:GBase.Interfaces.FileHandling.IFileHandler"/>
</summary>
<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>
<returns>True if successful, false if not</returns>
</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">
<summary>
The base class of the GBase database
@ -1034,47 +985,6 @@
A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
</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">
<summary>
A <see cref="T:GBase.Interfaces.IGBase"/> table
@ -1085,7 +995,7 @@
The <see cref="T:System.Type"/> of the class that this <see cref="T:GBase.Interfaces.IGBaseTable"/> represents
</summary>
</member>
<member name="P:GBase.Interfaces.IGBaseTable.FolderName">
<member name="P:GBase.Interfaces.IGBaseTable.Name">
<summary>
The name of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
@ -1095,15 +1005,19 @@
The <see cref="T:GBase.Interfaces.IGBaseColumn"/>s of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
</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)">
<summary>
Initialize this <see cref="T:GBase.Interfaces.IGBase"/>
</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="databasePath">The path to the database files</param>
<param name="folderName"></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="cancellationToken">A <see cref="T:System.Threading.CancellationToken"/> to cancel the asynchronous operation</param>
///
<returns>True if successful, false if not</returns>
</member>
<member name="M:GBase.Interfaces.IGBaseTable.AddColumn(GBase.Interfaces.IGBaseColumn)">
@ -1120,6 +1034,20 @@
<param name="column">The given <see cref="T:GBase.Interfaces.IGBaseColumn"/></param>
<returns>True if successful, false if not</returns>
</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">
<summary>
Settings of a <see cref="T:GBase.Interfaces.IGBase"/> instance

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

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

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

@ -4,18 +4,16 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using GBase.Api;
using GBase.Attributes;
using GBase.Exceptions;
using GBase.Factories;
using GBase.FileHandling.Factories;
using GBase.Helpers;
using GBase.Interfaces;
using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Pool;
using GBase.Interfaces.FileHandling;
namespace GBase
@ -23,26 +21,21 @@ namespace GBase
/// <summary>
/// A <see cref="IGBase"/> table
/// </summary>
public class GBaseTable<T> : IGBaseTable<T> where T : IGBaseObject, new()
public class GBaseTable : IGBaseTable
{
private readonly IFileHandler _fileHandler;
private readonly IDataHandlerPool _dataHandlerPool;
private readonly IGBaseColumnFactory _gBaseColumnFactory;
/// <summary>
/// A <see cref="IGBase"/> table
/// </summary>
/// <param name="fileHandlerFactory"></param>
/// <param name="dataHandlerPool">The <see cref="IDataHandlerPool"/></param>
/// <param name="gBaseColumnFactory"></param>
public GBaseTable(IFileHandlerFactory fileHandlerFactory, IDataHandlerPool dataHandlerPool, IGBaseColumnFactory gBaseColumnFactory)
public GBaseTable(IFileHandlerFactory fileHandlerFactory, IGBaseColumnFactory gBaseColumnFactory)
{
_fileHandler = fileHandlerFactory.Create();
_dataHandlerPool = dataHandlerPool;
_gBaseColumnFactory = gBaseColumnFactory;
Columns = new List<IGBaseColumn>();
Entries = new List<T>();
Entries = new List<object>();
}
@ -54,7 +47,7 @@ namespace GBase
/// <summary>
/// The name of this <see cref="IGBaseTable"/>
/// </summary>
public string FolderName { get; private set; }
public string Name { get; private set; }
/// <summary>
/// The <see cref="IGBaseColumn"/>s of this <see cref="IGBaseTable"/>
@ -64,85 +57,38 @@ namespace GBase
/// <summary>
/// The entries of this <see cref="IGBaseTable"/>
/// </summary>
public List<T> Entries { get; }
private int CurrentLastKey
{
get
{
T lastEntry = Entries.LastOrDefault();
if (lastEntry == null)
return -1;
return lastEntry.Key;
}
}
public List<object> Entries { get; }
/// <summary>
/// Initialize this <see cref="IGBase"/>
/// </summary>
/// <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="folderName"></param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the asynchronous operation</param>
/// <returns>True if successful, false if not</returns>
public async Task Init(Type type, string databasePath, string folderName, CancellationToken cancellationToken)
public async Task<bool> Init(Type type, string name, string databasePath, CancellationToken cancellationToken)
{
Type = type;
FolderName = folderName;
Name = name;
string fileName = $"{name}.{GBase.GBASE_TABLE_FILE_EXTENSION}";
string path = Path.Combine(databasePath, fileName);
await _fileHandler.Init(path, cancellationToken);
//TODO: Init columns list depending on GBaseColumnAttributes set for this GBaseTable
foreach (var property in type.GetProperties())
{
GBaseColumnAttribute gBaseColumnAttribute = property.GetCustomAttribute<GBaseColumnAttribute>() ??
property.GetAttributeFromInheritedInterfaces<GBaseColumnAttribute>();
GBaseColumnAttribute gBaseColumnAttribute = property.GetCustomAttribute<GBaseColumnAttribute>();
if (gBaseColumnAttribute == null)
continue;
IGBaseColumn gBaseColumn = _gBaseColumnFactory.Create(property.Name, property.PropertyType, gBaseColumnAttribute.IsKey);
IGBaseColumn gBaseColumn = _gBaseColumnFactory.Create();
AddColumn(gBaseColumn);
}
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);
}
}
return true;
}
/// <summary>
@ -150,7 +96,7 @@ namespace GBase
/// </summary>
/// <param name="column">The given <see cref="IGBaseColumn"/></param>
/// <returns>True if successful, false if not</returns>
public bool AddColumn(IGBaseColumn column) //TODO: if a column is added, it has to be added to every entry file as well
public bool AddColumn(IGBaseColumn column)
{
if (Columns.Contains(column))
return false;
@ -164,7 +110,7 @@ namespace GBase
/// </summary>
/// <param name="column">The given <see cref="IGBaseColumn"/></param>
/// <returns>True if successful, false if not</returns>
public bool RemoveColumn(IGBaseColumn column) //TODO: if a column is removed, it has to be removed from every entry file as well
public bool RemoveColumn(IGBaseColumn column)
{
if (!Columns.Contains(column))
return false;
@ -173,65 +119,58 @@ namespace GBase
}
/// <summary>
/// Add an entry that implements <see cref="IGBaseObject"/> to this <see cref="IGBaseTable"/>
/// Add an entry that implements <see cref="INotifyGBaseEntryChanged"/> to this <see cref="IGBaseTable"/>
/// </summary>
/// <param name="entry">The entry implementing <see cref="IGBaseObject"/></param>
/// <param name="cancellationToken"></param>
/// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <returns>True if successful, false if not</returns>
public async Task<bool> AddEntry(T entry, CancellationToken cancellationToken)
public bool AddEntry(INotifyGBaseEntryChanged entry) //TODO: Write to file
{
entry.Key ??= new GBaseKey();
if (entry.Key != -1)
throw new InvalidKeyException("Key of entry is already set. Make sure it is -1 when initializing.");
entry.Key.Key = CurrentLastKey + 1; //set next possible key
Entries.Add(entry);
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);
entry.GBaseEntryChanged += OnGBaseEntryChanged;
return true;
}
public T GetEntryForKey(int key) => Entries.FirstOrDefault(e => e.Key == key);
/// <summary>
/// Remove an entry that implements <see cref="IGBaseObject"/> from this <see cref="IGBaseTable"/>
/// Remove an entry that implements <see cref="INotifyGBaseEntryChanged"/> from this <see cref="IGBaseTable"/>
/// </summary>
/// <param name="entry">The entry implementing <see cref="IGBaseObject"/></param>
/// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <returns>True if successful, false if not</returns>
public async Task<bool> RemoveEntry(T entry)
public bool RemoveEntry(INotifyGBaseEntryChanged entry) //TODO: remove from file
{
if (!Entries.Contains(entry))
return false;
await _fileHandler.DeleteEntryFile(entry);
entry.GBaseEntryChanged -= OnGBaseEntryChanged;
return Entries.Remove(entry);
}
public async Task SetValue<TProperty>(T entry, string propertyName, TProperty value, CancellationToken cancellationToken)
/// <summary>
/// Modify the property of a given entry with the given value
/// </summary>
/// <param name="entry">The entry</param>
/// <param name="propertyName">The name of the property</param>
/// <param name="value">The new value to set</param>
/// <returns>True if successful, false if not</returns>
private bool ModifyEntry(object entry, string propertyName, object value) //TODO: Write to file
{
using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
await dataHandlerItem.Use().SetValue<T, TProperty>(file.File, propertyName, value, cancellationToken);
//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
return true;
}
public async Task<TProperty> GetValue<TProperty>(T entry, string propertyName, CancellationToken cancellationToken)
/// <summary>
/// A <see cref="IGBase"/> entry changed
/// </summary>
/// <param name="entry">The entry (sender)</param>
/// <param name="args">The <see cref="GBaseEntryChangedEventArgs"/></param>
private void OnGBaseEntryChanged(object entry, GBaseEntryChangedEventArgs args)
{
using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
return await dataHandlerItem.Use().GetValue<T, TProperty>(file.File, propertyName, cancellationToken);
}
//TODO: Might change, depending on #23
bool success = ModifyEntry(entry, args.ColumnName, args.Value);
public async Task<IEnumerable<TProperty>> GetValues<TProperty>(T entry, string propertyName, CancellationToken cancellationToken)
{
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);
if (!success)
throw new Exception("Failed to handle EntryChanged"); //TODO: Decide what to do here
}
/// <summary>
@ -241,7 +180,6 @@ namespace GBase
public async ValueTask DisposeAsync()
{
await _fileHandler.DisposeAsync();
await _dataHandlerPool.DisposeAsync();
foreach (var column in Columns)
{
@ -250,9 +188,9 @@ namespace GBase
Columns.Clear();
foreach (var entry in Entries.ToList())
foreach (var entry in Entries.OfType<INotifyGBaseEntryChanged>().ToList())
{
await RemoveEntry(entry);
RemoveEntry(entry);
}
Entries.Clear();

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

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

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

@ -7,13 +7,8 @@ using GBase.DataHandling;
using GBase.DataHandling.Cache;
using GBase.DataHandling.Cache.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.Cache;
using LightweightIocContainer;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Installers;
@ -27,23 +22,16 @@ namespace GBase.Installers
/// <inheritdoc />
public void Install(IIocContainer container)
{
container.Register<IDataHandler, IXmlDataHandler, XmlDataHandler>();
container.Register<IDataReader, IXmlDataReader, XmlDataReader>();
container.Register<IDataWriter, IXmlDataWriter, XmlDataWriter>();
container.Register<IXmlDataHandler, XmlDataHandler>();
container.Register<IXmlDataReader, XmlDataReader>();
container.Register<IXmlDataWriter, XmlDataWriter>();
//cache
container.Register<IXmlDataHandlerCache, XmlDataHandlerCache>();
container.Register<IXmlDataHandlerCacheEntry, XmlDataHandlerCacheEntry>();
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
container.RegisterFactory<IDataHandlerFactory>();
container.RegisterFactory<IXmlDataHandlerFactory>();
container.RegisterFactory<IXmlDataReaderFactory>();
container.RegisterFactory<IXmlDataWriterFactory>();

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

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

@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@ -13,63 +12,52 @@ namespace GBase.Interfaces.DataHandling
/// <summary>
/// Interface for data handlers to implement
/// </summary>
public interface IDataHandler
public interface IDataHandler : IAsyncDisposable
{
/// <summary>
/// Initialize the <see cref="IDataHandler"/>
/// </summary>
/// <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>
bool Init(bool overwrite);
Task<bool> AddEntry<T>(T entry, IGBaseTable table, FileStream entryFile, CancellationToken cancellationToken);
Task<bool> RemoveEntry<T>(T entry);
Task<bool> Init(bool overwrite, CancellationToken cancellationToken);
/// <summary>
/// Set the value for the given property
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the property</typeparam>
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
/// <param name="entryFile"></param>
/// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns>
Task SetValue<T, TProperty>(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken);
Task SetValue<T, TProperty>(string propertyName, TProperty value);
/// <summary>
/// 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="entryFile"></param>
/// <param name="propertyName">The name of the property</param>
/// <param name="value">The value to set</param>
/// <param name="cancellationToken"></param>
/// <returns>A <see cref="Task"/> to await</returns>
Task RemoveValue<T, TProperty>(FileStream entryFile, string propertyName, TProperty value, CancellationToken cancellationToken);
Task RemoveValue<T, TProperty>(string propertyName, TProperty value);
/// <summary>
/// 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="file"></param>
/// <param name="propertyName">The name of the property</param>
/// <param name="cancellationToken"></param>
/// <returns>The value for the given property</returns>
Task<TProperty> GetValue<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken);
Task<TProperty> GetValue<T, TProperty>(string propertyName);
/// <summary>
/// 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="file"></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>
Task<IEnumerable<TProperty>> GetValues<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken);
Task<IEnumerable<TProperty>> GetValues<T, TProperty>(string propertyName);
}
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -2,13 +2,11 @@
// Created: 2020-03-09
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using System.Threading;
using GBase;
using GBase.Factories;
using GBase.FileHandling.Factories;
using GBase.Interfaces;
using GBase.Interfaces.DataHandling.Pool;
using GBase.Interfaces.FileHandling;
using Moq;
using NUnit.Framework;
@ -25,24 +23,17 @@ namespace Test.GBase
Mock<IFileHandlerFactory> fileHandlerFactoryMock = new Mock<IFileHandlerFactory>();
fileHandlerFactoryMock.Setup(f => f.Create()).Returns(new Mock<IFileHandler>().Object);
IGBaseColumn gBaseColumn = null;
Mock<IGBaseColumnFactory> gBaseColumnFactoryMock = new Mock<IGBaseColumnFactory>();
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);
gBaseColumnFactoryMock.Setup(c => c.Create()).Returns(new GBaseColumn());
Mock<IDataHandlerPool> dataHandlerPoolMock = new Mock<IDataHandlerPool>();
IGBaseTable<Foo> table = new GBaseTable<Foo>(fileHandlerFactoryMock.Object, dataHandlerPoolMock.Object, gBaseColumnFactoryMock.Object);
table.Init(typeof(Foo), "", "", CancellationToken.None);
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
IGBaseTable table = new GBaseTable(fileHandlerFactoryMock.Object, gBaseColumnFactoryMock.Object);
table.Init(typeof(Foo), nameof(Foo), "", CancellationToken.None);
Foo foo = new Foo("Test");
table.AddEntry(foo, cancellationTokenSource.Token);
table.AddEntry(foo);
Foo foo2 = new Foo("Test2");
table.AddEntry(foo2, cancellationTokenSource.Token);
table.AddEntry(foo2);
foo.Name = "Foo - ex Test";
foo2.Name = "Some Name";

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

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

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

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

Loading…
Cancel
Save