Configuration refactoring

Append custom parse attribute for config binding/
pull/3/head
Ogoun 2 years ago
parent 426ae54ebb
commit 75e146e411

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
<ItemGroup>

@ -7,8 +7,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Topshelf" Version="4.2.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Topshelf" Version="4.3.0" />
</ItemGroup>
<ItemGroup>

@ -6,7 +6,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ZeroLevel.SqLite\ZeroLevel.SqLite.csproj" />
<ProjectReference Include="..\ZeroLevel\ZeroLevel.csproj" />
</ItemGroup>

@ -0,0 +1,12 @@
namespace ZeroLevel.NN.Services.KNN
{
public class FPoint
{
public float[] Values { get; set; }
}
public interface IMetric
{
float Calculate(FPoint a, FPoint b);
}
}

@ -35,13 +35,14 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Aurigma.GraphicsMill.Core.x64" Version="10.6.29" />
<PackageReference Include="Aurigma.GraphicsMill.Core.x64" Version="10.6.31" />
<PackageReference Include="Microsoft.ML.OnnxRuntime.Managed" Version="1.12.1" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ZeroLevel.HNSW\ZeroLevel.HNSW.csproj" />
<ProjectReference Include="..\ZeroLevel\ZeroLevel.csproj" />
</ItemGroup>

@ -26,8 +26,8 @@
<ItemGroup>
<PackageReference Include="System.Data.Common" Version="4.3.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.2" />
<PackageReference Include="System.Security.Permissions" Version="4.7.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.3" />
<PackageReference Include="System.Security.Permissions" Version="6.0.0" />
</ItemGroup>
<ItemGroup>

@ -1,177 +0,0 @@
using SQLite;
using System;
using System.Threading;
using ZeroLevel.Services.Serialization;
using ZeroLevel.Services.Shedulling;
namespace ZeroLevel.SqLite
{
public sealed class ExpirationRecord
{
[PrimaryKey, AutoIncrement]
public long Id { get; set; }
[Indexed]
public long Expiration { get; set; }
public byte[] Data { get; set; }
}
public sealed class SqLiteDelayDataStorage<T>
: BaseSqLiteDB<ExpirationRecord>
where T : class, IBinarySerializable, new()
{
#region Fields
private readonly IExpirationSheduller _sheduller;
private readonly Func<T, DateTime> _expire_date_calc_func;
private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
#endregion Fields
#region Ctor
public SqLiteDelayDataStorage(string database_file_path,
Func<T, bool> expire_callback,
Func<T, DateTime> expire_date_calc_func)
: base(database_file_path)
{
this._expire_date_calc_func = expire_date_calc_func;
CreateTable();
_sheduller = Sheduller.CreateExpirationSheduller();
OnExpire += expire_callback;
Preload();
}
#endregion Ctor
#region API
public event Func<T, bool> OnExpire;
public bool Push(T packet)
{
DateTime expirationDate;
try
{
expirationDate = _expire_date_calc_func(packet);
}
catch (Exception ex)
{
Log.Error(ex, "[SqLiteDelayDataStorage] Fault append data to storage");
return false;
}
var expirationTime = expirationDate.Ticks;
_rwLock.EnterWriteLock();
long id = -1;
try
{
var r = Append(new ExpirationRecord { Expiration = expirationTime, Data = MessageSerializer.Serialize(packet) });
id = r.Id;
}
catch (Exception ex)
{
Log.Error(ex, $"[SqLiteDelayDataStorage] Fault insert record in delay storage. Expiration time: '{expirationTime}'.");
return false;
}
finally
{
_rwLock.ExitWriteLock();
}
_sheduller.Push(expirationDate, (k) => Pop(id));
return true;
}
#endregion API
#region Private members
private void Preload()
{
_rwLock.EnterReadLock();
try
{
foreach (var record in SelectAll())
{
_sheduller.Push(new DateTime(record.Expiration, DateTimeKind.Local), (k) => Pop(record.Id));
}
}
catch (Exception ex)
{
Log.Error(ex, "[SqLiteDelayDataStorage] Fault preload datafrom db");
}
finally
{
_rwLock.ExitReadLock();
}
}
private void Pop(long id)
{
try
{
byte[] body;
_rwLock.EnterReadLock();
try
{
body = Single(r=>r.Id == id)?.Data;
}
catch (Exception ex)
{
Log.Error(ex, $"[SqLiteDelayDataStorage] Fault get body by id '{id}'");
RemoveRecordById(id);
return;
}
finally
{
_rwLock.ExitReadLock();
}
T packet;
try
{
packet = MessageSerializer.Deserialize<T>(body);
}
catch (Exception ex)
{
Log.Error(ex, $"[SqLiteDelayDataStorage] Fault deserialize body. Id '{id}'");
RemoveRecordById(id);
return;
}
if (OnExpire?.Invoke(packet) ?? false)
{
RemoveRecordById(id);
}
}
catch (Exception ex)
{
Log.Error(ex, "[SqLiteDelayDataStorage] Сбой обработки отложенной записи из DB");
}
}
private void RemoveRecordById(long id)
{
_rwLock.EnterWriteLock();
try
{
Delete(r => r.Id == id);
}
catch (Exception ex)
{
Log.Error(ex, $"[SqLiteDelayDataStorage] Fault remove record by id '{id}'");
}
finally
{
_rwLock.ExitWriteLock();
}
}
#endregion Private members
#region IDisposable
protected override void DisposeStorageData()
{
_sheduller.Dispose();
}
#endregion IDisposable
}
}

@ -9,9 +9,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

@ -19,10 +19,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZeroLevel.SQL", "ZeroLevel.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZeroLevel.Logger", "ZeroLevel.Logger\ZeroLevel.Logger.csproj", "{D1C061DB-3565-43C3-B8F3-628DE4908750}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZeroLevel.SqLite", "ZeroLevel.SqLite\ZeroLevel.SqLite.csproj", "{5B545DD6-8573-4CDD-B32D-9B0AA2AC2F9A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZeroLevel.EventsServer", "ZeroLevel.EventsServer\ZeroLevel.EventsServer.csproj", "{04219F58-4D3A-4707-82A8-4DDDC9882969}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WPFExamples", "WPFExamples", "{7CCA0125-7A96-48FA-9F0D-BCF7EAD8FF9D}"
ProjectSection(SolutionItems) = preProject
WPFExamples\Controls\AlignableWrapPanel.cs = WPFExamples\Controls\AlignableWrapPanel.cs
@ -67,7 +63,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "ConnectionTest\Cl
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AutoLoader", "AutoLoader", "{2EF83101-63BC-4397-A005-A747189143D4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppContainer", "AutoLoader\AppContainer\AppContainer.csproj", "{9DE345EA-955B-41A8-93AF-277C0B5A9AC5}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppContainer", "AutoLoader\AppContainer\AppContainer.csproj", "{9DE345EA-955B-41A8-93AF-277C0B5A9AC5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -151,30 +147,6 @@ Global
{D1C061DB-3565-43C3-B8F3-628DE4908750}.Release|x64.Build.0 = Release|x64
{D1C061DB-3565-43C3-B8F3-628DE4908750}.Release|x86.ActiveCfg = Release|x86
{D1C061DB-3565-43C3-B8F3-628DE4908750}.Release|x86.Build.0 = Release|x86
{5B545DD6-8573-4CDD-B32D-9B0AA2AC2F9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B545DD6-8573-4CDD-B32D-9B0AA2AC2F9A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B545DD6-8573-4CDD-B32D-9B0AA2AC2F9A}.Debug|x64.ActiveCfg = Debug|x64
{5B545DD6-8573-4CDD-B32D-9B0AA2AC2F9A}.Debug|x64.Build.0 = Debug|x64
{5B545DD6-8573-4CDD-B32D-9B0AA2AC2F9A}.Debug|x86.ActiveCfg = Debug|x86
{5B545DD6-8573-4CDD-B32D-9B0AA2AC2F9A}.Debug|x86.Build.0 = Debug|x86
{5B545DD6-8573-4CDD-B32D-9B0AA2AC2F9A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B545DD6-8573-4CDD-B32D-9B0AA2AC2F9A}.Release|Any CPU.Build.0 = Release|Any CPU
{5B545DD6-8573-4CDD-B32D-9B0AA2AC2F9A}.Release|x64.ActiveCfg = Release|x64
{5B545DD6-8573-4CDD-B32D-9B0AA2AC2F9A}.Release|x64.Build.0 = Release|x64
{5B545DD6-8573-4CDD-B32D-9B0AA2AC2F9A}.Release|x86.ActiveCfg = Release|x86
{5B545DD6-8573-4CDD-B32D-9B0AA2AC2F9A}.Release|x86.Build.0 = Release|x86
{04219F58-4D3A-4707-82A8-4DDDC9882969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{04219F58-4D3A-4707-82A8-4DDDC9882969}.Debug|Any CPU.Build.0 = Debug|Any CPU
{04219F58-4D3A-4707-82A8-4DDDC9882969}.Debug|x64.ActiveCfg = Debug|x64
{04219F58-4D3A-4707-82A8-4DDDC9882969}.Debug|x64.Build.0 = Debug|x64
{04219F58-4D3A-4707-82A8-4DDDC9882969}.Debug|x86.ActiveCfg = Debug|x86
{04219F58-4D3A-4707-82A8-4DDDC9882969}.Debug|x86.Build.0 = Debug|x86
{04219F58-4D3A-4707-82A8-4DDDC9882969}.Release|Any CPU.ActiveCfg = Release|Any CPU
{04219F58-4D3A-4707-82A8-4DDDC9882969}.Release|Any CPU.Build.0 = Release|Any CPU
{04219F58-4D3A-4707-82A8-4DDDC9882969}.Release|x64.ActiveCfg = Release|x64
{04219F58-4D3A-4707-82A8-4DDDC9882969}.Release|x64.Build.0 = Release|x64
{04219F58-4D3A-4707-82A8-4DDDC9882969}.Release|x86.ActiveCfg = Release|x86
{04219F58-4D3A-4707-82A8-4DDDC9882969}.Release|x86.Build.0 = Release|x86
{3496A688-0749-48C2-BD60-ABB42A5C17C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3496A688-0749-48C2-BD60-ABB42A5C17C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3496A688-0749-48C2-BD60-ABB42A5C17C9}.Debug|x64.ActiveCfg = Debug|x64

@ -4,13 +4,32 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Reflection;
using ZeroLevel.Services.Collections;
using ZeroLevel.Services.Invokation;
using ZeroLevel.Services.ObjectMapping;
using ZeroLevel.Services.Reflection;
using ZeroLevel.Services.Serialization;
namespace ZeroLevel.Services.Config
{
public interface IConfigRecordParser
{
object Parse(string line);
}
public class ConfigRecordParseAttribute
: Attribute
{
public IConfigRecordParser Parser { get; set; }
public ConfigRecordParseAttribute(Type parserType)
{
if (parserType == null) throw new ArgumentNullException(nameof(parserType));
Parser = (IConfigRecordParser)Activator.CreateInstance(parserType);
}
}
/// <summary>
/// Base configuration
/// </summary>
@ -477,119 +496,106 @@ namespace ZeroLevel.Services.Config
var instance = TypeHelpers.CreateInitialState(type);
mapper.TraversalMembers(member =>
{
if (Contains(member.Name))
int count = Count(member.Name);
if (count > 0)
{
int count = Count(member.Name);
switch (count)
var values = this.Items(member.Name);
IConfigRecordParser parser = member.Original.GetCustomAttribute<ConfigRecordParseAttribute>()?.Parser;
if (TypeHelpers.IsArray(member.ClrType) && member.ClrType.GetArrayRank() == 1)
{
int index = 0;
var itemType = member.ClrType.GetElementType();
if (parser == null)
{
var elements = values.SelectMany(v => SplitRange(v, itemType)).ToArray();
var arrayBuilder = CollectionFactory.CreateArray(itemType, elements.Length);
foreach (var item in elements)
{
arrayBuilder.Set(item, index);
index++;
}
member.Setter(instance, arrayBuilder.Complete());
}
else
{
var elements = values.Select(v => parser.Parse(v)).ToArray();
var arrayBuilder = CollectionFactory.CreateArray(itemType, elements.Length);
foreach (var item in elements)
{
arrayBuilder.Set(item, index);
index++;
}
member.Setter(instance, arrayBuilder.Complete());
}
}
else if (TypeHelpers.IsEnumerable(member.ClrType) && member.ClrType != typeof(string))
{
case 0: return;
case 1: // field
if (TypeHelpers.IsArray(member.ClrType)
&& member.ClrType.GetArrayRank() == 1)
var itemType = member.ClrType.GenericTypeArguments.First();
var collectionBuilder = CollectionFactory.Create(itemType);
if (parser == null)
{
var elements = values.SelectMany(v => SplitRange(v, itemType)).ToArray();
foreach (var item in elements)
{
var itemType = member.ClrType.GetElementType();
var elements = SplitRange(First(member.Name), itemType).ToArray();
var arrayBuilder = CollectionFactory.CreateArray(itemType, elements.Length);
int index = 0;
foreach (var item in elements)
{
arrayBuilder.Set(item, index);
index++;
}
member.Setter(instance, arrayBuilder.Complete());
collectionBuilder.Append(item);
}
else if (TypeHelpers.IsEnumerable(member.ClrType) && member.ClrType != typeof(string))
}
else
{
var elements = values.Select(v => parser.Parse(v)).ToArray();
foreach (var item in elements)
{
var itemType = member.ClrType.GenericTypeArguments.First();
var collectionBuilder = CollectionFactory.Create(itemType);
foreach (var item in SplitRange(First(member.Name), itemType))
{
collectionBuilder.Append(item);
}
member.Setter(instance, collectionBuilder.Complete());
collectionBuilder.Append(item);
}
else if (TypeHelpers.IsEnum(member.ClrType))
}
member.Setter(instance, collectionBuilder.Complete());
}
else
{
var single = values.First();
if (parser != null)
{
member.Setter(instance, parser.Parse(single));
}
else
{
if (TypeHelpers.IsEnum(member.ClrType))
{
var value = Enum.Parse(member.ClrType, First(member.Name));
var value = Enum.Parse(member.ClrType, single);
member.Setter(instance, value);
}
else if (TypeHelpers.IsUri(member.ClrType))
{
var uri = new Uri(First(member.Name));
var uri = new Uri(single);
member.Setter(instance, uri);
}
else if (TypeHelpers.IsIpEndPoint(member.ClrType))
{
var ep = ZeroLevel.Network.NetUtils.CreateIPEndPoint(First(member.Name));
var ep = ZeroLevel.Network.NetUtils.CreateIPEndPoint(single);
member.Setter(instance, ep);
}
else if (member.ClrType == typeof(IPAddress))
{
var ip = IPAddress.Parse(First(member.Name));
var ip = IPAddress.Parse(single);
member.Setter(instance, ip);
}
else
{
var item = First(member.Name);
var itemType = member.ClrType;
member.Setter(instance, StringToTypeConverter.TryConvert(item, itemType));
}
break;
default: // array, or first
if (TypeHelpers.IsArray(member.ClrType)
&& member.ClrType.GetArrayRank() == 1)
{
//throw new NotSupportedException("Multidimensions array not supported");
var itemType = member.ClrType.GetElementType();
if (itemType == typeof(string))
{
var array = Items(member.Name).ToArray();
member.Setter(instance, array);
}
else
{
var arrayBuilder = CollectionFactory.CreateArray(itemType, count);
int index = 0;
foreach (var item in Items(member.Name))
{
arrayBuilder.Set(StringToTypeConverter.TryConvert(item, itemType), index);
index++;
}
member.Setter(instance, arrayBuilder.Complete());
}
}
else if (typeof(string) != member.ClrType && TypeHelpers.IsEnumerable(member.ClrType))
{
var itemType = member.ClrType.GenericTypeArguments.First();
if (itemType == typeof(string))
{
member.Setter(instance, Items(member.Name));
}
else
{
var collectionBuilder = CollectionFactory.Create(itemType);
foreach (var item in Items(member.Name))
{
collectionBuilder.Append(StringToTypeConverter.TryConvert(item, itemType));
}
member.Setter(instance, collectionBuilder.Complete());
}
}
else
{
var item = First(member.Name);
var itemType = member.ClrType;
member.Setter(instance, StringToTypeConverter.TryConvert(item, itemType));
member.Setter(instance, StringToTypeConverter.TryConvert(single, itemType));
}
break;
}
}
}
});
return instance;
}
private static IEnumerable<object> SplitRange(string line, Type elementType)
{
if (string.IsNullOrWhiteSpace(line)) yield return StringToTypeConverter.TryConvert(line, elementType);
if (string.IsNullOrWhiteSpace(line))
yield return StringToTypeConverter.TryConvert(line, elementType);
foreach (var part in line.Split(','))
{
if (TypeHelpers.IsNumericType(elementType) && part.IndexOf('-') >= 0)
@ -597,6 +603,7 @@ namespace ZeroLevel.Services.Config
var lr = part.Split('-');
if (lr.Length == 2)
{
// not use parser with range
long left = (long)Convert.ChangeType(StringToTypeConverter.TryConvert(lr[0], elementType), typeof(long));
long right = (long)Convert.ChangeType(StringToTypeConverter.TryConvert(lr[1], elementType), typeof(long));
for (; left <= right; left++)

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Reflection.PortableExecutable;
namespace ZeroLevel.Services
{

@ -6,16 +6,17 @@
</Description>
<Authors>ogoun</Authors>
<Company>ogoun</Company>
<AssemblyVersion>3.3.6.5</AssemblyVersion>
<PackageReleaseNotes>Configuration floating number convert fix</PackageReleaseNotes>
<AssemblyVersion>3.3.6.6</AssemblyVersion>
<PackageReleaseNotes>Configuration binding refactoring.
Append custom parsing attribute.</PackageReleaseNotes>
<PackageProjectUrl>https://github.com/ogoun/Zero/wiki</PackageProjectUrl>
<Copyright>Copyright Ogoun 2022</Copyright>
<PackageLicenseUrl></PackageLicenseUrl>
<PackageIconUrl></PackageIconUrl>
<RepositoryUrl>https://github.com/ogoun/Zero</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Version>3.3.6.5</Version>
<FileVersion>3.3.6.5</FileVersion>
<Version>3.3.6.6</Version>
<FileVersion>3.3.6.6</FileVersion>
<Platforms>AnyCPU;x64;x86</Platforms>
<PackageIcon>zero.png</PackageIcon>
<DebugType>full</DebugType>

Loading…
Cancel
Save

Powered by TurnKey Linux.