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> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

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

@ -6,7 +6,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ZeroLevel.SqLite\ZeroLevel.SqLite.csproj" />
<ProjectReference Include="..\ZeroLevel\ZeroLevel.csproj" /> <ProjectReference Include="..\ZeroLevel\ZeroLevel.csproj" />
</ItemGroup> </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>
<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="Microsoft.ML.OnnxRuntime.Managed" Version="1.12.1" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" /> <PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ZeroLevel.HNSW\ZeroLevel.HNSW.csproj" />
<ProjectReference Include="..\ZeroLevel\ZeroLevel.csproj" /> <ProjectReference Include="..\ZeroLevel\ZeroLevel.csproj" />
</ItemGroup> </ItemGroup>

@ -26,8 +26,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Data.Common" Version="4.3.0" /> <PackageReference Include="System.Data.Common" Version="4.3.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.2" /> <PackageReference Include="System.Data.SqlClient" Version="4.8.3" />
<PackageReference Include="System.Security.Permissions" Version="4.7.0" /> <PackageReference Include="System.Security.Permissions" Version="6.0.0" />
</ItemGroup> </ItemGroup>
<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> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>

@ -19,10 +19,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZeroLevel.SQL", "ZeroLevel.
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZeroLevel.Logger", "ZeroLevel.Logger\ZeroLevel.Logger.csproj", "{D1C061DB-3565-43C3-B8F3-628DE4908750}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZeroLevel.Logger", "ZeroLevel.Logger\ZeroLevel.Logger.csproj", "{D1C061DB-3565-43C3-B8F3-628DE4908750}"
EndProject 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}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WPFExamples", "WPFExamples", "{7CCA0125-7A96-48FA-9F0D-BCF7EAD8FF9D}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
WPFExamples\Controls\AlignableWrapPanel.cs = WPFExamples\Controls\AlignableWrapPanel.cs WPFExamples\Controls\AlignableWrapPanel.cs = WPFExamples\Controls\AlignableWrapPanel.cs
@ -67,7 +63,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "ConnectionTest\Cl
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AutoLoader", "AutoLoader", "{2EF83101-63BC-4397-A005-A747189143D4}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AutoLoader", "AutoLoader", "{2EF83101-63BC-4397-A005-A747189143D4}"
EndProject 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 EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution 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|x64.Build.0 = Release|x64
{D1C061DB-3565-43C3-B8F3-628DE4908750}.Release|x86.ActiveCfg = Release|x86 {D1C061DB-3565-43C3-B8F3-628DE4908750}.Release|x86.ActiveCfg = Release|x86
{D1C061DB-3565-43C3-B8F3-628DE4908750}.Release|x86.Build.0 = 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.ActiveCfg = Debug|Any CPU
{3496A688-0749-48C2-BD60-ABB42A5C17C9}.Debug|Any CPU.Build.0 = 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 {3496A688-0749-48C2-BD60-ABB42A5C17C9}.Debug|x64.ActiveCfg = Debug|x64

@ -4,13 +4,32 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Reflection;
using ZeroLevel.Services.Collections; using ZeroLevel.Services.Collections;
using ZeroLevel.Services.Invokation;
using ZeroLevel.Services.ObjectMapping; using ZeroLevel.Services.ObjectMapping;
using ZeroLevel.Services.Reflection; using ZeroLevel.Services.Reflection;
using ZeroLevel.Services.Serialization; using ZeroLevel.Services.Serialization;
namespace ZeroLevel.Services.Config 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> /// <summary>
/// Base configuration /// Base configuration
/// </summary> /// </summary>
@ -477,119 +496,106 @@ namespace ZeroLevel.Services.Config
var instance = TypeHelpers.CreateInitialState(type); var instance = TypeHelpers.CreateInitialState(type);
mapper.TraversalMembers(member => mapper.TraversalMembers(member =>
{ {
if (Contains(member.Name)) int count = Count(member.Name);
if (count > 0)
{ {
int count = Count(member.Name); var values = this.Items(member.Name);
switch (count) 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; var itemType = member.ClrType.GenericTypeArguments.First();
case 1: // field var collectionBuilder = CollectionFactory.Create(itemType);
if (TypeHelpers.IsArray(member.ClrType) if (parser == null)
&& member.ClrType.GetArrayRank() == 1) {
var elements = values.SelectMany(v => SplitRange(v, itemType)).ToArray();
foreach (var item in elements)
{ {
var itemType = member.ClrType.GetElementType(); collectionBuilder.Append(item);
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());
} }
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(); collectionBuilder.Append(item);
var collectionBuilder = CollectionFactory.Create(itemType);
foreach (var item in SplitRange(First(member.Name), itemType))
{
collectionBuilder.Append(item);
}
member.Setter(instance, collectionBuilder.Complete());
} }
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); member.Setter(instance, value);
} }
else if (TypeHelpers.IsUri(member.ClrType)) else if (TypeHelpers.IsUri(member.ClrType))
{ {
var uri = new Uri(First(member.Name)); var uri = new Uri(single);
member.Setter(instance, uri); member.Setter(instance, uri);
} }
else if (TypeHelpers.IsIpEndPoint(member.ClrType)) 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); member.Setter(instance, ep);
} }
else if (member.ClrType == typeof(IPAddress)) else if (member.ClrType == typeof(IPAddress))
{ {
var ip = IPAddress.Parse(First(member.Name)); var ip = IPAddress.Parse(single);
member.Setter(instance, ip); member.Setter(instance, ip);
} }
else 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; var itemType = member.ClrType;
member.Setter(instance, StringToTypeConverter.TryConvert(item, itemType)); member.Setter(instance, StringToTypeConverter.TryConvert(single, itemType));
} }
break; }
} }
} }
}); });
return instance; return instance;
} }
private static IEnumerable<object> SplitRange(string line, Type elementType) 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(',')) foreach (var part in line.Split(','))
{ {
if (TypeHelpers.IsNumericType(elementType) && part.IndexOf('-') >= 0) if (TypeHelpers.IsNumericType(elementType) && part.IndexOf('-') >= 0)
@ -597,6 +603,7 @@ namespace ZeroLevel.Services.Config
var lr = part.Split('-'); var lr = part.Split('-');
if (lr.Length == 2) if (lr.Length == 2)
{ {
// not use parser with range
long left = (long)Convert.ChangeType(StringToTypeConverter.TryConvert(lr[0], elementType), typeof(long)); long left = (long)Convert.ChangeType(StringToTypeConverter.TryConvert(lr[0], elementType), typeof(long));
long right = (long)Convert.ChangeType(StringToTypeConverter.TryConvert(lr[1], elementType), typeof(long)); long right = (long)Convert.ChangeType(StringToTypeConverter.TryConvert(lr[1], elementType), typeof(long));
for (; left <= right; left++) for (; left <= right; left++)

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

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

Loading…
Cancel
Save

Powered by TurnKey Linux.