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. 26
      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"> <project version="4">
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.GBase/.idea/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.GBase/.idea/riderModule.iml" /> <module fileurl="file://$PROJECT_DIR$/.idea/.idea.GBase/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.GBase/riderModule.iml" />
</modules> </modules>
</component> </component>
</project> </project>

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

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

@ -0,0 +1,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)] [AttributeUsage(AttributeTargets.Property)]
public class GBaseColumnAttribute : Attribute 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>(); _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 if (_pool.All(i => i.InUse) && _pool.Count == _availableDataHandlers) //no free dataHandlers available
return await WaitForDataHandler(requester, cancellationToken); return await WaitForDataHandler(requester, cancellationToken);
@ -47,17 +47,17 @@ namespace GBase.DataHandling.Pool
return GetDataHandler(); 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); 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 (_waitingRequesters.Contains(request) && _waitingRequesters.IndexOf(request) == 0) //request is in list and is first
{ {
if (_pool.Any(i => !i.InUse)) if (_pool.Any(i => !i.InUse))
dataHandlerItem = GetDataHandler(); dataHandler = GetDataHandler();
else else
await Task.Delay(1000, cancellationToken); await Task.Delay(1000, cancellationToken);
} }
@ -69,19 +69,26 @@ namespace GBase.DataHandling.Pool
_waitingRequesters.Remove(request); _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()); IPoolItem<IDataHandler> item = _poolItemFactory.Create(_dataHandlerFactory.Create());
item.Item.Init(overwrite); item.Item.Init(overwrite);
_pool.Add(item); _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() public async ValueTask DisposeAsync()
{ {

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

@ -48,6 +48,7 @@ namespace GBase.DataHandling
/// <summary> /// <summary>
/// A <see cref="IDataHandler"/> that handles its data in an xml file /// A <see cref="IDataHandler"/> that handles its data in an xml file
/// </summary> /// </summary>
/// <param name="path">The path to the xml file</param>
/// <param name="xmlDataReaderFactory">The <see cref="IXmlDataReader"/> factory</param> /// <param name="xmlDataReaderFactory">The <see cref="IXmlDataReader"/> factory</param>
/// <param name="xmlDataWriterFactory">The <see cref="IXmlDataWriter"/> factory</param> /// <param name="xmlDataWriterFactory">The <see cref="IXmlDataWriter"/> factory</param>
/// <param name="xmlDataHandlerCacheFactory">The <see cref="IXmlDataHandlerCache"/> factory</param> /// <param name="xmlDataHandlerCacheFactory">The <see cref="IXmlDataHandlerCache"/> factory</param>
@ -79,11 +80,12 @@ namespace GBase.DataHandling
public async Task<bool> AddEntry<T>(T entry, IGBaseTable table, FileStream entryFile, CancellationToken cancellationToken) 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) foreach (var column in table.Columns)
{ {
//set value for each column //TODO: Set value for each column
PropertyInfo property = entry.GetType().GetProperty(column.Name); PropertyInfo property = entry.GetType().GetProperty(column.Name);
if (property == null) if (property == null)
continue; //TODO: What to do in this case? (Shouldn't really happen...) 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 System.Xml.Linq;
using GBase.DataHandling.Exceptions; using GBase.DataHandling.Exceptions;
using GBase.Helpers; using GBase.Helpers;
using GBase.Interfaces;
using GBase.Interfaces.DataHandling; using GBase.Interfaces.DataHandling;
using GBase.Interfaces.DataHandling.Xml; using GBase.Interfaces.DataHandling.Xml;
namespace GBase.DataHandling namespace GBase.DataHandling
{ {
/// <summary> /// <summary>
/// An <see cref="IDataReader"/> that reads from a xml file /// A <see cref="IDataReader"/> that reads from a xml file
/// </summary> /// </summary>
public class XmlDataReader : IXmlDataReader public class XmlDataReader : IXmlDataReader
{ {
private readonly IGBase _gBase;
/// <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> /// <summary>
/// Read the data of a property /// Read the data of a property
/// </summary> /// </summary>
@ -49,7 +40,6 @@ namespace GBase.DataHandling
if (typeName == null) if (typeName == null)
throw new ArgumentNullException(nameof(typeName)); throw new ArgumentNullException(nameof(typeName));
file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to load it
XDocument xmlDocument = await XDocument.LoadAsync(file, LoadOptions.None, cancellationToken); 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
@ -75,9 +65,9 @@ namespace GBase.DataHandling
IEnumerable<string> values = valueElements.Select(v => v.Value); IEnumerable<string> values = valueElements.Select(v => v.Value);
if (typeof(TProperty) != typeof(string) && typeof(TProperty).GetInterfaces().Contains(typeof(IEnumerable))) //read property is an IEnumerable if (typeof(TProperty) != typeof(string) && typeof(TProperty).GetInterfaces().Contains(typeof(IEnumerable))) //read property is an IEnumerable
return values.Select(s => Enumerables.ConvertToGBaseEnumerable<TProperty>(s, _gBase)).ToList(); return values.Select(Enumerables.ConvertToGBaseEnumerable<TProperty>).ToList();
return values.Select(value => (TProperty) Convert.ChangeType(value, typeof(TProperty))).ToList(); return values.Select(value => (TProperty)Convert.ChangeType(value, typeof(TProperty))).ToList();
}, cancellationToken); }, cancellationToken);
} }
} }

@ -27,16 +27,18 @@ namespace GBase.DataHandling
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param>
/// <returns>Returns true if successful, false if not</returns> /// <returns>Returns true if successful, false if not</returns>
/// <exception cref="Exception">No root element found</exception> /// <exception cref="Exception">No root element found</exception>
public async Task InitFile(FileStream file, string rootElementName, CancellationToken cancellationToken) public async Task<bool> InitFile(FileStream file, string rootElementName, CancellationToken cancellationToken)
{ {
//if the xml file isn't empty, return //if the xml file isn't empty, return
if (file.Length > 3) //> 3 because of BOM if (file.Length > 3) //> 3 because of BOM
return; return true; //TODO: Don't return bool?
XDocument xmlDocument = new XDocument(); XDocument xmlDocument = new XDocument();
xmlDocument.Add(new XElement(rootElementName)); xmlDocument.Add(new XElement(rootElementName));
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
await xmlDocument.SaveAsync(file, SaveOptions.OmitDuplicateNamespaces, cancellationToken); await xmlDocument.SaveAsync(file, SaveOptions.OmitDuplicateNamespaces, cancellationToken);
return true;
} }
/// <summary> /// <summary>
@ -72,7 +74,7 @@ namespace GBase.DataHandling
if (typeName == null) if (typeName == null)
throw new ArgumentNullException(nameof(typeName)); throw new ArgumentNullException(nameof(typeName));
file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to load it file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
XDocument xmlDocument = await XDocument.LoadAsync(file, LoadOptions.None, cancellationToken); 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

@ -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. // Copyright(c) 2020 SimonG. All Rights Reserved.
using System; using System;
using GBase.Interfaces; using GBase.Api;
namespace GBase.Exceptions namespace GBase.Exceptions
{ {
/// <summary> /// <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> /// </summary>
public class InvalidTableTypeException : Exception public class InvalidTableTypeException : Exception
{ {
/// <summary> /// <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> /// </summary>
/// <param name="type">The table type</param> /// <param name="type">The table type</param>
public InvalidTableTypeException(Type type) public InvalidTableTypeException(Type type)
: base($"Table type ({type}) doesn't implement {nameof(IGBaseObject)}.") : base($"Table type ({type}) doesn't implement {nameof(INotifyGBaseEntryChanged)}.")
{ {
Type = type; 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. // Copyright(c) 2020 SimonG. All Rights Reserved.
using System; using System;
using GBase.Exceptions;
using GBase.FileHandling.Factories; using GBase.FileHandling.Factories;
using GBase.Interfaces; using GBase.Interfaces;
using GBase.Interfaces.DataHandling.Pool; 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> /// <returns>A newly created instance of the implementation for <see cref="IGBaseTable"/></returns>
public IGBaseTable Create(Type type) public IGBaseTable Create(Type type)
{ {
if (!typeof(IGBaseObject).IsAssignableFrom(type))
throw new InvalidTableTypeException(type);
Type gBaseTableType = typeof(GBaseTable<>).MakeGenericType(type); Type gBaseTableType = typeof(GBaseTable<>).MakeGenericType(type);
return (IGBaseTable) Activator.CreateInstance(gBaseTableType, _fileHandlerFactory, _dataHandlerPool, _gBaseColumnFactory); return (IGBaseTable) Activator.CreateInstance(gBaseTableType, _fileHandlerFactory, _dataHandlerPool, _gBaseColumnFactory);
} }

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

@ -60,7 +60,7 @@ namespace GBase.FileHandling
return _files; 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); string directoryPath = Path.Combine(_path, table.FolderName);
@ -68,7 +68,7 @@ namespace GBase.FileHandling
Directory.CreateDirectory(directoryPath); Directory.CreateDirectory(directoryPath);
//create new entry file //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 //check if file is already opened
IGBaseFile file = _files.FirstOrDefault(f => f.FilePath.Equals(filePath)); IGBaseFile file = _files.FirstOrDefault(f => f.FilePath.Equals(filePath));

@ -8,6 +8,7 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.Api;
using GBase.Attributes; using GBase.Attributes;
using GBase.Exceptions; using GBase.Exceptions;
using GBase.Factories; using GBase.Factories;
@ -102,6 +103,8 @@ namespace GBase
return Tables.OfType<IGBaseTable<T>>().First(); return Tables.OfType<IGBaseTable<T>>().First();
throw new MissingTableException<T>(); throw new MissingTableException<T>();
// //TODO: This probably doesn't work, because even though t.Type : T, IGBaseTable<t.Type> !: IGBaseTable<T>
// return (IGBaseTable<T>) Convert.ChangeType(Tables.FirstOrDefault(t => typeof(T).IsAssignableFrom(t.Type)), typeof(IGBaseTable<T>)); //TestMe
} }
/// <summary> /// <summary>
@ -126,15 +129,6 @@ namespace GBase
return await table.AddEntry(entry, cancellationToken); 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() public async Task SetValue<T, TProperty>(T entry, string propertyName, TProperty value, CancellationToken cancellationToken) where T : IGBaseObject, new()
{ {
IGBaseTable<T> table = GetTable<T>(); IGBaseTable<T> table = GetTable<T>();

@ -201,6 +201,7 @@
<summary> <summary>
A <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/> that handles its data in an xml file A <see cref="T:GBase.Interfaces.DataHandling.IDataHandler"/> that handles its data in an xml file
</summary> </summary>
<param name="path">The path to the xml file</param>
<param name="xmlDataReaderFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/> factory</param> <param name="xmlDataReaderFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataReader"/> factory</param>
<param name="xmlDataWriterFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/> factory</param> <param name="xmlDataWriterFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.IXmlDataWriter"/> factory</param>
<param name="xmlDataHandlerCacheFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.Cache.IXmlDataHandlerCache"/> factory</param> <param name="xmlDataHandlerCacheFactory">The <see cref="T:GBase.Interfaces.DataHandling.Xml.Cache.IXmlDataHandlerCache"/> factory</param>
@ -260,15 +261,9 @@
</member> </member>
<member name="T:GBase.DataHandling.XmlDataReader"> <member name="T:GBase.DataHandling.XmlDataReader">
<summary> <summary>
An <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file A <see cref="T:GBase.Interfaces.DataHandling.IDataReader"/> that reads from a xml file
</summary> </summary>
</member> </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)"> <member name="M:GBase.DataHandling.XmlDataReader.Read``2(System.IO.FileStream,System.String,System.Threading.CancellationToken)">
<summary> <summary>
Read the data of a property Read the data of a property
@ -368,12 +363,12 @@
</member> </member>
<member name="T:GBase.Exceptions.InvalidTableTypeException"> <member name="T:GBase.Exceptions.InvalidTableTypeException">
<summary> <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> </summary>
</member> </member>
<member name="M:GBase.Exceptions.InvalidTableTypeException.#ctor(System.Type)"> <member name="M:GBase.Exceptions.InvalidTableTypeException.#ctor(System.Type)">
<summary> <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> </summary>
<param name="type">The table type</param> <param name="type">The table type</param>
</member> </member>
@ -411,7 +406,7 @@
Factory for the <see cref="T:GBase.Interfaces.IGBaseColumn"/> Factory for the <see cref="T:GBase.Interfaces.IGBaseColumn"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.Factories.IGBaseColumnFactory.Create(System.String,System.Type,System.Boolean)"> <member name="M:GBase.Factories.IGBaseColumnFactory.Create(System.String,System.Type)">
<summary> <summary>
Creates an <see cref="T:GBase.Interfaces.IGBaseColumn"/> Creates an <see cref="T:GBase.Interfaces.IGBaseColumn"/>
</summary> </summary>
@ -542,7 +537,7 @@
A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/> A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="M:GBase.GBaseColumn.#ctor(System.String,System.Type,System.Boolean)"> <member name="M:GBase.GBaseColumn.#ctor(System.String,System.Type)">
<summary> <summary>
A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/> A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
@ -629,17 +624,17 @@
</member> </member>
<member name="M:GBase.GBaseTable`1.AddEntry(`0,System.Threading.CancellationToken)"> <member name="M:GBase.GBaseTable`1.AddEntry(`0,System.Threading.CancellationToken)">
<summary> <summary>
Add an entry that implements <see cref="T:GBase.Interfaces.IGBaseObject"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/> Add an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
<param name="entry">The entry implementing <see cref="T:GBase.Interfaces.IGBaseObject"/></param> <param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<param name="cancellationToken"></param> <param name="cancellationToken"></param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.GBaseTable`1.RemoveEntry(`0)"> <member name="M:GBase.GBaseTable`1.RemoveEntry(`0)">
<summary> <summary>
Remove an entry that implements <see cref="T:GBase.Interfaces.IGBaseObject"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/> Remove an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
<param name="entry">The entry implementing <see cref="T:GBase.Interfaces.IGBaseObject"/></param> <param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.GBaseTable`1.DisposeAsync"> <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"/> Convert an <see cref="T:System.Collections.IEnumerable"/> to a GBase <see cref="T:System.String"/>
</summary> </summary>
<param name="enumerable">The <see cref="T:System.Collections.IEnumerable"/></param> <param name="enumerable">The <see cref="T:System.Collections.IEnumerable"/></param>
<returns>The converted <see cref="T:System.Collections.IEnumerable"/> as a GBase <see cref="T:System.String"/></returns> <returns></returns>
</member> </member>
<member name="M:GBase.Helpers.Enumerables.ConvertToGBaseEnumerable``1(System.String,GBase.Interfaces.IGBase)"> <member name="M:GBase.Helpers.Enumerables.ConvertToGBaseEnumerable``1(System.String)">
<summary> <summary>
Convert a given <see cref="T:System.String"/> to an <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:System.Type"/> <typeparamref name="TEnumerable"/> Convert a given <see cref="T:System.String"/> to an <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:System.Type"/> <typeparamref name="TEnumerable"/>
</summary> </summary>
<typeparam name="TEnumerable">The <see cref="T:System.Collections.Generic.IEnumerable`1"/> <see cref="T:System.Type"/></typeparam> <typeparam name="TEnumerable">The <see cref="T:System.Collections.Generic.IEnumerable`1"/> <see cref="T:System.Type"/></typeparam>
<typeparam name="T"></typeparam>
<param name="string">The given <see cref="T:System.String"/></param> <param name="string">The given <see cref="T:System.String"/></param>
<param name="gBase"></param>
<returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:System.Type"/> <typeparamref name="TEnumerable"/></returns> <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:System.Type"/> <typeparamref name="TEnumerable"/></returns>
<exception cref="T:GBase.Exceptions.InterfaceEnumerablePassedException">Interface was passed to an <see cref="T:System.Collections.Generic.IEnumerable`1"/></exception> <exception cref="T:GBase.Exceptions.InterfaceEnumerablePassedException">Interface was passed to an <see cref="T:System.Collections.Generic.IEnumerable`1"/></exception>
</member> </member>
@ -1034,27 +1027,6 @@
A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/> A column of a <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
</member> </member>
<member name="T:GBase.Interfaces.IGBaseObject">
<summary>
GBase object that allows conversion from <see cref="T:System.String"/>
</summary>
</member>
<member name="P:GBase.Interfaces.IGBaseObject.Key">
<summary>
<see cref="T:GBase.Interfaces.IGBase"/> Key
</summary>
</member>
<member name="P:GBase.Interfaces.IGBaseObject.FileName">
<summary>
The FileName of the GBase file for an entry of this object
</summary>
</member>
<member name="M:GBase.Interfaces.IGBaseObject.InitializeFromString(System.String)">
<summary>
Initialize this <see cref="T:GBase.Interfaces.IGBaseObject"/> from a given <see cref="T:System.String"/>
</summary>
<param name="string">The given <see cref="T:System.String"/></param>
</member>
<member name="P:GBase.Interfaces.IGBaseTable`1.Entries"> <member name="P:GBase.Interfaces.IGBaseTable`1.Entries">
<summary> <summary>
The entries of this <see cref="T:GBase.Interfaces.IGBaseTable"/> The entries of this <see cref="T:GBase.Interfaces.IGBaseTable"/>
@ -1062,17 +1034,17 @@
</member> </member>
<member name="M:GBase.Interfaces.IGBaseTable`1.AddEntry(`0,System.Threading.CancellationToken)"> <member name="M:GBase.Interfaces.IGBaseTable`1.AddEntry(`0,System.Threading.CancellationToken)">
<summary> <summary>
Add an entry that implements <see cref="T:GBase.Interfaces.IGBaseObject"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/> Add an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> to this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
<param name="entry">The entry implementing <see cref="T:GBase.Interfaces.IGBaseObject"/></param> <param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<param name="cancellationToken"></param> <param name="cancellationToken"></param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="M:GBase.Interfaces.IGBaseTable`1.RemoveEntry(`0)"> <member name="M:GBase.Interfaces.IGBaseTable`1.RemoveEntry(`0)">
<summary> <summary>
Remove an entry that implements <see cref="T:GBase.Interfaces.IGBaseObject"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/> Remove an entry that implements <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/> from this <see cref="T:GBase.Interfaces.IGBaseTable"/>
</summary> </summary>
<param name="entry">The entry implementing <see cref="T:GBase.Interfaces.IGBaseObject"/></param> <param name="entry">The entry implementing <see cref="T:GBase.Api.INotifyGBaseEntryChanged"/></param>
<returns>True if successful, false if not</returns> <returns>True if successful, false if not</returns>
</member> </member>
<member name="T:GBase.Interfaces.IGBaseTable"> <member name="T:GBase.Interfaces.IGBaseTable">

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

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

@ -5,6 +5,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.Api;
using GBase.Exceptions; using GBase.Exceptions;
using GBase.Interfaces; using GBase.Interfaces;
@ -28,9 +29,6 @@ namespace GBase
throw new MissingTableException<T>(); 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) => protected async Task SetValue<TProperty>(T @this, string propertyName, TProperty value, CancellationToken cancellationToken) =>
await _gBaseTable.SetValue(@this, propertyName, value, 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) => protected async Task<IEnumerable<TProperty>> GetValues<TProperty>(T @this, string propertyName, CancellationToken cancellationToken) =>
await _gBaseTable.GetValues<TProperty>(@this, propertyName, 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.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.Api;
using GBase.Attributes; using GBase.Attributes;
using GBase.Exceptions;
using GBase.Factories; using GBase.Factories;
using GBase.FileHandling.Factories; using GBase.FileHandling.Factories;
using GBase.Helpers; using GBase.Helpers;
@ -66,18 +66,6 @@ namespace GBase
/// </summary> /// </summary>
public List<T> Entries { get; } public List<T> Entries { get; }
private int CurrentLastKey
{
get
{
T lastEntry = Entries.LastOrDefault();
if (lastEntry == null)
return -1;
return lastEntry.Key;
}
}
/// <summary> /// <summary>
/// Initialize this <see cref="IGBase"/> /// Initialize this <see cref="IGBase"/>
@ -87,7 +75,7 @@ namespace GBase
/// <param name="folderName"></param> /// <param name="folderName"></param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the asynchronous operation</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the asynchronous operation</param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
public async Task Init(Type type, string databasePath, string folderName, CancellationToken cancellationToken) public async Task<bool> Init(Type type, string databasePath, string folderName, CancellationToken cancellationToken) //TODO: Remove bool return value?
{ {
Type = type; Type = type;
FolderName = folderName; FolderName = folderName;
@ -95,19 +83,17 @@ namespace GBase
//TODO: Init columns list depending on GBaseColumnAttributes set for this GBaseTable //TODO: Init columns list depending on GBaseColumnAttributes set for this GBaseTable
foreach (var property in type.GetProperties()) foreach (var property in type.GetProperties())
{ {
GBaseColumnAttribute gBaseColumnAttribute = property.GetCustomAttribute<GBaseColumnAttribute>() ?? GBaseColumnAttribute gBaseColumnAttribute = property.GetCustomAttribute<GBaseColumnAttribute>();
property.GetAttributeFromInheritedInterfaces<GBaseColumnAttribute>();
if (gBaseColumnAttribute == null) if (gBaseColumnAttribute == null)
continue; continue;
IGBaseColumn gBaseColumn = _gBaseColumnFactory.Create(property.Name, property.PropertyType, gBaseColumnAttribute.IsKey); IGBaseColumn gBaseColumn = _gBaseColumnFactory.Create(property.Name, property.PropertyType);
AddColumn(gBaseColumn); AddColumn(gBaseColumn);
} }
List<IGBaseFile> files = _fileHandler.Init(databasePath, FolderName, cancellationToken); List<IGBaseFile> files = _fileHandler.Init(databasePath, FolderName, cancellationToken);
if (files == null) if (files == null)
return; return true;
foreach (var file in files) //create entries for existing files foreach (var file in files) //create entries for existing files
{ {
@ -116,33 +102,25 @@ namespace GBase
T entry = new T(); T entry = new T();
List<object> parameters = new List<object>(); 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), nameof(IDataHandler.GetValue),
BindingFlags.Public | BindingFlags.Instance, BindingFlags.Public | BindingFlags.Instance,
typeof(T), column.Type, typeof(T), column.Type,
file.File, column.Name, cancellationToken)); file.File, column.Name, cancellationToken));
} }
IGBaseColumn keyColumn = Columns.FirstOrDefault(c => c.IsKey); entry.Initialize(parameters);
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; file.Entry = entry;
Entries.Add(entry); Entries.Add(entry);
} }
} }
return true;
} }
/// <summary> /// <summary>
@ -173,35 +151,26 @@ namespace GBase
} }
/// <summary> /// <summary>
/// Add an entry that implements <see cref="IGBaseObject"/> to this <see cref="IGBaseTable"/> /// Add an entry that implements <see cref="INotifyGBaseEntryChanged"/> to this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
/// <param name="entry">The entry implementing <see cref="IGBaseObject"/></param> /// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
public async Task<bool> AddEntry(T entry, CancellationToken cancellationToken) public async Task<bool> AddEntry(T entry, CancellationToken cancellationToken)
{ {
entry.Key ??= new GBaseKey();
if (entry.Key != -1)
throw new InvalidKeyException("Key of entry is already set. Make sure it is -1 when initializing.");
entry.Key.Key = CurrentLastKey + 1; //set next possible key
Entries.Add(entry); Entries.Add(entry);
using IGBaseFile file = _fileHandler.CreateEntryFile(entry, this); using IGBaseFile file = _fileHandler.CreateEntryFile(entry, this);
using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken); IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
await dataHandlerItem.Use().AddEntry(entry, this, file.File, cancellationToken); await dataHandler.AddEntry(entry, this, file.File, cancellationToken);
return true; return true;
} }
public T GetEntryForKey(int key) => Entries.FirstOrDefault(e => e.Key == key);
/// <summary> /// <summary>
/// Remove an entry that implements <see cref="IGBaseObject"/> from this <see cref="IGBaseTable"/> /// Remove an entry that implements <see cref="INotifyGBaseEntryChanged"/> from this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
/// <param name="entry">The entry implementing <see cref="IGBaseObject"/></param> /// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
public async Task<bool> RemoveEntry(T entry) public 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) public async Task SetValue<TProperty>(T entry, string propertyName, TProperty value, CancellationToken cancellationToken)
{ {
using IGBaseFile file = await _fileHandler.RequestEntryFile(entry); using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken); IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
await dataHandlerItem.Use().SetValue<T, TProperty>(file.File, propertyName, value, cancellationToken); await dataHandler.SetValue<T, TProperty>(file.File, propertyName, value, cancellationToken);
} }
public async Task<TProperty> GetValue<TProperty>(T entry, string propertyName, CancellationToken cancellationToken) public async Task<TProperty> GetValue<TProperty>(T entry, string propertyName, CancellationToken cancellationToken)
{ {
using IGBaseFile file = await _fileHandler.RequestEntryFile(entry); using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken); IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
return await dataHandlerItem.Use().GetValue<T, TProperty>(file.File, propertyName, cancellationToken); return await dataHandler.GetValue<T, TProperty>(file.File, propertyName, cancellationToken);
} }
public async Task<IEnumerable<TProperty>> GetValues<TProperty>(T entry, string propertyName, CancellationToken cancellationToken) public async Task<IEnumerable<TProperty>> GetValues<TProperty>(T entry, string propertyName, CancellationToken cancellationToken)
{ {
using IGBaseFile file = await _fileHandler.RequestEntryFile(entry); using IGBaseFile file = await _fileHandler.RequestEntryFile(entry);
using IPoolItem<IDataHandler> dataHandlerItem = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken); IDataHandler dataHandler = await _dataHandlerPool.RequestDataHandler(this, false, cancellationToken);
return await dataHandlerItem.Use().GetValues<T, TProperty>(file.File, propertyName, cancellationToken); return await dataHandler.GetValues<T, TProperty>(file.File, propertyName, cancellationToken);
} }
/// <summary> /// <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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using GBase.Api;
using GBase.Exceptions; using GBase.Exceptions;
using GBase.Interfaces;
namespace GBase.Helpers namespace GBase.Helpers
{ {
@ -21,16 +20,13 @@ namespace GBase.Helpers
/// Convert an <see cref="IEnumerable"/> to a GBase <see cref="string"/> /// Convert an <see cref="IEnumerable"/> to a GBase <see cref="string"/>
/// </summary> /// </summary>
/// <param name="enumerable">The <see cref="IEnumerable"/></param> /// <param name="enumerable">The <see cref="IEnumerable"/></param>
/// <returns>The converted <see cref="IEnumerable"/> as a GBase <see cref="string"/></returns> /// <returns></returns>
public static string ToGBaseString(this IEnumerable enumerable) public static string ToGBaseString(this IEnumerable enumerable)
{ {
StringBuilder @string = new StringBuilder(); StringBuilder @string = new StringBuilder();
foreach (var item in enumerable) foreach (var item in enumerable)
{ {
if (item is IGBaseObject gBaseObject) @string.Append($"{item}{ENUMERABLE_STRING_DIVIDER}");
@string.Append($"{gBaseObject.Key}{ENUMERABLE_STRING_DIVIDER}");
else
@string.Append($"{item}{ENUMERABLE_STRING_DIVIDER}");
} }
char lastChar = @string[^1]; char lastChar = @string[^1];
@ -45,10 +41,9 @@ namespace GBase.Helpers
/// </summary> /// </summary>
/// <typeparam name="TEnumerable">The <see cref="IEnumerable{T}"/> <see cref="Type"/></typeparam> /// <typeparam name="TEnumerable">The <see cref="IEnumerable{T}"/> <see cref="Type"/></typeparam>
/// <param name="string">The given <see cref="string"/></param> /// <param name="string">The given <see cref="string"/></param>
/// <param name="gBase"></param>
/// <returns>An <see cref="IEnumerable{T}"/> of <see cref="Type"/> <typeparamref name="TEnumerable"/></returns> /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="Type"/> <typeparamref name="TEnumerable"/></returns>
/// <exception cref="InterfaceEnumerablePassedException">Interface was passed to an <see cref="IEnumerable{T}"/></exception> /// <exception cref="InterfaceEnumerablePassedException">Interface was passed to an <see cref="IEnumerable{T}"/></exception>
public static TEnumerable ConvertToGBaseEnumerable<TEnumerable>(string @string, IGBase gBase) public static TEnumerable ConvertToGBaseEnumerable<TEnumerable>(string @string)
{ {
//get generic type parameter of TEnumerable //get generic type parameter of TEnumerable
Type genericType = typeof(TEnumerable).GetGenericArguments()[0]; Type genericType = typeof(TEnumerable).GetGenericArguments()[0];
@ -66,16 +61,9 @@ namespace GBase.Helpers
if (genericType.IsInterface) if (genericType.IsInterface)
throw new InterfaceEnumerablePassedException(genericType); throw new InterfaceEnumerablePassedException(genericType);
if (!int.TryParse(value, out int key)) IGBaseObject gBaseObject = (IGBaseObject) Activator.CreateInstance(genericType);
throw new InvalidKeyException("Key is not an integer."); gBaseObject.InitializeFromString(value);
item = gBaseObject;
//TODO: What to do when this table isn't initialized yet?
item = GenericMethodCaller.Call(gBase, nameof(IGBase.GetEntryForKey),
BindingFlags.Public | BindingFlags.Instance, genericType, key);
// IGBaseObject gBaseObject = (IGBaseObject) Activator.CreateInstance(genericType);
// gBaseObject.InitializeFromString(value);
// item = gBaseObject;
} }
else else
item = Convert.ChangeType(value, genericType); item = Convert.ChangeType(value, genericType);

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

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

@ -21,7 +21,7 @@ namespace GBase.Interfaces.DataHandling
/// <param name="rootElementName"></param> /// <param name="rootElementName"></param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the async operation</param>
/// <returns>Returns true if successful, false if not</returns> /// <returns>Returns true if successful, false if not</returns>
Task InitFile(FileStream file, string rootElementName, CancellationToken cancellationToken); Task<bool> InitFile(FileStream file, string rootElementName, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Write the data of a property /// Write the data of a property

@ -10,6 +10,6 @@ namespace GBase.Interfaces.DataHandling.Pool
{ {
public interface IDataHandlerPool : IAsyncDisposable 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 // Created: 2020-09-19
// Copyright(c) 2020 SimonG. All Rights Reserved. // Copyright(c) 2020 SimonG. All Rights Reserved.
using System;
namespace GBase.Interfaces.DataHandling.Pool namespace GBase.Interfaces.DataHandling.Pool
{ {
public interface IPoolItem<T> : IDisposable public interface IPoolItem<T>
{ {
T Item { get; } T Item { get; }
bool InUse { get; } bool InUse { get; set; }
T Use();
} }
} }

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

@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.Api;
using GBase.Interfaces.Settings; using GBase.Interfaces.Settings;
namespace GBase.Interfaces namespace GBase.Interfaces
@ -58,7 +59,6 @@ namespace GBase.Interfaces
bool RemoveTable(IGBaseTable table); bool RemoveTable(IGBaseTable table);
Task<bool> AddEntry<T>(T entry, CancellationToken cancellationToken) where T : IGBaseObject, new(); 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 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<TProperty> GetValue<T, TProperty>(T entry, string propertyName, CancellationToken cancellationToken) where T : IGBaseObject, new();

@ -9,10 +9,9 @@ namespace GBase.Interfaces
/// <summary> /// <summary>
/// A column of a <see cref="IGBaseTable"/> /// A column of a <see cref="IGBaseTable"/>
/// </summary> /// </summary>
public interface IGBaseColumn : IAsyncDisposable public interface IGBaseColumn : IAsyncDisposable //TODO: Make column generic (generic type is type of the value of the column?)?
{ {
string Name { get; } string Name { get; }
Type Type { 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.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using GBase.Api;
namespace GBase.Interfaces namespace GBase.Interfaces
{ {
@ -17,19 +18,20 @@ namespace GBase.Interfaces
List<T> Entries { get; } List<T> Entries { get; }
/// <summary> /// <summary>
/// Add an entry that implements <see cref="IGBaseObject"/> to this <see cref="IGBaseTable"/> /// Add an entry that implements <see cref="INotifyGBaseEntryChanged"/> to this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
/// <param name="entry">The entry implementing <see cref="IGBaseObject"/></param> /// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
Task<bool> AddEntry(T entry, CancellationToken cancellationToken); 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> /// <summary>
/// Remove an entry that implements <see cref="IGBaseObject"/> from this <see cref="IGBaseTable"/> /// Remove an entry that implements <see cref="INotifyGBaseEntryChanged"/> from this <see cref="IGBaseTable"/>
/// </summary> /// </summary>
/// <param name="entry">The entry implementing <see cref="IGBaseObject"/></param> /// <param name="entry">The entry implementing <see cref="INotifyGBaseEntryChanged"/></param>
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
Task<bool> RemoveEntry(T entry); Task<bool> RemoveEntry(T entry);
@ -43,7 +45,7 @@ namespace GBase.Interfaces
/// <summary> /// <summary>
/// A <see cref="IGBase"/> table /// A <see cref="IGBase"/> table
/// </summary> /// </summary>
public interface IGBaseTable : IAsyncDisposable public interface IGBaseTable : IAsyncDisposable //TODO: make generic?
{ {
/// <summary> /// <summary>
/// The <see cref="System.Type"/> of the class that this <see cref="IGBaseTable"/> represents /// The <see cref="System.Type"/> of the class that this <see cref="IGBaseTable"/> represents
@ -69,7 +71,7 @@ namespace GBase.Interfaces
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the asynchronous operation</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the asynchronous operation</param>
/// /// /// ///
/// <returns>True if successful, false if not</returns> /// <returns>True if successful, false if not</returns>
Task Init(Type type, string databasePath, string folderName, CancellationToken cancellationToken); Task<bool> Init(Type type, string databasePath, string folderName, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Add a given <see cref="IGBaseColumn"/> to this <see cref="IGBaseTable"/> /// Add a given <see cref="IGBaseColumn"/> to this <see cref="IGBaseTable"/>

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

@ -10,7 +10,6 @@ using GBase.DataHandling;
using GBase.DataHandling.Cache; using GBase.DataHandling.Cache;
using GBase.DataHandling.Cache.Factories; using GBase.DataHandling.Cache.Factories;
using GBase.DataHandling.Factories; using GBase.DataHandling.Factories;
using GBase.Interfaces;
using GBase.Interfaces.DataHandling.Xml; using GBase.Interfaces.DataHandling.Xml;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
@ -34,7 +33,7 @@ namespace Test.GBase.DataHandling
Mock<IXmlDataReaderFactory> dataReaderFactoryMock = new Mock<IXmlDataReaderFactory>(); Mock<IXmlDataReaderFactory> dataReaderFactoryMock = new Mock<IXmlDataReaderFactory>();
dataReaderFactoryMock.Setup(r => r.Create()) dataReaderFactoryMock.Setup(r => r.Create())
.Returns(new XmlDataReader(Mock.Of<IGBase>())); .Returns(new XmlDataReader());
Mock<IXmlDataHandlerCachePropertyEntryFactory> dataHandlerCachePropertyEntryFactoryMock = new Mock<IXmlDataHandlerCachePropertyEntryFactory>(); Mock<IXmlDataHandlerCachePropertyEntryFactory> dataHandlerCachePropertyEntryFactoryMock = new Mock<IXmlDataHandlerCachePropertyEntryFactory>();
dataHandlerCachePropertyEntryFactoryMock.Setup(p => p.Create(It.IsAny<string>(), It.IsAny<object>())) dataHandlerCachePropertyEntryFactoryMock.Setup(p => p.Create(It.IsAny<string>(), It.IsAny<object>()))

@ -48,9 +48,9 @@ namespace Test.GBase.GBaseIntegrationTest
await model.AddItem(new Item("Item 2", 2), _cancellationTokenSource.Token); await model.AddItem(new Item("Item 2", 2), _cancellationTokenSource.Token);
await model.AddItem(new Item("Item 3", 3), _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(1), _cancellationTokenSource.Token);
await model.AddGroup(new Group(2) {Items = { model.Items[1], model.Items[2] }}, _cancellationTokenSource.Token); await model.AddGroup(new Group(2), _cancellationTokenSource.Token);
await model.AddGroup(new Group(3) {Items = { model.Items[0], model.Items[2] }}, _cancellationTokenSource.Token); await model.AddGroup(new Group(3), _cancellationTokenSource.Token);
} }
} }
} }

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

@ -4,13 +4,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using GBase.Api; using GBase.Api;
using GBase.Interfaces;
namespace Test.GBase.GBaseIntegrationTest namespace Test.GBase.GBaseIntegrationTest
{ {
public interface IGroup : IGBaseObject //: INotifyGBaseEntryChanged public interface IGroup : IGBaseObject //: INotifyGBaseEntryChanged
{ {
int Number { get; } int Key { get; }
List<Item> Items { get; } List<IItem> Items { get; }
} }
} }

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

@ -3,7 +3,6 @@
// Copyright(c) 2020 SimonG. All Rights Reserved. // Copyright(c) 2020 SimonG. All Rights Reserved.
using System.Collections.Generic; using System.Collections.Generic;
using GBase;
using GBase.Attributes; using GBase.Attributes;
namespace Test.GBase.GBaseIntegrationTest 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; Name = name;
Number = number; Key = key;
} }
[GBaseColumn] [GBaseColumn]
public string Name { get; private set; } public string Name { get; private set; }
[GBaseColumn] [GBaseColumn]
public int Number { get; private set; } public int Key { get; private set; }
public GBaseKey Key { get; set; } public override string ToString() => $"{Name}";
public string FileName => 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]; Name = (string) parameters[0];
Number = (int) parameters[1]; Key = (int) parameters[1];
} }
} }
} }

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

@ -27,8 +27,8 @@ namespace Test.GBase
IGBaseColumn gBaseColumn = null; IGBaseColumn gBaseColumn = null;
Mock<IGBaseColumnFactory> gBaseColumnFactoryMock = new Mock<IGBaseColumnFactory>(); Mock<IGBaseColumnFactory> gBaseColumnFactoryMock = new Mock<IGBaseColumnFactory>();
gBaseColumnFactoryMock.Setup(c => c.Create(It.IsAny<string>(), It.IsAny<Type>(), It.IsAny<bool>())) gBaseColumnFactoryMock.Setup(c => c.Create(It.IsAny<string>(), It.IsAny<Type>()))
.Callback<string, Type, bool>((name, type, isKey) => { gBaseColumn = new GBaseColumn(name, type, isKey); }) .Callback<string, Type>((name, type) => { gBaseColumn = new GBaseColumn(name, type); })
.Returns(gBaseColumn); .Returns(gBaseColumn);
Mock<IDataHandlerPool> dataHandlerPoolMock = new Mock<IDataHandlerPool>(); Mock<IDataHandlerPool> dataHandlerPoolMock = new Mock<IDataHandlerPool>();

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

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

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

@ -5,7 +5,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using GBase;
namespace Test.GBase.TestClasses namespace Test.GBase.TestClasses
{ {
@ -23,10 +22,13 @@ namespace Test.GBase.TestClasses
private int Number { get; set; } private int Number { get; set; }
public GBaseKey Key { get; set; } public void InitializeFromString(string @string)
public string FileName { get; } {
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(); throw new NotImplementedException();
} }

Loading…
Cancel
Save