diff --git a/TestApp/TestApp.csproj b/TestApp/TestApp.csproj index 480e7bd..e6e53e0 100644 --- a/TestApp/TestApp.csproj +++ b/TestApp/TestApp.csproj @@ -7,7 +7,7 @@ - + diff --git a/ZeroLevel.Discovery/ZeroLevel.Discovery.csproj b/ZeroLevel.Discovery/ZeroLevel.Discovery.csproj index 606f9d4..22f73b8 100644 --- a/ZeroLevel.Discovery/ZeroLevel.Discovery.csproj +++ b/ZeroLevel.Discovery/ZeroLevel.Discovery.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/ZeroLevel.EventsServer/ZeroLevel.EventsServer.csproj b/ZeroLevel.EventsServer/ZeroLevel.EventsServer.csproj index 03cb9e8..c1cb915 100644 --- a/ZeroLevel.EventsServer/ZeroLevel.EventsServer.csproj +++ b/ZeroLevel.EventsServer/ZeroLevel.EventsServer.csproj @@ -6,7 +6,6 @@ - diff --git a/ZeroLevel.NN/Services/KNN/Point.cs b/ZeroLevel.NN/Services/KNN/Point.cs new file mode 100644 index 0000000..fb37d3c --- /dev/null +++ b/ZeroLevel.NN/Services/KNN/Point.cs @@ -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); + } +} diff --git a/ZeroLevel.NN/ZeroLevel.NN.csproj b/ZeroLevel.NN/ZeroLevel.NN.csproj index e081781..dc33965 100644 --- a/ZeroLevel.NN/ZeroLevel.NN.csproj +++ b/ZeroLevel.NN/ZeroLevel.NN.csproj @@ -35,13 +35,14 @@ - + + diff --git a/ZeroLevel.SQL/ZeroLevel.SQL.csproj b/ZeroLevel.SQL/ZeroLevel.SQL.csproj index b46f68d..82e1d8d 100644 --- a/ZeroLevel.SQL/ZeroLevel.SQL.csproj +++ b/ZeroLevel.SQL/ZeroLevel.SQL.csproj @@ -26,8 +26,8 @@ - - + + diff --git a/ZeroLevel.SqLite/SqLiteDelayDataStorage.cs b/ZeroLevel.SqLite/SqLiteDelayDataStorage.cs deleted file mode 100644 index 301b7f6..0000000 --- a/ZeroLevel.SqLite/SqLiteDelayDataStorage.cs +++ /dev/null @@ -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 - : BaseSqLiteDB - where T : class, IBinarySerializable, new() - { - #region Fields - - private readonly IExpirationSheduller _sheduller; - private readonly Func _expire_date_calc_func; - private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim(); - - #endregion Fields - - #region Ctor - - public SqLiteDelayDataStorage(string database_file_path, - Func expire_callback, - Func 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 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(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 - } -} diff --git a/ZeroLevel.UnitTests/ZeroLevel.UnitTests.csproj b/ZeroLevel.UnitTests/ZeroLevel.UnitTests.csproj index b4447bf..bbd442c 100644 --- a/ZeroLevel.UnitTests/ZeroLevel.UnitTests.csproj +++ b/ZeroLevel.UnitTests/ZeroLevel.UnitTests.csproj @@ -9,9 +9,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ZeroLevel.sln b/ZeroLevel.sln index 229af50..837e078 100644 --- a/ZeroLevel.sln +++ b/ZeroLevel.sln @@ -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 diff --git a/ZeroLevel/Services/Config/BaseConfiguration.cs b/ZeroLevel/Services/Config/BaseConfiguration.cs index e7bd8f8..3f4a5f3 100644 --- a/ZeroLevel/Services/Config/BaseConfiguration.cs +++ b/ZeroLevel/Services/Config/BaseConfiguration.cs @@ -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); + } + } + /// /// Base configuration /// @@ -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()?.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 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++) diff --git a/ZeroLevel/Services/IL.cs b/ZeroLevel/Services/IL.cs index 72abce3..c3c5832 100644 --- a/ZeroLevel/Services/IL.cs +++ b/ZeroLevel/Services/IL.cs @@ -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 { diff --git a/ZeroLevel/ZeroLevel.csproj b/ZeroLevel/ZeroLevel.csproj index dc078ba..de209f9 100644 --- a/ZeroLevel/ZeroLevel.csproj +++ b/ZeroLevel/ZeroLevel.csproj @@ -6,16 +6,17 @@ ogoun ogoun - 3.3.6.5 - Configuration floating number convert fix + 3.3.6.6 + Configuration binding refactoring. +Append custom parsing attribute. https://github.com/ogoun/Zero/wiki Copyright Ogoun 2022 https://github.com/ogoun/Zero git - 3.3.6.5 - 3.3.6.5 + 3.3.6.6 + 3.3.6.6 AnyCPU;x64;x86 zero.png full