Compare commits

..

No commits in common. 'master' and 'ImproveDataHandling_#25' have entirely different histories.

  1. 14
      .drone.yml
  2. 2
      .idea/.idea.GBase/.idea/modules.xml
  3. 14
      .idea/.idea.GBase/.idea/riderModule.iml
  4. 11
      GBase.Api/GBase.Api.xml
  5. 22
      GBase.Api/IGBaseObject.cs
  6. 5
      GBase/Attributes/GBaseColumnAttribute.cs
  7. 25
      GBase/DataHandling/Pool/DataHandlerPool.cs
  8. 10
      GBase/DataHandling/Pool/PoolItem.cs
  9. 6
      GBase/DataHandling/XmlDataHandler.cs
  10. 16
      GBase/DataHandling/XmlDataReader.cs
  11. 8
      GBase/DataHandling/XmlDataWriter.cs
  12. 17
      GBase/Exceptions/InvalidKeyException.cs
  13. 8
      GBase/Exceptions/InvalidTableTypeException.cs
  14. 17
      GBase/Exceptions/MissingKeyColumnException.cs
  15. 4
      GBase/Factories/GBaseTableFactory.cs
  16. 2
      GBase/Factories/IGBaseColumnFactory.cs
  17. 4
      GBase/FileHandling/FileHandler.cs
  18. 12
      GBase/GBase.cs
  19. 60
      GBase/GBase.xml
  20. 4
      GBase/GBaseColumn.cs
  21. 30
      GBase/GBaseKey.cs
  22. 12
      GBase/GBaseObject.cs
  23. 77
      GBase/GBaseTable.cs
  24. 19
      GBase/Helpers/Attributes.cs
  25. 24
      GBase/Helpers/Enumerables.cs
  26. 1
      GBase/Installers/DataHandlingInstaller.cs
  27. 3
      GBase/Installers/GBaseInstaller.cs
  28. 2
      GBase/Interfaces/DataHandling/IDataWriter.cs
  29. 2
      GBase/Interfaces/DataHandling/Pool/IDataHandlerPool.cs
  30. 8
      GBase/Interfaces/DataHandling/Pool/IPoolItem.cs
  31. 3
      GBase/Interfaces/FileHandling/IFileHandler.cs
  32. 2
      GBase/Interfaces/IGBase.cs
  33. 3
      GBase/Interfaces/IGBaseColumn.cs
  34. 29
      GBase/Interfaces/IGBaseObject.cs
  35. 16
      GBase/Interfaces/IGBaseTable.cs
  36. 2
      README.md
  37. 3
      Test.GBase/DataHandling/XmlDataHandlerLocalIntegrationTest.cs
  38. 6
      Test.GBase/GBaseIntegrationTest/GBaseIntegrationTest.cs
  39. 26
      Test.GBase/GBaseIntegrationTest/Group.cs
  40. 5
      Test.GBase/GBaseIntegrationTest/IGroup.cs
  41. 4
      Test.GBase/GBaseIntegrationTest/IItem.cs
  42. 23
      Test.GBase/GBaseIntegrationTest/Item.cs
  43. 12
      Test.GBase/GBaseIntegrationTest/Model.cs
  44. 4
      Test.GBase/GBaseTableIntegrationTest.cs
  45. 10
      Test.GBase/Helpers/EnumerablesTest.cs
  46. 10
      Test.GBase/TestClasses/Foo.cs
  47. 1
      Test.GBase/TestClasses/IUserType.cs
  48. 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

@ -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,22 @@
// Author: Gockner, Simon
// Created: 2020-02-14
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System.Collections.Generic;
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);
void Initialize(List<object> parameters);
}
}

@ -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; }
}
}

@ -37,7 +37,7 @@ namespace GBase.DataHandling.Pool
_waitingRequesters = new List<IPoolRequest>();
}
public async Task<IPoolItem<IDataHandler>> RequestDataHandler(object requester, bool overwrite, CancellationToken cancellationToken)
public async Task<IDataHandler> RequestDataHandler(object requester, bool overwrite, CancellationToken cancellationToken)
{
if (_pool.All(i => i.InUse) && _pool.Count == _availableDataHandlers) //no free dataHandlers available
return await WaitForDataHandler(requester, cancellationToken);
@ -47,17 +47,17 @@ namespace GBase.DataHandling.Pool
return GetDataHandler();
}
private async Task<IPoolItem<IDataHandler>> WaitForDataHandler(object requester, CancellationToken cancellationToken)
private async Task<IDataHandler> WaitForDataHandler(object requester, CancellationToken cancellationToken)
{
IPoolItem<IDataHandler> dataHandlerItem = null;
IDataHandler dataHandler = null;
IPoolRequest request = _poolRequestFactory.Create(requester);
while (dataHandlerItem == null)
while (dataHandler == null)
{
if (_waitingRequesters.Contains(request) && _waitingRequesters.IndexOf(request) == 0) //request is in list and is first
{
if (_pool.Any(i => !i.InUse))
dataHandlerItem = GetDataHandler();
dataHandler = GetDataHandler();
else
await Task.Delay(1000, cancellationToken);
}
@ -69,19 +69,26 @@ namespace GBase.DataHandling.Pool
_waitingRequesters.Remove(request);
return dataHandlerItem;
return dataHandler;
}
private IPoolItem<IDataHandler> CreateDataHandler(bool overwrite)
private IDataHandler CreateDataHandler(bool overwrite)
{
IPoolItem<IDataHandler> item = _poolItemFactory.Create(_dataHandlerFactory.Create());
item.Item.Init(overwrite);
_pool.Add(item);
return item;
item.InUse = true;
return item.Item;
}
private IPoolItem<IDataHandler> GetDataHandler() => _pool.First(i => !i.InUse);
private IDataHandler GetDataHandler()
{
IPoolItem<IDataHandler> item = _pool.First(i => !i.InUse);
item.InUse = true;
return item.Item;
}
public async ValueTask DisposeAsync()
{

@ -14,14 +14,6 @@ namespace GBase.DataHandling.Pool
}
public T Item { get; }
public bool InUse { get; private set; }
public T Use()
{
InUse = true;
return Item;
}
public void Dispose() => InUse = false;
public bool InUse { get; set; }
}
}

@ -48,6 +48,7 @@ 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="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>
@ -79,11 +80,12 @@ namespace GBase.DataHandling
public async Task<bool> AddEntry<T>(T entry, IGBaseTable table, FileStream entryFile, CancellationToken cancellationToken)
{
await _xmlDataWriter.InitFile(entryFile, table.Type.Name, cancellationToken);
if (!await _xmlDataWriter.InitFile(entryFile, table.Type.Name, cancellationToken))
return false;
foreach (var column in table.Columns)
{
//set value for each column
//TODO: Set value for each column
PropertyInfo property = entry.GetType().GetProperty(column.Name);
if (property == null)
continue; //TODO: What to do in this case? (Shouldn't really happen...)

@ -12,25 +12,16 @@ 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;
/// <summary>
/// An <see cref="IDataReader"/> that reads from a xml file
/// </summary>
/// <param name="gBase">The <see cref="IGBase"/></param>
public XmlDataReader(IGBase gBase) => _gBase = gBase;
/// <summary>
/// Read the data of a property
/// </summary>
@ -49,7 +40,6 @@ namespace GBase.DataHandling
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
@ -75,9 +65,9 @@ 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();
return values.Select(value => (TProperty)Convert.ChangeType(value, typeof(TProperty))).ToList();
}, cancellationToken);
}
}

@ -27,16 +27,18 @@ namespace GBase.DataHandling
/// <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> InitFile(FileStream file, string rootElementName, CancellationToken cancellationToken)
{
//if the xml file isn't empty, return
if (file.Length > 3) //> 3 because of BOM
return;
return true; //TODO: Don't return bool?
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);
return true;
}
/// <summary>
@ -72,7 +74,7 @@ namespace GBase.DataHandling
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
file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
XDocument xmlDocument = await XDocument.LoadAsync(file, LoadOptions.None, cancellationToken);
file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it

@ -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)
{
}
}
}

@ -3,21 +3,21 @@
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using GBase.Interfaces;
using GBase.Api;
namespace GBase.Exceptions
{
/// <summary>
/// <see cref="Exception"/> that the passed table type doesn't implement <see cref="IGBaseObject"/>"/>
/// <see cref="Exception"/> that the passed table type doesn't implement <see cref="INotifyGBaseEntryChanged"/>"/>
/// </summary>
public class InvalidTableTypeException : Exception
{
/// <summary>
/// <see cref="Exception"/> that the passed table type doesn't implement <see cref="IGBaseObject"/>"/>
/// <see cref="Exception"/> that the passed table type doesn't implement <see cref="INotifyGBaseEntryChanged"/>"/>
/// </summary>
/// <param name="type">The table type</param>
public InvalidTableTypeException(Type type)
: base($"Table type ({type}) doesn't implement {nameof(IGBaseObject)}.")
: base($"Table type ({type}) doesn't implement {nameof(INotifyGBaseEntryChanged)}.")
{
Type = type;
}

@ -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.")
{
}
}
}

@ -3,7 +3,6 @@
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
using GBase.Exceptions;
using GBase.FileHandling.Factories;
using GBase.Interfaces;
using GBase.Interfaces.DataHandling.Pool;
@ -39,9 +38,6 @@ namespace GBase.Factories
/// <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);
}

@ -17,6 +17,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(string name, Type type);
}
}

@ -60,7 +60,7 @@ namespace GBase.FileHandling
return _files;
}
public IGBaseFile CreateEntryFile<T>(T entry, IGBaseTable table) where T : IGBaseObject
public IGBaseFile CreateEntryFile<T>(T entry, IGBaseTable table)
{
string directoryPath = Path.Combine(_path, table.FolderName);
@ -68,7 +68,7 @@ namespace GBase.FileHandling
Directory.CreateDirectory(directoryPath);
//create new entry file
string filePath = $"{Path.Combine(directoryPath, entry.FileName)}.{GBASE_TABLE_FILE_EXTENSION}";
string filePath = $"{Path.Combine(directoryPath, entry.ToString())}.{GBASE_TABLE_FILE_EXTENSION}";
//check if file is already opened
IGBaseFile file = _files.FirstOrDefault(f => f.FilePath.Equals(filePath));

@ -8,6 +8,7 @@ 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;
@ -102,6 +103,8 @@ namespace GBase
return Tables.OfType<IGBaseTable<T>>().First();
throw new MissingTableException<T>();
// //TODO: This probably doesn't work, because even though t.Type : T, IGBaseTable<t.Type> !: IGBaseTable<T>
// return (IGBaseTable<T>) Convert.ChangeType(Tables.FirstOrDefault(t => typeof(T).IsAssignableFrom(t.Type)), typeof(IGBaseTable<T>)); //TestMe
}
/// <summary>
@ -126,15 +129,6 @@ namespace GBase
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>();

@ -201,6 +201,7 @@
<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="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>
@ -260,15 +261,9 @@
</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(GBase.Interfaces.IGBase)">
<summary>
An <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file
</summary>
<param name="gBase">The <see cref="T:GBase.Interfaces.IGBase"/></param>
</member>
<member name="M:GBase.DataHandling.XmlDataReader.Read``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary>
Read the data of a property
@ -368,12 +363,12 @@
</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"/>"/>
<see cref="T:System.Exception"/> that the passed table type doesn't implement <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/>"/>
</summary>
</member>
<member name="M:GBase.Exceptions.InvalidTableTypeException.#ctor(System.Type)">
<summary>
<see cref="T:System.Exception"/> that the passed table type doesn't implement <see cref="T:GBase.Interfaces.IGBaseObject"/>"/>
<see cref="T:System.Exception"/> that the passed table type doesn't implement <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/>"/>
</summary>
<param name="type">The table type</param>
</member>
@ -411,7 +406,7 @@
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(System.String,System.Type)">
<summary>
Creates an <see cref="T:GBase.Interfaces.IGBaseColumn"/>
</summary>
@ -542,7 +537,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(System.String,System.Type)">
<summary>
A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary>
@ -629,17 +624,17 @@
</member>
<member name="M:GBase.GBaseTable`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"/>
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="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<param name="cancellationToken"></param>
<returns>True if successful, false if not</returns>
</member>
<member name="M:GBase.GBaseTable`1.RemoveEntry(`0)">
<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`1.DisposeAsync">
@ -653,16 +648,14 @@
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>
@ -1034,27 +1027,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"/>
@ -1062,17 +1034,17 @@
</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"/>
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="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<param name="cancellationToken"></param>
<returns>True if successful, false if not</returns>
</member>
<member name="M:GBase.Interfaces.IGBaseTable`1.RemoveEntry(`0)">
<summary>
Remove an entry that implements <see cref="T:GBase.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="T:GBase.Interfaces.IGBaseTable">

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

@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using GBase.Api;
using GBase.Exceptions;
using GBase.Interfaces;
@ -28,9 +29,6 @@ namespace GBase
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);
@ -40,6 +38,12 @@ namespace GBase
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);
/// <summary>
/// Initialize this <see cref="GBaseObject{T}"/> from a given <see cref="string"/>
/// </summary>
/// <param name="string">The given <see cref="string"/></param>
public abstract void InitializeFromString(string @string);
public abstract void Initialize(List<object> parameters);
}
}

@ -8,8 +8,8 @@ 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;
@ -66,18 +66,6 @@ namespace GBase
/// </summary>
public List<T> Entries { get; }
private int CurrentLastKey
{
get
{
T lastEntry = Entries.LastOrDefault();
if (lastEntry == null)
return -1;
return lastEntry.Key;
}
}
/// <summary>
/// Initialize this <see cref="IGBase"/>
@ -87,7 +75,7 @@ namespace GBase
/// <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 databasePath, string folderName, CancellationToken cancellationToken) //TODO: Remove bool return value?
{
Type = type;
FolderName = folderName;
@ -95,19 +83,17 @@ namespace GBase
//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(property.Name, property.PropertyType);
AddColumn(gBaseColumn);
}
List<IGBaseFile> files = _fileHandler.Init(databasePath, FolderName, cancellationToken);
if (files == null)
return;
return true;
foreach (var file in files) //create entries for existing files
{
@ -116,33 +102,25 @@ namespace GBase
T entry = new T();
List<object> parameters = new List<object>();
foreach (var column in Columns.Where(c => !c.IsKey))
foreach (var column in Columns)
{
using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
parameters.Add(await GenericMethodCaller.CallAsync(dataHandlerItem.Use(),
parameters.Add(await GenericMethodCaller.CallAsync(dataHandler,
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);
entry.Initialize(parameters);
file.Entry = entry;
Entries.Add(entry);
}
}
return true;
}
/// <summary>
@ -173,35 +151,26 @@ 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="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <param name="cancellationToken"></param>
/// <returns>True if successful, false if not</returns>
public async Task<bool> AddEntry(T entry, CancellationToken cancellationToken)
{
entry.Key ??= new GBaseKey();
if (entry.Key != -1)
throw new InvalidKeyException("Key of entry is already set. Make sure it is -1 when initializing.");
entry.Key.Key = CurrentLastKey + 1; //set next possible key
Entries.Add(entry);
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);
IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
await dataHandler.AddEntry(entry, this, file.File, cancellationToken);
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)
{
@ -216,22 +185,22 @@ namespace GBase
public async Task SetValue<TProperty>(T entry, string propertyName, TProperty value, CancellationToken cancellationToken)
{
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);
IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
await dataHandler.SetValue<T, TProperty>(file.File, propertyName, value, cancellationToken);
}
public async Task<TProperty> GetValue<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().GetValue<T, TProperty>(file.File, propertyName, cancellationToken);
IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
return await dataHandler.GetValue<T, TProperty>(file.File, propertyName, cancellationToken);
}
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);
IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
return await dataHandler.GetValues<T, TProperty>(file.File, propertyName, cancellationToken);
}
/// <summary>

@ -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);

@ -38,7 +38,6 @@ namespace GBase.Installers
//pool
container.Register<IDataHandlerPool, DataHandlerPool>(Lifestyle.Singleton).WithParameters(10);
container.Register<IPoolRequest, PoolRequest>();
container.Register<IPoolItemFactory, PoolItemFactory>();
container.RegisterFactory<IPoolRequestFactory>();

@ -5,7 +5,6 @@
using GBase.Factories;
using GBase.Interfaces;
using LightweightIocContainer;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Installers;
@ -19,7 +18,7 @@ namespace GBase.Installers
/// <inheritdoc />
public void Install(IIocContainer container)
{
container.Register<IGBase, GBase>(Lifestyle.Singleton);
container.Register<IGBase, GBase>();
container.Register<IGBaseColumn, GBaseColumn>();
//factories

@ -21,7 +21,7 @@ namespace GBase.Interfaces.DataHandling
/// <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> InitFile(FileStream file, string rootElementName, CancellationToken cancellationToken);
/// <summary>
/// Write the data of a property

@ -10,6 +10,6 @@ namespace GBase.Interfaces.DataHandling.Pool
{
public interface IDataHandlerPool : IAsyncDisposable
{
Task<IPoolItem<IDataHandler>> RequestDataHandler(object requester, bool overwrite, CancellationToken cancellationToken);
Task<IDataHandler> RequestDataHandler(object requester, bool overwrite, CancellationToken cancellationToken);
}
}

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

@ -6,7 +6,6 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using GBase.Api;
namespace GBase.Interfaces.FileHandling
{
@ -24,7 +23,7 @@ namespace GBase.Interfaces.FileHandling
/// <returns>True if successful, false if not</returns>
List<IGBaseFile> Init(string path, string folderName, CancellationToken cancellationToken);
IGBaseFile CreateEntryFile<T>(T entry, IGBaseTable table) where T : IGBaseObject;
IGBaseFile CreateEntryFile<T>(T entry, IGBaseTable table);
Task<bool> DeleteEntryFile<T>(T entry);

@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using GBase.Api;
using GBase.Interfaces.Settings;
namespace GBase.Interfaces
@ -58,7 +59,6 @@ namespace GBase.Interfaces
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();

@ -9,10 +9,9 @@ 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,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using GBase.Api;
namespace GBase.Interfaces
{
@ -17,19 +18,20 @@ namespace GBase.Interfaces
List<T> Entries { get; }
/// <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="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <param name="cancellationToken"></param>
/// <returns>True if successful, false if not</returns>
Task<bool> AddEntry(T entry, CancellationToken cancellationToken);
T GetEntryForKey(int key);
//T GetEntry(T entry); //TODO: This doesn't make sense... (passing instance of T to get the same instance back...)
/// <summary>
/// Remove an entry that implements <see cref="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>
Task<bool> RemoveEntry(T entry);
@ -43,7 +45,7 @@ namespace GBase.Interfaces
/// <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
@ -69,7 +71,7 @@ namespace GBase.Interfaces
/// <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 databasePath, string folderName, CancellationToken cancellationToken);
/// <summary>
/// Add a given <see cref="IGBaseColumn"/> to this <see cref="IGBaseTable"/>

@ -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)

@ -10,7 +10,6 @@ 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;
@ -34,7 +33,7 @@ namespace Test.GBase.DataHandling
Mock<IXmlDataReaderFactory> dataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
dataReaderFactoryMock.Setup(r => r.Create())
.Returns(new XmlDataReader(Mock.Of<IGBase>()));
.Returns(new XmlDataReader());
Mock<IXmlDataHandlerCachePropertyEntryFactory> dataHandlerCachePropertyEntryFactoryMock = new Mock<IXmlDataHandlerCachePropertyEntryFactory>();
dataHandlerCachePropertyEntryFactoryMock.Setup(p => p.Create(It.IsAny<string>(), It.IsAny<object>()))

@ -48,9 +48,9 @@ namespace Test.GBase.GBaseIntegrationTest
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);
await model.AddGroup(new Group(1), _cancellationTokenSource.Token);
await model.AddGroup(new Group(2), _cancellationTokenSource.Token);
await model.AddGroup(new Group(3), _cancellationTokenSource.Token);
}
}
}

@ -3,7 +3,6 @@
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System.Collections.Generic;
using GBase;
using GBase.Attributes;
namespace Test.GBase.GBaseIntegrationTest
@ -13,29 +12,24 @@ namespace Test.GBase.GBaseIntegrationTest
{
public Group()
{
Items = new List<Item>();
Items = new List<IItem>();
}
public Group(int number)
public Group(int key)
{
Number = number;
Items = new List<Item>();
Key = key;
Items = new List<IItem>();
}
[GBaseColumn]
public int Number { get; private set; }
[GBaseColumn]
public List<Item> Items { get; }
public int Key { get; private set; }
public List<IItem> 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)
public override string ToString() => $"{Key}";
public void InitializeFromString(string @string) => Key = int.Parse(@string);
public void Initialize(List<object> parameters)
{
Key = key;
Number = (int) parameters[0];
Key = (int) parameters[0];
}
}
}

@ -4,13 +4,12 @@
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; }
int Key { get; }
List<IItem> Items { get; }
}
}

@ -2,13 +2,13 @@
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
using GBase.Interfaces;
using GBase.Api;
namespace Test.GBase.GBaseIntegrationTest
{
public interface IItem : IGBaseObject //: INotifyGBaseEntryChanged
{
string Name { get; }
int Number { get; }
int Key { get; }
}
}

@ -3,7 +3,6 @@
// Copyright(c) 2020 SimonG. All Rights Reserved.
using System.Collections.Generic;
using GBase;
using GBase.Attributes;
namespace Test.GBase.GBaseIntegrationTest
@ -16,28 +15,32 @@ namespace Test.GBase.GBaseIntegrationTest
}
public Item(string name, int number)
public Item(string name, int key)
{
Name = name;
Number = number;
Key = key;
}
[GBaseColumn]
public string Name { get; private set; }
[GBaseColumn]
public int Number { get; private set; }
public int Key { get; private set; }
public GBaseKey Key { get; set; }
public string FileName => Name;
public override string ToString() => $"{Name}";
public override string ToString() => $"{Number}/{Name}";
public void InitializeFromString(string @string)
{
string[] properties = @string.Split('/');
public void Initialize(GBaseKey key, List<object> parameters)
Key = int.Parse(properties[0]);
Name = properties[1];
}
public void Initialize(List<object> parameters)
{
Key = key;
Name = (string) parameters[0];
Number = (int) parameters[1];
Key = (int) parameters[1];
}
}
}

@ -19,23 +19,23 @@ namespace Test.GBase.GBaseIntegrationTest
public Model(IGBaseFactory gBaseFactory)
{
_gBase = gBaseFactory.Create(new Settings());
Items = new List<Item>();
Groups = new List<Group>();
Items = new List<IItem>();
Groups = new List<IGroup>();
}
public List<Item> Items { get; private set; }
public List<Group> Groups { get; private set; }
public List<IItem> Items { get; private set; }
public List<IGroup> Groups { get; private set; }
public async Task Initialize(CancellationToken cancellationToken)
{
await _gBase.Init("DB", Assembly.GetExecutingAssembly(), cancellationToken);
IGBaseTable<Item> itemsTable = _gBase.GetTable<Item>();
Items = itemsTable.Entries.ToList();
Items = itemsTable.Entries.Cast<IItem>().ToList();
//Items = (await _gBase.GetValues<Model, Item>(this, nameof(Items), cancellationToken)).Cast<IItem>().ToList();
IGBaseTable<Group> groupsTable = _gBase.GetTable<Group>();
Groups = groupsTable.Entries.ToList();
Groups = groupsTable.Entries.Cast<IGroup>().ToList();
//Groups = (await _gBase.GetValues<Model, Group>(this, nameof(Groups), cancellationToken)).Cast<IGroup>().ToList();
}

@ -27,8 +27,8 @@ namespace Test.GBase
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); })
gBaseColumnFactoryMock.Setup(c => c.Create(It.IsAny<string>(), It.IsAny<Type>()))
.Callback<string, Type>((name, type) => { gBaseColumn = new GBaseColumn(name, type); })
.Returns(gBaseColumn);
Mock<IDataHandlerPool> dataHandlerPoolMock = new Mock<IDataHandlerPool>();

@ -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);
}
}

@ -4,10 +4,8 @@
using System;
using System.Collections.Generic;
using GBase;
using GBase.Api;
using GBase.Attributes;
using GBase.Interfaces;
namespace Test.GBase.TestClasses
{
@ -37,10 +35,12 @@ namespace Test.GBase.TestClasses
}
}
public GBaseKey Key { get; set; }
public string FileName => Name;
public void InitializeFromString(string @string)
{
throw new NotImplementedException();
}
public void Initialize(GBaseKey key, List<object> parameters)
public void Initialize(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
{

@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using GBase;
namespace Test.GBase.TestClasses
{
@ -23,10 +22,13 @@ namespace Test.GBase.TestClasses
private int Number { get; set; }
public GBaseKey Key { get; set; }
public string FileName { get; }
public void InitializeFromString(string @string)
{
string numberString = @string.Split('_').Last();
Number = Convert.ToInt32(numberString);
}
public void Initialize(GBaseKey key, List<object> parameters)
public void Initialize(List<object> parameters)
{
throw new NotImplementedException();
}

Loading…
Cancel
Save