From 4d6a7f5e2712f1335f5a9041701d025a7dbb0bb6 Mon Sep 17 00:00:00 2001 From: Ogoun Date: Tue, 2 Apr 2019 18:43:22 +0300 Subject: [PATCH] start localization --- ZeroExample/App.config | 17 + ZeroExample/Program.cs | 26 ++ ZeroExample/Properties/AssemblyInfo.cs | 36 ++ ZeroExample/ZeroExample.csproj | 62 +++ ZeroExample/packages.config | 4 + ...l.Discovery.csproj.CoreCompileInputs.cache | 2 +- ...el.Discovery.csprojAssemblyReference.cache | Bin 167852 -> 168237 bytes ...croservices.csproj.CoreCompileInputs.cache | 2 +- ...icroservices.csprojAssemblyReference.cache | Bin 79168 -> 78215 bytes ZeroLevel.sln | 14 + ZeroLevel/Models/BaseModel.cs | 2 +- ZeroLevel/Models/BinaryDocument.cs | 16 +- ZeroLevel/Models/InvokeResult.cs | 14 +- .../Application/BaseWindowsService.cs | 8 +- .../Application/BusinessApplication.cs | 21 +- .../Services/Application/ZeroServiceState.cs | 9 - .../Services/Collections/FixSizeQueue.cs | 6 +- .../Collections/RoundRobinCollection.cs | 5 + .../Services/Collections/SparseIterator.cs | 82 ---- .../Services/Config/BaseConfiguration.cs | 42 ++- .../Services/Config/BaseConfigurationSet.cs | 4 +- ZeroLevel/Services/Config/Configuration.cs | 2 +- ZeroLevel/Services/Config/IConfiguration.cs | 54 ++- .../Services/Config/IConfigurationSet.cs | 42 +-- .../Implementation/CommandLineReader.cs | 2 +- .../Config/Implementation/IniFileReader.cs | 4 +- .../Config/Implementation/IniFileWriter.cs | 15 +- .../Services/DOM/Contracts/IMetadataReader.cs | 8 +- .../DOM/DSL/Contracts/ISpecialTableBuilder.cs | 2 +- .../Services/DOM/DSL/Model/TFlowRules.cs | 4 +- .../Services/SpecialTableBuilderFactory.cs | 8 +- .../Services/DOM/DSL/Services/TContainer.cs | 17 +- .../Services/DOM/DSL/Services/TRender.cs | 170 ++++----- ZeroLevel/Services/DOM/DSL/TEngine.cs | 4 +- .../Services/DOM/DSL/Tokens/TElementToken.cs | 4 +- .../Services/DOM/DSL/Tokens/TTextToken.cs | 4 +- ZeroLevel/Services/DOM/DSL/Tokens/TToken.cs | 4 +- ZeroLevel/Services/DOM/Model/Agency.cs | 6 +- ZeroLevel/Services/DOM/Model/Assotiation.cs | 8 +- .../Services/DOM/Model/AssotiationRelation.cs | 10 +- .../{AsideContent.cs => AttachContent.cs} | 18 +- ZeroLevel/Services/DOM/Model/Category.cs | 11 +- .../Services/DOM/Model/DescriptiveMetadata.cs | 18 +- ZeroLevel/Services/DOM/Model/Document.cs | 28 +- ZeroLevel/Services/DOM/Model/Flow/Audio.cs | 4 +- .../Services/DOM/Model/Flow/FlowAlign.cs | 10 +- .../Services/DOM/Model/Flow/FormContent.cs | 2 +- ZeroLevel/Services/DOM/Model/Flow/Image.cs | 4 +- .../Services/DOM/Model/Flow/Paragraph.cs | 2 +- ZeroLevel/Services/DOM/Model/Flow/Section.cs | 2 +- ZeroLevel/Services/DOM/Model/Flow/Video.cs | 4 +- ZeroLevel/Services/DOM/Model/FlowContent.cs | 3 - ZeroLevel/Services/DOM/Model/Header.cs | 12 - ZeroLevel/Services/DOM/Model/Identifier.cs | 14 +- ZeroLevel/Services/DOM/Model/Priority.cs | 12 +- ZeroLevel/Services/DOM/Model/Tag.cs | 6 - ZeroLevel/Services/DOM/Model/TagMetadata.cs | 9 +- .../Services/DOM/Services/ContentBuilder.cs | 16 +- .../DOM/Services/DocumentContentReader.cs | 8 +- .../Services/DependencyInjection/Container.cs | 126 ++++--- .../Contracts/ICompositionProvider.cs | 12 +- .../Contracts/IContainerInstanceRegister.cs | 32 +- .../Contracts/IContainerRegister.cs | 356 +++++++++--------- .../Contracts/IParameterStorage.cs | 64 ++-- .../Contracts/IPoolContainer.cs | 91 ----- .../Contracts/IResolver.cs | 118 +++--- .../Internal/ConstructorMetadata.cs | 18 +- .../Internal/ConstructorParameter.cs | 22 +- .../DependencyInjection/Internal/IPoolable.cs | 9 - .../Internal/ResolveTypeInfo.cs | 18 +- ZeroLevel/Services/Drawing/TextPainter.cs | 2 +- .../Services/Extensions/ArrayExtensions.cs | 6 +- .../CollectionComparsionExtensions.cs | 8 +- .../Services/Extensions/DateTimeExtensions.cs | 6 +- ZeroLevel/Services/Extensions/FPCommon.cs | 2 +- ZeroLevel/Services/Extensions/Monades.cs | 3 - ZeroLevel/Services/FileSystem/FSUtils.cs | 16 +- ZeroLevel/Services/FileSystem/FileArchive.cs | 59 ++- .../FileSystem/PeriodicFileSystemWatcher.cs | 13 +- .../Impersonation/IImpersonationExecutor.cs | 2 +- .../Services/Impersonation/Impersonation.cs | 30 +- .../ImpersonationNativeMethods.cs | 34 +- .../Impersonation/MySafeTokenHandle.cs | 2 +- .../ProcessImpersonationExecutor.cs | 15 +- .../UserImpersonationExecutor.cs | 11 +- .../Services/Invokation/InvokeWrapper.cs | 96 ++--- ZeroLevel/Services/Invokation/Invoker.cs | 8 +- ZeroLevel/Services/Logging/ILog.cs | 18 +- .../Services/Logging/ILogMessageBuffer.cs | 11 +- .../Implementation/EncryptedFileLog.cs | 15 +- .../Logging/Implementation/TextFileLogger.cs | 57 ++- ZeroLevel/Services/Logging/Log.cs | 40 +- ZeroLevel/Services/Logging/LogLevel.cs | 27 +- .../Services/Logging/LogLevelNameMapping.cs | 6 +- .../Trees/ItemFieldToTreeConverter.cs | 304 --------------- ZeroLevel/ZeroLevel.csproj | 6 +- .../ZeroLevel.csproj.CoreCompileInputs.cache | 2 +- .../ZeroLevel.csprojAssemblyReference.cache | Bin 12917 -> 20909 bytes 98 files changed, 1061 insertions(+), 1527 deletions(-) create mode 100644 ZeroExample/App.config create mode 100644 ZeroExample/Program.cs create mode 100644 ZeroExample/Properties/AssemblyInfo.cs create mode 100644 ZeroExample/ZeroExample.csproj create mode 100644 ZeroExample/packages.config delete mode 100644 ZeroLevel/Services/Collections/SparseIterator.cs rename ZeroLevel/Services/DOM/Model/{AsideContent.cs => AttachContent.cs} (72%) delete mode 100644 ZeroLevel/Services/DependencyInjection/Contracts/IPoolContainer.cs delete mode 100644 ZeroLevel/Services/DependencyInjection/Internal/IPoolable.cs delete mode 100644 ZeroLevel/Services/Trees/ItemFieldToTreeConverter.cs diff --git a/ZeroExample/App.config b/ZeroExample/App.config new file mode 100644 index 0000000..f0a74bb --- /dev/null +++ b/ZeroExample/App.config @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ZeroExample/Program.cs b/ZeroExample/Program.cs new file mode 100644 index 0000000..a846279 --- /dev/null +++ b/ZeroExample/Program.cs @@ -0,0 +1,26 @@ +using ZeroLevel; +using ZeroLevel.Services.Applications; + +namespace ZeroExample +{ + public sealed class MyFirstApp + : BaseWindowsService, IZeroService + { + public MyFirstApp() : base("MyApp") { Log.AddConsoleLogger(); } + public override void PauseAction() { } + public override void ResumeAction() { } + public override void StartAction() + { + Log.Info("Started"); + } + public override void StopAction() { } + } + + class Program + { + static void Main(string[] args) + { + Bootstrap.Startup(args); + } + } +} diff --git a/ZeroExample/Properties/AssemblyInfo.cs b/ZeroExample/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a825422 --- /dev/null +++ b/ZeroExample/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ZeroExample")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ZeroExample")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("50cebec2-2571-4592-afd2-970bdb41947b")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ZeroExample/ZeroExample.csproj b/ZeroExample/ZeroExample.csproj new file mode 100644 index 0000000..4734f4b --- /dev/null +++ b/ZeroExample/ZeroExample.csproj @@ -0,0 +1,62 @@ + + + + + Debug + AnyCPU + {50CEBEC2-2571-4592-AFD2-970BDB41947B} + Exe + ZeroExample + ZeroExample + v4.7.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + ..\packages\ZeroLevel.1.0.3\lib\net47\ZeroLevel.dll + + + + + Component + + + + + + Designer + + + + + \ No newline at end of file diff --git a/ZeroExample/packages.config b/ZeroExample/packages.config new file mode 100644 index 0000000..c024b44 --- /dev/null +++ b/ZeroExample/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csproj.CoreCompileInputs.cache b/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csproj.CoreCompileInputs.cache index 7a6e9ee..ffd6fd9 100644 --- a/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csproj.CoreCompileInputs.cache +++ b/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -02ab5562f7a9f633d41e073aff759527ff59696c +4f0bbfe8ac44b56784f7eeaa3cdef96609d6b97e diff --git a/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csprojAssemblyReference.cache b/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csprojAssemblyReference.cache index 86a36f8fd3758d056a732c4e81d1a6baa42fee80..9b98d2082451f5fef5531a34b6133ee8242d1db2 100644 GIT binary patch literal 168237 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 literal 167852 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 gsN4GSb%*Y?B#m6J*$~=CIv_ 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 X5cw%!e?*`FyB!n(gB3TYaO?QLnyo;6 diff --git a/ZeroLevel.sln b/ZeroLevel.sln index c2f94eb..aef504b 100644 --- a/ZeroLevel.sln +++ b/ZeroLevel.sln @@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroLevel.Microservices", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroLevel.Discovery", "ZeroLevel.Discovery\ZeroLevel.Discovery.csproj", "{4F55B23F-938C-4DA2-B6DC-B6BC66D36073}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroExample", "ZeroExample\ZeroExample.csproj", "{50CEBEC2-2571-4592-AFD2-970BDB41947B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -55,6 +57,18 @@ Global {4F55B23F-938C-4DA2-B6DC-B6BC66D36073}.Release|x64.Build.0 = Release|Any CPU {4F55B23F-938C-4DA2-B6DC-B6BC66D36073}.Release|x86.ActiveCfg = Release|Any CPU {4F55B23F-938C-4DA2-B6DC-B6BC66D36073}.Release|x86.Build.0 = Release|Any CPU + {50CEBEC2-2571-4592-AFD2-970BDB41947B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {50CEBEC2-2571-4592-AFD2-970BDB41947B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50CEBEC2-2571-4592-AFD2-970BDB41947B}.Debug|x64.ActiveCfg = Debug|Any CPU + {50CEBEC2-2571-4592-AFD2-970BDB41947B}.Debug|x64.Build.0 = Debug|Any CPU + {50CEBEC2-2571-4592-AFD2-970BDB41947B}.Debug|x86.ActiveCfg = Debug|Any CPU + {50CEBEC2-2571-4592-AFD2-970BDB41947B}.Debug|x86.Build.0 = Debug|Any CPU + {50CEBEC2-2571-4592-AFD2-970BDB41947B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {50CEBEC2-2571-4592-AFD2-970BDB41947B}.Release|Any CPU.Build.0 = Release|Any CPU + {50CEBEC2-2571-4592-AFD2-970BDB41947B}.Release|x64.ActiveCfg = Release|Any CPU + {50CEBEC2-2571-4592-AFD2-970BDB41947B}.Release|x64.Build.0 = Release|Any CPU + {50CEBEC2-2571-4592-AFD2-970BDB41947B}.Release|x86.ActiveCfg = Release|Any CPU + {50CEBEC2-2571-4592-AFD2-970BDB41947B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ZeroLevel/Models/BaseModel.cs b/ZeroLevel/Models/BaseModel.cs index f2c8c2e..41591e7 100644 --- a/ZeroLevel/Models/BaseModel.cs +++ b/ZeroLevel/Models/BaseModel.cs @@ -10,7 +10,7 @@ namespace ZeroLevel.Models #region Equal public bool Equals(BaseModel other) { - if (this == null) // и так бывает + if (this == null) throw new NullReferenceException(); if (other == null) return false; diff --git a/ZeroLevel/Models/BinaryDocument.cs b/ZeroLevel/Models/BinaryDocument.cs index ae76f40..e4687b7 100644 --- a/ZeroLevel/Models/BinaryDocument.cs +++ b/ZeroLevel/Models/BinaryDocument.cs @@ -6,7 +6,7 @@ using ZeroLevel.Services.Serialization; namespace ZeroLevel.Models { ///

- /// Документ в бинарном представлении + /// Binary data represantation /// public class BinaryDocument : IBinarySerializable, @@ -14,31 +14,31 @@ namespace ZeroLevel.Models ICloneable { /// - /// Идентификатор + /// Id /// public Guid Id { get; set; } /// - /// Имя файла + /// File name /// public string FileName { get; set; } /// - /// Тип содержимого (pdf, doc и т.п.) + /// Content type (pdf, doc, etc.) /// public string ContentType { get; set; } /// - /// Содержимое + /// Content /// public byte[] Document { get; set; } /// - /// Дата создания + /// Creation date /// public DateTime Created { get; set; } /// - /// Опциональные заголовки + /// Optional headers /// public List
Headers { get; set; } /// - /// Категории + /// Categories /// public List Categories { get; set; } diff --git a/ZeroLevel/Models/InvokeResult.cs b/ZeroLevel/Models/InvokeResult.cs index 2ec5753..d66280a 100644 --- a/ZeroLevel/Models/InvokeResult.cs +++ b/ZeroLevel/Models/InvokeResult.cs @@ -5,7 +5,7 @@ using ZeroLevel.Services.Serialization; namespace ZeroLevel.Models { /// - /// Результат выполнения действий + /// Action result /// [DataContract] public class InvokeResult : @@ -29,12 +29,12 @@ namespace ZeroLevel.Models #region Properties /// - /// Успех выполнения операции + /// true when action successfully invoked /// [DataMember] public bool Success; /// - /// Комментарий (сообщение об ошибке при сбое, или доп. информация) + /// Comment /// [DataMember] public string Comment; @@ -42,15 +42,15 @@ namespace ZeroLevel.Models #region Fabric methods /// - /// Сбой при выполнении плана действий + /// Error when action invoking /// public static InvokeResult Fault(string comment) { return new InvokeResult(false, comment); } /// - /// Успешное выполнение + /// Successfully /// public static InvokeResult Succeeding(string comment = "") { return new InvokeResult(true, comment); } /// - /// Успешное выполнение + /// Successfully /// public static InvokeResult Succeeding() { return _successResultWitoutComment; } #endregion @@ -91,7 +91,7 @@ namespace ZeroLevel.Models #region Fabric methods public static InvokeResult Succeeding(T value, string comment = "") { return new InvokeResult(value, true, comment); } - public static InvokeResult Fault(string comment) { return new InvokeResult(false, comment); } + public static InvokeResult Fault(string comment) { return new InvokeResult(false, comment); } #endregion public override void Serialize(IBinaryWriter writer) diff --git a/ZeroLevel/Services/Application/BaseWindowsService.cs b/ZeroLevel/Services/Application/BaseWindowsService.cs index ffbd7dd..27859c5 100644 --- a/ZeroLevel/Services/Application/BaseWindowsService.cs +++ b/ZeroLevel/Services/Application/BaseWindowsService.cs @@ -54,7 +54,7 @@ namespace ZeroLevel.Services.Applications } catch (Exception ex) { - Log.SystemFatal(ex, $"[{Name}] Failed to start service"); + Log.Fatal(ex, $"[{Name}] Failed to start service"); Stop(); } } @@ -72,7 +72,7 @@ namespace ZeroLevel.Services.Applications } catch (Exception ex) { - Log.SystemFatal(ex, $"[{Name}] Failed to pause service"); + Log.Fatal(ex, $"[{Name}] Failed to pause service"); Stop(); } } @@ -90,7 +90,7 @@ namespace ZeroLevel.Services.Applications } catch (Exception ex) { - Log.SystemFatal(ex, $"[{Name}] Failed to continue work service after pause"); + Log.Fatal(ex, $"[{Name}] Failed to continue work service after pause"); Stop(); } } @@ -108,7 +108,7 @@ namespace ZeroLevel.Services.Applications } catch (Exception ex) { - Log.SystemFatal(ex, $"[{Name}] Failed to stop service"); + Log.Fatal(ex, $"[{Name}] Failed to stop service"); } finally { diff --git a/ZeroLevel/Services/Application/BusinessApplication.cs b/ZeroLevel/Services/Application/BusinessApplication.cs index 899fff6..55cea17 100644 --- a/ZeroLevel/Services/Application/BusinessApplication.cs +++ b/ZeroLevel/Services/Application/BusinessApplication.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Linq; using System.Reflection; using System.ServiceProcess; using ZeroLevel.Services.Applications; @@ -10,7 +11,7 @@ namespace ZeroLevel { static Bootstrap() { - // Хак, чтобы не переписывать runtime секцию конфига при каждом обновлении Newtonsoft пакета + // Tricks for minimize config changes for dependency resolve AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; } @@ -27,6 +28,11 @@ namespace ZeroLevel { return Assembly.LoadFile(Path.Combine(Configuration.BaseDirectory, "Microsoft.Owin.dll")); } + var candidates = Directory.GetFiles(Path.Combine(Configuration.BaseDirectory), args.Name, SearchOption.TopDirectoryOnly); + if (candidates != null && candidates.Any()) + { + return Assembly.LoadFile(candidates.First()); + } } catch (Exception ex) { @@ -36,7 +42,7 @@ namespace ZeroLevel } /// - /// Установка приложения в качестве службы + /// Self-install as windows service /// private static void InstallApplication() { @@ -48,11 +54,11 @@ namespace ZeroLevel } catch (Exception ex) { - Log.SystemFatal(ex, "[Bootstrap] Fault service install"); + Log.Fatal(ex, "[Bootstrap] Fault service install"); } } /// - /// Удаление приложения из служб + /// Uninstall from windows services /// private static void UninstallApplication() { @@ -64,7 +70,7 @@ namespace ZeroLevel } catch (Exception ex) { - Log.SystemFatal(ex, "[Bootstrap] Fault service uninstall"); + Log.Fatal(ex, "[Bootstrap] Fault service uninstall"); } } @@ -125,7 +131,6 @@ namespace ZeroLevel return; } } - // Исключения в процессе работы приложения перехыватываются уровнем ниже if (Environment.UserInteractive) { try @@ -136,7 +141,7 @@ namespace ZeroLevel } catch (Exception ex) { - Log.SystemFatal(ex, "[Bootstrap] The service start in interactive mode was faulted with error"); + Log.Fatal(ex, "[Bootstrap] The service start in interactive mode was faulted with error"); } } else @@ -149,7 +154,7 @@ namespace ZeroLevel } catch (Exception ex) { - Log.SystemFatal(ex, "[Bootstrap] The service start was faulted with error"); + Log.Fatal(ex, "[Bootstrap] The service start was faulted with error"); } } } diff --git a/ZeroLevel/Services/Application/ZeroServiceState.cs b/ZeroLevel/Services/Application/ZeroServiceState.cs index 317757c..7281199 100644 --- a/ZeroLevel/Services/Application/ZeroServiceState.cs +++ b/ZeroLevel/Services/Application/ZeroServiceState.cs @@ -6,17 +6,8 @@ namespace ZeroLevel.Services.Applications public enum ZeroServiceState : int { Initialized = 0, - /// - /// Сервис работает - /// Started = 1, - /// - /// Работа сервиса приостановлена - /// Paused = 2, - /// - /// Сервис остановлен (ресурсы освобождены) - /// Stopped = 3 } } diff --git a/ZeroLevel/Services/Collections/FixSizeQueue.cs b/ZeroLevel/Services/Collections/FixSizeQueue.cs index 568946c..013814e 100644 --- a/ZeroLevel/Services/Collections/FixSizeQueue.cs +++ b/ZeroLevel/Services/Collections/FixSizeQueue.cs @@ -3,9 +3,6 @@ using System.Collections.Generic; namespace ZeroLevel.Services.Collections { - /// - /// Очередь фиксированной длины - /// public sealed class FixSizeQueue : IFixSizeQueue { @@ -26,8 +23,7 @@ namespace ZeroLevel.Services.Collections _count = 0; } /// - /// Добавление элемента в очередь, при достижении предела по размеру, - /// перезаписывается самый старый элемент + /// If count is limited when intem adding, oldest item replace with new item /// public void Push(T item) { diff --git a/ZeroLevel/Services/Collections/RoundRobinCollection.cs b/ZeroLevel/Services/Collections/RoundRobinCollection.cs index b51ac57..457236e 100644 --- a/ZeroLevel/Services/Collections/RoundRobinCollection.cs +++ b/ZeroLevel/Services/Collections/RoundRobinCollection.cs @@ -5,6 +5,11 @@ using System.Threading; namespace ZeroLevel.Services.Collections { + /// + /// Collection return new seq every iteration + /// Sample. Original: [1,2,3]. Iteration #1: [1, 2, 3]. Iteration #2: [2, 3, 1]. Iteration #3: [3, 1, 2]. Iteration #4: [1, 2, 3] + /// + /// public sealed class RoundRobinCollection : IDisposable { diff --git a/ZeroLevel/Services/Collections/SparseIterator.cs b/ZeroLevel/Services/Collections/SparseIterator.cs deleted file mode 100644 index b723d41..0000000 --- a/ZeroLevel/Services/Collections/SparseIterator.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace ZeroLevel.Services.Collections -{ - /// - /// Циклический разреженный итератор - /// позволяет выполнять циклический обход массива, с возможностью отмечать элементы - /// которые требуется прпускать при следующих обходах. - /// - public class SparseIterator - { - private readonly T[] _array; - private readonly HashSet _removed = new HashSet(); - private int index = -1; - - public SparseIterator(IEnumerable items) - { - _array = items.ToArray(); - } - /// - /// Текущий элемент последовательности - /// - public T Current - { - get - { - if (index >= 0 && index < _array.Length) - { - return _array[index]; - } - throw new IndexOutOfRangeException(); - } - } - /// - /// Указывает на отсутствие элементов в последовательности или на - /// то что все элементы были отмечены для пропуска - /// - public bool IsEmpty - { - get - { - return _array.Length == 0 || _array.Length == _removed.Count; - } - } - /// - /// Сдвиг на следующий элемент, если достигнут конец последовательности, - /// переключается на первый неотмеченный для пропуска элемент - /// - /// вернет -1 если последовательность пуста, или если не осталось элементов не отмеченных для пропуска - public int MoveNext() - { - do - { - index++; - } while (_removed.Contains(index)); - if (index >= _array.Length) - { - if (IsEmpty) return -1; - index = -1; - do - { - index++; - } while (_removed.Contains(index)); - } - return index; - } - /// - /// Отмечает текущий элемент для пропуска при следующем обходе - /// - /// - public bool Exclude() - { - if (index >= 0) - { - return _removed.Add(index); - } - return false; - } - } -} diff --git a/ZeroLevel/Services/Config/BaseConfiguration.cs b/ZeroLevel/Services/Config/BaseConfiguration.cs index 9e5e811..1c976c1 100644 --- a/ZeroLevel/Services/Config/BaseConfiguration.cs +++ b/ZeroLevel/Services/Config/BaseConfiguration.cs @@ -8,27 +8,27 @@ using ZeroLevel.Services.Serialization; namespace ZeroLevel.Services.Config { /// - /// Упрощенная конфигурация, без разделения параметров по секциям + /// Base configuration /// internal sealed class BaseConfiguration : IConfiguration { #region Private members /// - /// Указывает на заморозку конфигурации, все изменения запрещены + /// When true, any changes disallow /// private bool _freezed = false; /// - /// Указывает на перманентную заморозку конфигурации, разморозка запрещена + /// When true, freeze permanent, can't be canceled /// private bool _permanentFreezed = false; private readonly object _freezeLock = new object(); /// - /// Список вида ключ-значение + /// Key-values dictionary /// private readonly ConcurrentDictionary> _keyValues = new ConcurrentDictionary>(); /// - /// Пустой список + /// Empty list /// private static readonly IEnumerable EmptyValuesList = new List(0); @@ -44,10 +44,10 @@ namespace ZeroLevel.Services.Config #region Properties /// - /// Список значений по ключу + /// Get values by key /// - /// Ключ - /// Список значений + /// key + /// Values list public IEnumerable this[string key] { get @@ -62,7 +62,7 @@ namespace ZeroLevel.Services.Config } } /// - /// Список ключей + /// Keys list /// public IEnumerable Keys { @@ -240,10 +240,10 @@ namespace ZeroLevel.Services.Config #endregion /// - /// Добавление ключа и связанного с ним значения + /// Add key-value /// - /// Ключ - /// Значение + /// Key + /// Value public IConfiguration Append(string key, string value) { if (false == _freezed) @@ -258,8 +258,7 @@ namespace ZeroLevel.Services.Config return this; } /// - /// Задает значение в единственном числе, - /// существующее значение будет перезаписано + /// Set unique value for key /// public IConfiguration SetUnique(string key, string value) { @@ -270,15 +269,18 @@ namespace ZeroLevel.Services.Config { _keyValues.TryAdd(key, new List()); } - _keyValues[key].Clear(); + else + { + _keyValues[key].Clear(); + } _keyValues[key].Add(value?.Trim() ?? null); } return this; } /// - /// Очистка связанного с ключом списка значений + /// Clean values binded with key /// - /// Ключ + /// Key public IConfiguration Clear(string key) { if (false == _freezed) @@ -292,7 +294,7 @@ namespace ZeroLevel.Services.Config return this; } /// - /// Очистка конфигурации + /// Configuration drop /// public IConfiguration Clear() { @@ -303,9 +305,9 @@ namespace ZeroLevel.Services.Config return this; } /// - /// Удаление ключа и связанных с ним значений + /// Remove key and binded values /// - /// Ключ + /// Key public IConfiguration Remove(string key) { if (false == _freezed) diff --git a/ZeroLevel/Services/Config/BaseConfigurationSet.cs b/ZeroLevel/Services/Config/BaseConfigurationSet.cs index 9890308..ea22943 100644 --- a/ZeroLevel/Services/Config/BaseConfigurationSet.cs +++ b/ZeroLevel/Services/Config/BaseConfigurationSet.cs @@ -7,14 +7,14 @@ using ZeroLevel.Services.Serialization; namespace ZeroLevel.Services.Config { /// - /// Наборы именованых конфигураций (секций) + /// Named configuration sections array /// internal sealed class BaseConfigurationSet : IConfigurationSet { #region Private members /// - /// Список секций + /// Sections /// private readonly ConcurrentDictionary _sections = new ConcurrentDictionary(); diff --git a/ZeroLevel/Services/Config/Configuration.cs b/ZeroLevel/Services/Config/Configuration.cs index 507fc3b..afa421e 100644 --- a/ZeroLevel/Services/Config/Configuration.cs +++ b/ZeroLevel/Services/Config/Configuration.cs @@ -12,7 +12,7 @@ namespace ZeroLevel public static class Configuration { /// - /// Путь к каталогу приложения + /// Application folder path /// public static string BaseDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly()?.CodeBase)?. diff --git a/ZeroLevel/Services/Config/IConfiguration.cs b/ZeroLevel/Services/Config/IConfiguration.cs index 2fcda9a..60b7e49 100644 --- a/ZeroLevel/Services/Config/IConfiguration.cs +++ b/ZeroLevel/Services/Config/IConfiguration.cs @@ -5,7 +5,7 @@ using ZeroLevel.Services.Serialization; namespace ZeroLevel { /// - /// Интерфейс конфигурационных данных + /// Configuration section /// public interface IConfiguration : IEquatable, @@ -13,103 +13,101 @@ namespace ZeroLevel { #region Properties /// - /// Получение списка значений по ключу + /// Get values by key /// IEnumerable this[string key] { get; } /// - /// Перечисление ключей + /// Keys /// IEnumerable Keys { get; } /// - /// Указывает что конфигурация заблокирована на изменения + /// Configuration is locked for change when true /// bool Freezed { get; } #endregion #region Methods /// - /// Получение списка значений параметра по ключу + /// Get values by key /// - /// Имя параметра - /// Список значений + /// Key + /// Values list IEnumerable Items(string key); /// - /// Получение одного(первого) значения параметра по ключу + /// Get first value by key /// string First(string key); /// - /// Получить первое значение в виде объекта типа T + /// Get first value by key with cast to /// T First(string key); /// - /// Получить первое значение или значение по умолчанию + /// Get first or default value by key /// string FirstOrDefault(string name, string defaultValue); /// - /// Получить первое значение в виде объекта типа T или получить значение по умолчанию + /// Get first or default value by key with cast to /// T FirstOrDefault(string name); /// - /// Получить первое значение в виде объекта типа T или получить переданное значение по умолчанию + /// Get first or default value by key with cast to /// T FirstOrDefault(string name, T defaultValue); /// - /// Проверка наличия ключа + /// Check key exists /// bool Contains(string key); /// - /// Проверка наличия одного из ключей + /// Check one of key exists /// bool Contains(params string[] keys); /// - /// Проверка наличия значения по ключу + /// true if exists one or more values by key /// bool ContainsValue(string key, string value); /// - /// Количество значений параметра + /// Count values by key /// int Count(string key); /// - /// Выполняет указанное действие только в случае если в конфигурации есть ключ + /// Do action if key exists, action takes first value /// void DoWithFirst(string key, Action action); /// - /// Выполняет указанное действие только в случае если в конфигурации есть ключ + /// Do action if key exists, action takes first value with cast to /// void DoWithFirst(string key, Action action); #endregion #region Create, Clean, Delete /// - /// Очистка всей секции + /// Clean /// IConfiguration Clear(); /// - /// Очистка значения ключа + /// Clean values by key /// IConfiguration Clear(string key); /// - /// Удаление ключа и значений + /// Remove key and binded values /// IConfiguration Remove(string key); /// - /// Добавление параметра + /// Append key and value /// IConfiguration Append(string key, string value); /// - /// Задает значение в единственном числе, - /// существующее значение будет перезаписано + /// Set key with one value, if any values by key exists, they will be dropped /// IConfiguration SetUnique(string key, string value); /// - /// Запрещает вносить какие-либо изменения в конфигурацию + /// Sets a prohibition on changing /// - /// false - если уже установлен запрет + /// false - prohibition was set already bool Freeze(bool permanent = false); /// - /// Убирает запрет на внесение изменений в конфигурацию + /// Remove a prohibition on changing /// - /// false - если запрет снят bool Unfreeze(); #endregion } diff --git a/ZeroLevel/Services/Config/IConfigurationSet.cs b/ZeroLevel/Services/Config/IConfigurationSet.cs index bc3a36b..4fae6d6 100644 --- a/ZeroLevel/Services/Config/IConfigurationSet.cs +++ b/ZeroLevel/Services/Config/IConfigurationSet.cs @@ -5,7 +5,7 @@ using ZeroLevel.Services.Serialization; namespace ZeroLevel { /// - /// Интерфейс набора конфигурационных данных + /// Named configuration sections array /// public interface IConfigurationSet : IEquatable, @@ -13,72 +13,64 @@ namespace ZeroLevel { #region Properties /// - /// Получение конфигурации по умолчанию + /// Default section, always exists /// IConfiguration Default { get; } /// - /// Получение конфигурации по имени + /// Get configuration section by name /// IConfiguration this[string sectionName] { get; } /// - /// Получение имен конфигураций + /// Get configuration section names /// IEnumerable SectionNames { get; } /// - /// Получение всех конфигураций + /// Get all sections /// IEnumerable Sections { get; } /// - /// Указывает, заблокирован или нет набор секций + /// true if changing disallow /// bool SectionsFreezed { get; } #endregion #region Methods /// - /// Создание секции параметров + /// Create section /// - /// Название секции + /// Section name IConfiguration CreateSection(string sectionName); /// - /// Запрос секции данных по имени секции + /// Get configuration section by name /// /// Название секции /// Секция с данными IConfiguration GetSection(string sectionName); /// - /// Проверка наличия секции с указанным именем + /// Check for a section by name /// - /// Название секции - /// true - секция существует + /// Section name bool ContainsSection(string sectionName); - /// - /// Удаление секции + /// Remove section by name /// - /// Название секции - /// false - если секция уже удалена или не существует + /// Section name bool RemoveSection(string sectionName); /// - /// Запрещает вносить какие-либо изменения в существующую конфигурацию во всех секциях - /// а также менять набор секций + /// Sets a prohibition on changing configurations /// - /// false - если уже установлен запрет bool FreezeConfiguration(bool permanent = false); /// - /// Запрещает вносить какие-либо изменения в существующий набор секций + /// Sets a prohibition on changing sections /// - /// false - если уже установлен запрет bool FreezeSections(bool permanent = false); /// - /// Убирает запрет на внесение изменений в существующую конфигурацию во всех секциях - /// а также разрешает менять набор секций + /// Remove a prohibition on changing configurations /// /// false - если запрет снят bool UnfreezeConfiguration(); /// - /// Убирает запрет на внесение изменений в существующий набор секций + /// Sets a prohibition on changing sections /// - /// false - если запрет снят bool UnfreezeSections(); #endregion } diff --git a/ZeroLevel/Services/Config/Implementation/CommandLineReader.cs b/ZeroLevel/Services/Config/Implementation/CommandLineReader.cs index 7b8299b..87ead47 100644 --- a/ZeroLevel/Services/Config/Implementation/CommandLineReader.cs +++ b/ZeroLevel/Services/Config/Implementation/CommandLineReader.cs @@ -40,7 +40,7 @@ namespace ZeroLevel.Services.Config.Implementation } catch (Exception ex) { - throw new InvalidOperationException("Не удалось создать конфигурацию из аргументов командной строки", ex); + throw new InvalidOperationException("Can't read configuration from command line arguments", ex); } } return result; diff --git a/ZeroLevel/Services/Config/Implementation/IniFileReader.cs b/ZeroLevel/Services/Config/Implementation/IniFileReader.cs index cc636cc..e8386ff 100644 --- a/ZeroLevel/Services/Config/Implementation/IniFileReader.cs +++ b/ZeroLevel/Services/Config/Implementation/IniFileReader.cs @@ -15,13 +15,13 @@ namespace ZeroLevel.Services.Config.Implementation internal IniFileReader(string configPath) { if (String.IsNullOrWhiteSpace(configPath)) - throw new ArgumentNullException("configPath", "Не указан путь к конфигурационному файлу"); + throw new ArgumentNullException("configPath", "File path not found"); if (!File.Exists(configPath)) { configPath = Path.Combine(Configuration.BaseDirectory, configPath); if (!File.Exists(configPath)) { - throw new FileNotFoundException("Не существует конфигурационный файл: " + configPath); + throw new FileNotFoundException("File path not exists: " + configPath); } } _iniPath = configPath; diff --git a/ZeroLevel/Services/Config/Implementation/IniFileWriter.cs b/ZeroLevel/Services/Config/Implementation/IniFileWriter.cs index a57c033..9aa32c3 100644 --- a/ZeroLevel/Services/Config/Implementation/IniFileWriter.cs +++ b/ZeroLevel/Services/Config/Implementation/IniFileWriter.cs @@ -3,27 +3,23 @@ namespace ZeroLevel.Services.Config.Implementation { /// - /// Запись конфигурации в ini-файл + /// Write config to ini-file /// public class IniFileWriter : IConfigurationWriter { /// - /// Путь к ini-файлу + /// Config file path /// private readonly string _iniPath; - /// - /// Инициализирует новый экземпляр класса - /// - /// Путь к ini-файлу + public IniFileWriter(string iniPath) { _iniPath = iniPath; } /// - /// Запись простой конфигурации + /// Write config to file /// - /// Конфигурация public void WriteConfiguration(IConfiguration configuration) { using (TextWriter writer = new StreamWriter(_iniPath, false)) @@ -46,9 +42,8 @@ namespace ZeroLevel.Services.Config.Implementation } } /// - /// Запись конфигурации разбитой по секциям + /// Write configuration set to file /// - /// Конфигурация public void WriteConfigurationSet(IConfigurationSet configuration) { using (TextWriter writer = new StreamWriter(_iniPath, false)) diff --git a/ZeroLevel/Services/DOM/Contracts/IMetadataReader.cs b/ZeroLevel/Services/DOM/Contracts/IMetadataReader.cs index 42c2103..b296247 100644 --- a/ZeroLevel/Services/DOM/Contracts/IMetadataReader.cs +++ b/ZeroLevel/Services/DOM/Contracts/IMetadataReader.cs @@ -11,7 +11,7 @@ namespace ZeroLevel.DocumentObjectModel void EnterIdentifier(Identifier identifier); void ReadVersion(int version); - void ReadTimestamp(string timestamp); + void ReadTimestamp(long timestamp); void ReadDateLabel(string datelabel); void LeaveIdentifier(Identifier identifier); @@ -44,9 +44,9 @@ namespace ZeroLevel.DocumentObjectModel void LeaveHeaders(IEnumerable
headers); void LeaveDescriptioveBlock(DescriptiveMetadata metadata); - void EnterAsides(IEnumerable asides); - void ReadAside(AsideContent aside, int order); - void LeaveAsides(IEnumerable asides); + void EnterAsides(IEnumerable asides); + void ReadAside(AttachContent aside, int order); + void LeaveAsides(IEnumerable asides); void EnterAssotiations(IEnumerable assotiations); void ReadAssotiation(Assotiation assotiation, int order); diff --git a/ZeroLevel/Services/DOM/DSL/Contracts/ISpecialTableBuilder.cs b/ZeroLevel/Services/DOM/DSL/Contracts/ISpecialTableBuilder.cs index ae4f5fd..11d8306 100644 --- a/ZeroLevel/Services/DOM/DSL/Contracts/ISpecialTableBuilder.cs +++ b/ZeroLevel/Services/DOM/DSL/Contracts/ISpecialTableBuilder.cs @@ -6,7 +6,7 @@ namespace DOM.DSL.Contracts public interface ISpecialTableBuilder { /// - /// Указывает что ожидается запись тела ячейки таблицы + /// Indicates that a table cell body entry is expected. /// bool WaitCellBody { get; } void WriteToCell(string part); diff --git a/ZeroLevel/Services/DOM/DSL/Model/TFlowRules.cs b/ZeroLevel/Services/DOM/DSL/Model/TFlowRules.cs index 42d828b..ba33fdd 100644 --- a/ZeroLevel/Services/DOM/DSL/Model/TFlowRules.cs +++ b/ZeroLevel/Services/DOM/DSL/Model/TFlowRules.cs @@ -305,13 +305,13 @@ namespace DOM.DSL.Model case "ignore": TablePrefix = TablePostfix = null; break; - case "special": // Использование захардкоженного преобразования таблицы + case "special": // Using a hardcoded table conversion //TablePrefix = TablePostfix = null; ColumnsPrefix = ColumnsPostfix = null; ColumnPrefix = ColumnTemplate = ColumnPostfix = null; RowPrefix = RowPostfix = null; CellPrefix = CellPostfix = null; - // Аргументы: (style, paddings l-t-r-b, maxcellwidth, maxtablewidth) + // Args: (style, paddings l-t-r-b, maxcellwidth, maxtablewidth) UseSpecialTableBuilder = true; SpecialTableBuilder = SpecialTableBuilderFactory.CreateSpecialTableBuilder(special); if (SpecialTableBuilder == null) UseSpecialTableBuilder = false; diff --git a/ZeroLevel/Services/DOM/DSL/Services/SpecialTableBuilderFactory.cs b/ZeroLevel/Services/DOM/DSL/Services/SpecialTableBuilderFactory.cs index 3d008a8..e61b44a 100644 --- a/ZeroLevel/Services/DOM/DSL/Services/SpecialTableBuilderFactory.cs +++ b/ZeroLevel/Services/DOM/DSL/Services/SpecialTableBuilderFactory.cs @@ -17,12 +17,12 @@ namespace DOM.DSL.Services case "plaintext": // (Borders, 1-0-1-0, 0, 96) var options = new TextTableRenderOptions(); - if (args.Length > 1) // Стиль + if (args.Length > 1) // Style { if (Enum.TryParse(args[1], out options.Style) == false) options.Style = TextTableStyle.Borders; } - if (args.Length > 2) // Паддинги + if (args.Length > 2) // Paddings { var paddings = args[2].Split(' '); int buffer; @@ -40,7 +40,7 @@ namespace DOM.DSL.Services } } } - if (args.Length > 3) // Ширина ячейки + if (args.Length > 3) // Cell width { int buffer; if (true == int.TryParse(args[3].Trim(), out buffer)) @@ -48,7 +48,7 @@ namespace DOM.DSL.Services options.MaxCellWidth = buffer; } } - if (args.Length > 4) // Ширина таблицы + if (args.Length > 4) // Table width { int buffer; if (true == int.TryParse(args[4].Trim(), out buffer)) diff --git a/ZeroLevel/Services/DOM/DSL/Services/TContainer.cs b/ZeroLevel/Services/DOM/DSL/Services/TContainer.cs index f9bb8ff..f5e6feb 100644 --- a/ZeroLevel/Services/DOM/DSL/Services/TContainer.cs +++ b/ZeroLevel/Services/DOM/DSL/Services/TContainer.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Security; using System.Text; using System.Threading; +using ZeroLevel; using ZeroLevel.DocumentObjectModel; using ZeroLevel.DocumentObjectModel.Flow; using ZeroLevel.Services.FileSystem; @@ -56,7 +57,7 @@ namespace DOM.DSL.Services } else { - // Добавляются элементы разных типов, в этом случае все элементы приводим к string + // Added elements of different types. All elements casts to string var list = new List(); foreach (var i in _list) list.Add(i.ToString()); _elementType = typeof(string); @@ -170,7 +171,7 @@ namespace DOM.DSL.Services else if (_current is Category) SelectProperty((Category)_current, propertyName, propertyIndex); else if (_current is Header) SelectProperty((Header)_current, propertyName, propertyIndex); else if (_current is Tag) SelectProperty((Tag)_current, propertyName, propertyIndex); - else if (_current is AsideContent) SelectProperty((AsideContent)_current, propertyName, propertyIndex); + else if (_current is AttachContent) SelectProperty((AttachContent)_current, propertyName, propertyIndex); else if (_current is Assotiation) SelectProperty((Assotiation)_current, propertyName, propertyIndex); else if (_current is List
) SelectProperty((List
)_current, propertyName, propertyIndex); else if (_current is Identifier) SelectProperty((Identifier)_current, propertyName, propertyIndex); @@ -255,8 +256,9 @@ namespace DOM.DSL.Services { return (T)Convert.ChangeType(_current, type); } - catch + catch (Exception ex) { + Log.SystemWarning($"[DOM.TContainer] Fault cast current value from type '{_current?.GetType()?.FullName ?? string.Empty}' to type '{type.FullName}'. {ex.ToString()}"); return default(T); } } @@ -273,8 +275,9 @@ namespace DOM.DSL.Services { return Convert.ChangeType(_current, type); } - catch + catch(Exception ex) { + Log.SystemWarning($"[DOM.TContainer] Fault cast current value from type '{_current?.GetType()?.FullName ?? string.Empty}' to type '{type.FullName}'. {ex.ToString()}"); return TypeHelpers.CreateDefaultState(type); } } @@ -1144,7 +1147,7 @@ namespace DOM.DSL.Services } } - private void SelectProperty(AsideContent aside, string property, string propertyIndex) + private void SelectProperty(AttachContent aside, string property, string propertyIndex) { switch (property.Trim().ToLowerInvariant()) { @@ -2596,7 +2599,7 @@ namespace DOM.DSL.Services else if (_current is Category) return ((Category)_current).Title ?? string.Empty; else if (_current is Header) return ((Header)_current).Value ?? string.Empty; else if (_current is Tag) return ((Tag)_current).Name ?? string.Empty; - else if (_current is AsideContent) return ((AsideContent)_current).Caption ?? string.Empty; + else if (_current is AttachContent) return ((AttachContent)_current).Caption ?? string.Empty; else if (_current is Assotiation) return ((Assotiation)_current).Title ?? string.Empty; else if (_current is List
) return string.Join("; ", ((List
)_current).Select(h => h.Name)); else if (_current is Identifier) return string.Empty; @@ -2640,4 +2643,4 @@ namespace DOM.DSL.Services return _current?.ToString() ?? string.Empty; } } -} +} \ No newline at end of file diff --git a/ZeroLevel/Services/DOM/DSL/Services/TRender.cs b/ZeroLevel/Services/DOM/DSL/Services/TRender.cs index 3172752..642da42 100644 --- a/ZeroLevel/Services/DOM/DSL/Services/TRender.cs +++ b/ZeroLevel/Services/DOM/DSL/Services/TRender.cs @@ -43,64 +43,30 @@ namespace DOM.DSL.Services { private readonly Document _document; private readonly TEnvironment _environment; - private readonly DOMRenderElementCounter _counter; - private readonly TRenderOptions _options = new TRenderOptions(); - private readonly TContainerFactory _factory; - private readonly IDictionary _buffer = - new Dictionary(); - private readonly CustomBlocks _blocks = new CustomBlocks(); - - internal TContainerFactory Factory - { - get - { - return _factory; - } - } - - internal IDictionary BufferDictionary - { - get - { - return _buffer; - } - } - - internal DOMRenderElementCounter Counter - { - get - { - return _counter; - } - } - - internal TRenderOptions Options - { - get - { - return _options; - } - } + internal TContainerFactory Factory { get; } + internal IDictionary BufferDictionary { get; } = new Dictionary(); + internal DOMRenderElementCounter Counter { get; } + internal TRenderOptions Options { get; } = new TRenderOptions(); public TRender(Document document, TEnvironment environment) { _document = document; _environment = environment; - _counter = new DOMRenderElementCounter(); - _factory = new TContainerFactory(this); + Counter = new DOMRenderElementCounter(); + Factory = new TContainerFactory(this); } public void Resolve(TToken token, Action handler, bool release = true, TContainer self = null) { - var self_copy = self == null ? null : _factory.Get(self.Current, self.Index); + var self_copy = self == null ? null : Factory.Get(self.Current, self.Index); try { if (token is TTextToken) { - var container = _factory.Get(token.AsTextToken().Text); + var container = Factory.Get(token.AsTextToken().Text); handler(container); - if (release) _factory.Release(container); + if (release) Factory.Release(container); } else if (token is TElementToken) { @@ -108,7 +74,7 @@ namespace DOM.DSL.Services foreach (var c in containers) { handler(c); - if (release) _factory.Release(c); + if (release) Factory.Release(c); } } else if (token is TBlockToken) @@ -117,13 +83,13 @@ namespace DOM.DSL.Services foreach (var c in containers) { handler(c); - if (release) _factory.Release(c); + if (release) Factory.Release(c); } } } finally { - _factory.Release(self_copy); + Factory.Release(self_copy); } } @@ -133,56 +99,56 @@ namespace DOM.DSL.Services switch (token.ElementName.Trim().ToLowerInvariant()) { // External - case "now": container = _factory.Get(DateTime.Now); break; - case "utc": container = _factory.Get(DateTime.Now.ToUniversalTime()); break; - case "guid": container = _factory.Get(Guid.NewGuid()); break; - case "nowutc": container = _factory.Get(DateTime.UtcNow); break; + case "now": container = Factory.Get(DateTime.Now); break; + case "utc": container = Factory.Get(DateTime.Now.ToUniversalTime()); break; + case "guid": container = Factory.Get(Guid.NewGuid()); break; + case "nowutc": container = Factory.Get(DateTime.UtcNow); break; // Document - case "id": container = _factory.Get(_document.Id); break; - case "summary": container = _factory.Get(_document.Summary); break; - case "header": container = _factory.Get(_document.Header); break; - case "categories": container = _factory.Get(_document.Categories); break; + case "id": container = Factory.Get(_document.Id); break; + case "summary": container = Factory.Get(_document.Summary); break; + case "header": container = Factory.Get(_document.Header); break; + case "categories": container = Factory.Get(_document.Categories); break; case "directions": - container = _factory.Get(_document.Categories. + container = Factory.Get(_document.Categories. Select(c => c.DirectionCode).Distinct().ToList()); break; // Descriptive case "desc": - case "descriptive": container = _factory.Get(_document.DescriptiveMetadata); break; - case "author": container = _factory.Get(_document.DescriptiveMetadata.Byline); break; - case "copyright": container = _factory.Get(_document.DescriptiveMetadata.CopyrightNotice); break; - case "created": container = _factory.Get(_document.DescriptiveMetadata.Created); break; - case "lang": container = _factory.Get(_document.DescriptiveMetadata.Language); break; - case "priority": container = _factory.Get(_document.DescriptiveMetadata.Priority); break; - case "source": container = _factory.Get(_document.DescriptiveMetadata.Source); break; - case "publisher": container = _factory.Get(_document.DescriptiveMetadata.Publisher); break; + case "descriptive": container = Factory.Get(_document.DescriptiveMetadata); break; + case "author": container = Factory.Get(_document.DescriptiveMetadata.Byline); break; + case "copyright": container = Factory.Get(_document.DescriptiveMetadata.CopyrightNotice); break; + case "created": container = Factory.Get(_document.DescriptiveMetadata.Created); break; + case "lang": container = Factory.Get(_document.DescriptiveMetadata.Language); break; + case "priority": container = Factory.Get(_document.DescriptiveMetadata.Priority); break; + case "source": container = Factory.Get(_document.DescriptiveMetadata.Source); break; + case "publisher": container = Factory.Get(_document.DescriptiveMetadata.Publisher); break; case "meta": - case "headers": container = _factory.Get(_document.DescriptiveMetadata.Headers); break; + case "headers": container = Factory.Get(_document.DescriptiveMetadata.Headers); break; // Identifier - case "identifier": container = _factory.Get(_document.Identifier); break; - case "timestamp": container = _factory.Get(_document.Identifier.Timestamp); break; - case "datelabel": container = _factory.Get(_document.Identifier.DateLabel); break; - case "version": container = _factory.Get(_document.Identifier.Version); break; + case "identifier": container = Factory.Get(_document.Identifier); break; + case "timestamp": container = Factory.Get(_document.Identifier.Timestamp); break; + case "datelabel": container = Factory.Get(_document.Identifier.DateLabel); break; + case "version": container = Factory.Get(_document.Identifier.Version); break; // Tags - case "tags": container = _factory.Get(_document.TagMetadata); break; - case "keywords": container = _factory.Get(_document.TagMetadata.Keywords); break; - case "companies": container = _factory.Get(_document.TagMetadata.Companies); break; - case "persons": container = _factory.Get(_document.TagMetadata.Persons); break; - case "places": container = _factory.Get(_document.TagMetadata.Places); break; + case "tags": container = Factory.Get(_document.TagMetadata); break; + case "keywords": container = Factory.Get(_document.TagMetadata.Keywords); break; + case "companies": container = Factory.Get(_document.TagMetadata.Companies); break; + case "persons": container = Factory.Get(_document.TagMetadata.Persons); break; + case "places": container = Factory.Get(_document.TagMetadata.Places); break; - case "var": container = _factory.Get(_environment.CustomVariables); break; - case "buf": container = _factory.Get(_buffer); break; - case "env": container = _factory.Get(_environment); break; - case "counter": container = _factory.Get(_counter); break; - case "self": container = _factory.Get(self.Current, self.Index); break; - case "content": container = _factory.Get(new TContentElement(_document)); break; - case "aside": container = _factory.Get(_document.Aside); break; - case "assotiations": container = _factory.Get(_document.Assotiations); break; - case "null": container = _factory.Get(null); break; - case "empty": container = _factory.Get(string.Empty); break; + case "var": container = Factory.Get(_environment.CustomVariables); break; + case "buf": container = Factory.Get(BufferDictionary); break; + case "env": container = Factory.Get(_environment); break; + case "counter": container = Factory.Get(Counter); break; + case "self": container = Factory.Get(self.Current, self.Index); break; + case "content": container = Factory.Get(new TContentElement(_document)); break; + case "aside": container = Factory.Get(_document.Attachments); break; + case "assotiations": container = Factory.Get(_document.Assotiations); break; + case "null": container = Factory.Get(null); break; + case "empty": container = Factory.Get(string.Empty); break; // Blocks case "build": @@ -191,15 +157,15 @@ namespace DOM.DSL.Services { var block = new TBlockToken(_blocks.Get(token.NextToken.AsPropertyToken().PropertyName)); var result = ResolveBlockToken(block, self); - container = _factory.Get(result.Where(c => c.Current != null).Select(c => c.Current).ToList()); + container = Factory.Get(result.Where(c => c.Current != null).Select(c => c.Current).ToList()); foreach (var c in result) - _factory.Release(c); + Factory.Release(c); } break; } } - if (container == null) container = _factory.Get(null); + if (container == null) container = Factory.Get(null); if (token.NextToken is TPropertyToken) { @@ -286,13 +252,13 @@ namespace DOM.DSL.Services List result; if (success) { - var ls = self_parent == null ? null : _factory.Get(self_parent.Current, self_parent.Index); + var ls = self_parent == null ? null : Factory.Get(self_parent.Current, self_parent.Index); result = ResolveSimpleBlockToken(blockToken, ls); - _factory.Release(ls); + Factory.Release(ls); } else { - result = new List { _factory.Get(null) }; + result = new List { Factory.Get(null) }; } return result; } @@ -308,12 +274,12 @@ namespace DOM.DSL.Services int index = 0; foreach (var t in (IEnumerable)self_container.Current) { - var self = _factory.Get(t, index); + var self = Factory.Get(t, index); foreach (var bt in blockToken.Body) { Resolve(bt, c => list.Add(c), false, self); } - _factory.Release(self); + Factory.Release(self); index++; } } @@ -325,7 +291,7 @@ namespace DOM.DSL.Services } } } - _factory.Release(self_container); + Factory.Release(self_container); return list; } } @@ -366,12 +332,12 @@ namespace DOM.DSL.Services } special = string.Join(",", args.Select(a => a.ToString())); foreach (var a in args) - _factory.Release(a); + Factory.Release(a); } rules.UpdateRule(elementName, functionName, rule_token, special); } } - return _factory.Get(DocumentContentReader.ReadAs(_document, new TContentToStringConverter(this, rules))); + return Factory.Get(DocumentContentReader.ReadAs(_document, new TContentToStringConverter(this, rules))); } private void ApplyRenderCommand(TSystemToken token) @@ -396,13 +362,13 @@ namespace DOM.DSL.Services switch (args[0].ToString().Trim().ToLowerInvariant()) { case "xml": - _options.ValidateAsXml = true; + Options.ValidateAsXml = true; break; case "html": - _options.ValidateAsHtml = true; + Options.ValidateAsHtml = true; break; case "json": - _options.ValidateAsJson = true; + Options.ValidateAsJson = true; break; } } @@ -414,22 +380,24 @@ namespace DOM.DSL.Services int width; if (int.TryParse(args[0].ToString(), out width)) { - _options.MaxStringWidth = width; + Options.MaxStringWidth = width; } else { - _options.MaxStringWidth = -1; + Options.MaxStringWidth = -1; } } else { - _options.MaxStringWidth = -1; + Options.MaxStringWidth = -1; } } break; } foreach (var a in args) - _factory.Release(a); + { + Factory.Release(a); + } } } } diff --git a/ZeroLevel/Services/DOM/DSL/TEngine.cs b/ZeroLevel/Services/DOM/DSL/TEngine.cs index fa76c46..1b3c249 100644 --- a/ZeroLevel/Services/DOM/DSL/TEngine.cs +++ b/ZeroLevel/Services/DOM/DSL/TEngine.cs @@ -28,7 +28,7 @@ namespace DOM.DSL } catch (Exception ex) { - Log.SystemError(ex, "Fault parse template '{0}' to token list", template); + Log.SystemError(ex, $"Fault parse template '{template}' to token list"); } } return Enumerable.Empty(); @@ -69,7 +69,7 @@ namespace DOM.DSL } catch (Exception ex) { - Log.Debug("Fault transform document '{0} by token list'. {1}", document.Id, ex); + Log.Debug($"Fault transform document '{document.Id} by token list'. {ex.ToString()}"); if (ignore_fault == false) { throw ex; diff --git a/ZeroLevel/Services/DOM/DSL/Tokens/TElementToken.cs b/ZeroLevel/Services/DOM/DSL/Tokens/TElementToken.cs index 7cb580c..d538a67 100644 --- a/ZeroLevel/Services/DOM/DSL/Tokens/TElementToken.cs +++ b/ZeroLevel/Services/DOM/DSL/Tokens/TElementToken.cs @@ -1,7 +1,7 @@ namespace DOM.DSL.Tokens { /// - /// Токен ссылающийся на элемент документа + /// Token referring to the document element /// public class TElementToken : TToken @@ -11,7 +11,7 @@ ///
public string ElementName; /// - /// Опционально, при наличии свойств и/или функций для текущего элемента + /// Optionally, next token /// public TToken NextToken; diff --git a/ZeroLevel/Services/DOM/DSL/Tokens/TTextToken.cs b/ZeroLevel/Services/DOM/DSL/Tokens/TTextToken.cs index eb6c05c..889bfa9 100644 --- a/ZeroLevel/Services/DOM/DSL/Tokens/TTextToken.cs +++ b/ZeroLevel/Services/DOM/DSL/Tokens/TTextToken.cs @@ -1,13 +1,13 @@ namespace DOM.DSL.Tokens { /// - /// Текстовый токен + /// Text token /// public class TTextToken : TToken { /// - /// Текст в шаблоне, переносимый в результат без обработки + /// Constant text /// public string Text; diff --git a/ZeroLevel/Services/DOM/DSL/Tokens/TToken.cs b/ZeroLevel/Services/DOM/DSL/Tokens/TToken.cs index 64b97ee..b9bf4ef 100644 --- a/ZeroLevel/Services/DOM/DSL/Tokens/TToken.cs +++ b/ZeroLevel/Services/DOM/DSL/Tokens/TToken.cs @@ -3,13 +3,13 @@ namespace DOM.DSL.Tokens { /// - /// Абстрактная единица шаблона + /// Abstract token /// public abstract class TToken : TCloneable { public abstract TToken Clone(); /// - /// Копия с установкой NextToken в null, для предотвращения циклических расчетов + /// Copying token with set NextToken to null, to break cycle /// /// public abstract TToken CloneLocal(); diff --git a/ZeroLevel/Services/DOM/Model/Agency.cs b/ZeroLevel/Services/DOM/Model/Agency.cs index 0fcf263..5f8d379 100644 --- a/ZeroLevel/Services/DOM/Model/Agency.cs +++ b/ZeroLevel/Services/DOM/Model/Agency.cs @@ -5,15 +5,15 @@ namespace ZeroLevel.DocumentObjectModel public class Agency : IBinarySerializable { /// - /// Название источника + /// Agency name /// public string Title; /// - /// Ссылка на источник + /// Agency website /// public string Url; /// - /// Описание источника + /// Description /// public string Description; diff --git a/ZeroLevel/Services/DOM/Model/Assotiation.cs b/ZeroLevel/Services/DOM/Model/Assotiation.cs index 03a5cbb..9dace00 100644 --- a/ZeroLevel/Services/DOM/Model/Assotiation.cs +++ b/ZeroLevel/Services/DOM/Model/Assotiation.cs @@ -8,19 +8,19 @@ namespace ZeroLevel.DocumentObjectModel { #region Fields /// - /// Заголовок + /// Title /// public string Title; /// - /// Описание (например, что было изменено по сравнению с прошлой версией) + /// Description /// public string Description; /// - /// Ссылка на связанный документ + /// Binded document reference /// public Guid DocumentId; /// - /// Тип связи + /// Relation type /// public AssotiationRelation Relation; #endregion diff --git a/ZeroLevel/Services/DOM/Model/AssotiationRelation.cs b/ZeroLevel/Services/DOM/Model/AssotiationRelation.cs index 066b6ff..c05d06a 100644 --- a/ZeroLevel/Services/DOM/Model/AssotiationRelation.cs +++ b/ZeroLevel/Services/DOM/Model/AssotiationRelation.cs @@ -5,23 +5,23 @@ namespace ZeroLevel.DocumentObjectModel public enum AssotiationRelation : Int32 { /// - /// Тип отношения не определен + /// Relation type not defined /// Uncknown = 0, /// - /// Упоминается + /// Mentioned /// Mentions = 1, /// - /// Рассказывается о + /// It tells about /// About = 2, /// - /// Обновление предыдущей версии + /// Previous version update /// UpdateOf = 3, /// - /// Основано на + /// Based on /// BasedOn = 4 } diff --git a/ZeroLevel/Services/DOM/Model/AsideContent.cs b/ZeroLevel/Services/DOM/Model/AttachContent.cs similarity index 72% rename from ZeroLevel/Services/DOM/Model/AsideContent.cs rename to ZeroLevel/Services/DOM/Model/AttachContent.cs index 87910b5..e31caf2 100644 --- a/ZeroLevel/Services/DOM/Model/AsideContent.cs +++ b/ZeroLevel/Services/DOM/Model/AttachContent.cs @@ -3,33 +3,33 @@ using ZeroLevel.Services.Serialization; namespace ZeroLevel.DocumentObjectModel { - public sealed class AsideContent + public sealed class AttachContent : IBinarySerializable { /// - /// Идентификатор + /// ID /// public string Identity; /// - /// Название содержимого + /// Title /// public string Caption; /// - /// Описание (опционально) + /// Description (optional) /// public string Summary; /// - /// Тип содержимого + /// Content type /// public ContentType ContentType; /// - /// Содержимое в бинарном представлении + /// Binary content /// public byte[] Payload; - public AsideContent() { } - public AsideContent(IBinaryReader reader) { Deserialize(reader); } - public AsideContent(string identity, string caption, string description) + public AttachContent() { } + public AttachContent(IBinaryReader reader) { Deserialize(reader); } + public AttachContent(string identity, string caption, string description) { Identity = identity; Summary = description; Caption = caption; } #region IBinarySerializable diff --git a/ZeroLevel/Services/DOM/Model/Category.cs b/ZeroLevel/Services/DOM/Model/Category.cs index a790eb0..4eb9b0d 100644 --- a/ZeroLevel/Services/DOM/Model/Category.cs +++ b/ZeroLevel/Services/DOM/Model/Category.cs @@ -43,28 +43,27 @@ namespace ZeroLevel.DocumentObjectModel #region Fields /// - /// Название + /// Title /// public string Title { get; set; } /// - /// Описание + /// Description /// public string Description { get; set; } /// - /// Код категории + /// Category code /// public string Code { get; set; } /// - /// Код направления + /// Direction code /// public string DirectionCode { get; set; } /// - /// Указывает на принадлежность категории внутренней части системы - /// Категория не предназначенна для публичного доступа + /// Is instrnal category /// public bool IsSystem { get; set; } diff --git a/ZeroLevel/Services/DOM/Model/DescriptiveMetadata.cs b/ZeroLevel/Services/DOM/Model/DescriptiveMetadata.cs index a07cf71..9b453e7 100644 --- a/ZeroLevel/Services/DOM/Model/DescriptiveMetadata.cs +++ b/ZeroLevel/Services/DOM/Model/DescriptiveMetadata.cs @@ -23,39 +23,39 @@ namespace ZeroLevel.DocumentObjectModel #region Fields /// - /// Авторы (подпись) + /// Authors /// public string Byline; /// - /// Копирайт + /// Copyright /// public string CopyrightNotice; /// - /// Дата создания + /// Creation date /// public DateTime Created; /// - /// Основной язык + /// Main language /// public string Language; /// - /// Важность + /// Priority /// public Priority Priority; /// - /// Источник документа (например, информационное агентство) + /// Document source /// public Agency Source; /// - /// Издатель (Агентство) + /// Document publisher /// public Agency Publisher; /// - /// Ссылка на оригинальную новость, если текущая создана на ее основе + /// Reference to original document /// public Tag Original; /// - /// Опциональные заголовки + /// Headers (optional) /// public List
Headers; #endregion diff --git a/ZeroLevel/Services/DOM/Model/Document.cs b/ZeroLevel/Services/DOM/Model/Document.cs index 4c22f08..0deb6e3 100644 --- a/ZeroLevel/Services/DOM/Model/Document.cs +++ b/ZeroLevel/Services/DOM/Model/Document.cs @@ -35,49 +35,49 @@ namespace ZeroLevel.DocumentObjectModel Content = new FlowContent(); TagMetadata = new TagMetadata(); DescriptiveMetadata = new DescriptiveMetadata(); - Aside = new List(); + Attachments = new List(); Assotiations = new List(); Categories = new List(); } /// - /// Идентификатор документа + /// ID /// public Guid Id; /// - /// Краткое описание, лид + /// Short description /// public string Summary; /// - /// Заголовок + /// Title /// public string Header; /// - /// Дополнительные идентификаторы + /// Identification block /// public Identifier Identifier; /// - /// Содержимое документа + /// Content /// public FlowContent Content; /// - /// Теги + /// Tags /// public TagMetadata TagMetadata; /// - /// Метаданные документа + /// Metadata /// public DescriptiveMetadata DescriptiveMetadata; /// - /// Вложенные документы + /// Attachments /// - public List Aside; + public List Attachments; /// - /// Связанные документы + /// Binded documents /// public List Assotiations; /// - /// Категории + /// Categories /// public List Categories; @@ -94,7 +94,7 @@ namespace ZeroLevel.DocumentObjectModel writer.Write(this.TagMetadata); writer.Write(this.DescriptiveMetadata); - writer.WriteCollection(this.Aside); + writer.WriteCollection(this.Attachments); writer.WriteCollection(this.Assotiations); writer.WriteCollection(this.Categories); } @@ -110,7 +110,7 @@ namespace ZeroLevel.DocumentObjectModel this.TagMetadata = reader.Read(); this.DescriptiveMetadata = reader.Read(); - this.Aside = reader.ReadCollection(); + this.Attachments = reader.ReadCollection(); this.Assotiations = reader.ReadCollection(); this.Categories = reader.ReadCollection(); } diff --git a/ZeroLevel/Services/DOM/Model/Flow/Audio.cs b/ZeroLevel/Services/DOM/Model/Flow/Audio.cs index 672179e..f23c7a1 100644 --- a/ZeroLevel/Services/DOM/Model/Flow/Audio.cs +++ b/ZeroLevel/Services/DOM/Model/Flow/Audio.cs @@ -8,11 +8,11 @@ namespace ZeroLevel.DocumentObjectModel.Flow { public SourceType Source { get; set; } /// - /// Название + /// Title /// public string Title; /// - /// Ссылка или идентификатор вложения + /// Link or Attachment ID /// public string Identifier; diff --git a/ZeroLevel/Services/DOM/Model/Flow/FlowAlign.cs b/ZeroLevel/Services/DOM/Model/Flow/FlowAlign.cs index a9ddc1b..9d9dea1 100644 --- a/ZeroLevel/Services/DOM/Model/Flow/FlowAlign.cs +++ b/ZeroLevel/Services/DOM/Model/Flow/FlowAlign.cs @@ -3,24 +3,24 @@ namespace ZeroLevel.DocumentObjectModel.Flow { /// - /// Смещение содержимого в потоке + /// Content Offset in flow /// public enum FlowAlign : Int32 { /// - /// Без смещения + /// None /// None = 0, /// - /// Смещение к левой части, допускает продолжение потока справа + /// Flow: left /// Left = 1, /// - /// Смещение к правой части, допускает продолжение потока слева + /// Flow: right /// Right = 2, /// - /// Выравнивание по центру + /// Block /// Center = 3 } diff --git a/ZeroLevel/Services/DOM/Model/Flow/FormContent.cs b/ZeroLevel/Services/DOM/Model/Flow/FormContent.cs index 0757455..96e4698 100644 --- a/ZeroLevel/Services/DOM/Model/Flow/FormContent.cs +++ b/ZeroLevel/Services/DOM/Model/Flow/FormContent.cs @@ -4,7 +4,7 @@ using ZeroLevel.Services.Serialization; namespace ZeroLevel.DocumentObjectModel.Flow { /// - /// Отображение вложенного документа или содержимого по внешней ссылке + /// Attached document or content by external link /// public sealed class FormContent : ContentElement { diff --git a/ZeroLevel/Services/DOM/Model/Flow/Image.cs b/ZeroLevel/Services/DOM/Model/Flow/Image.cs index c7d4bbd..c6e2377 100644 --- a/ZeroLevel/Services/DOM/Model/Flow/Image.cs +++ b/ZeroLevel/Services/DOM/Model/Flow/Image.cs @@ -9,11 +9,11 @@ namespace ZeroLevel.DocumentObjectModel.Flow public SourceType Source { get; set; } public FlowAlign Align = FlowAlign.None; /// - /// Название + /// Title /// public string Title; /// - /// Ссылка или идентификатор вложения + /// Link or Attachment ID /// public string Identifier; diff --git a/ZeroLevel/Services/DOM/Model/Flow/Paragraph.cs b/ZeroLevel/Services/DOM/Model/Flow/Paragraph.cs index 7f1b8a7..0725fb0 100644 --- a/ZeroLevel/Services/DOM/Model/Flow/Paragraph.cs +++ b/ZeroLevel/Services/DOM/Model/Flow/Paragraph.cs @@ -5,7 +5,7 @@ using ZeroLevel.Services.Serialization; namespace ZeroLevel.DocumentObjectModel.Flow { /// - /// Параграф + /// Paragraph /// public class Paragraph : ContentElement diff --git a/ZeroLevel/Services/DOM/Model/Flow/Section.cs b/ZeroLevel/Services/DOM/Model/Flow/Section.cs index 40f889e..1b7b412 100644 --- a/ZeroLevel/Services/DOM/Model/Flow/Section.cs +++ b/ZeroLevel/Services/DOM/Model/Flow/Section.cs @@ -5,7 +5,7 @@ using ZeroLevel.Services.Serialization; namespace ZeroLevel.DocumentObjectModel.Flow { /// - /// Логически завершенный информационный блок + /// Document block /// public class Section : ContentElement diff --git a/ZeroLevel/Services/DOM/Model/Flow/Video.cs b/ZeroLevel/Services/DOM/Model/Flow/Video.cs index bd198be..fa1c9ca 100644 --- a/ZeroLevel/Services/DOM/Model/Flow/Video.cs +++ b/ZeroLevel/Services/DOM/Model/Flow/Video.cs @@ -8,11 +8,11 @@ namespace ZeroLevel.DocumentObjectModel.Flow { public SourceType Source { get; set; } /// - /// Название + /// Title /// public string Title; /// - /// Ссылка или идентификатор вложения + /// Link or Attachment ID /// public string Identifier; diff --git a/ZeroLevel/Services/DOM/Model/FlowContent.cs b/ZeroLevel/Services/DOM/Model/FlowContent.cs index 5c3e412..8ac0a97 100644 --- a/ZeroLevel/Services/DOM/Model/FlowContent.cs +++ b/ZeroLevel/Services/DOM/Model/FlowContent.cs @@ -7,9 +7,6 @@ namespace ZeroLevel.DocumentObjectModel public class FlowContent : ContentElement { - /// - /// Содержимое - /// public List
Sections = new List
(); public FlowContent() : diff --git a/ZeroLevel/Services/DOM/Model/Header.cs b/ZeroLevel/Services/DOM/Model/Header.cs index 3b8b2ec..5f3988f 100644 --- a/ZeroLevel/Services/DOM/Model/Header.cs +++ b/ZeroLevel/Services/DOM/Model/Header.cs @@ -24,21 +24,9 @@ namespace ZeroLevel.DocumentObjectModel #endregion #region Fields - /// - /// Название - /// public string Name; - /// - /// Значение - /// public string Value; - /// - /// Тип - /// public string Type; - /// - /// Дополнительная информация - /// public string Tag; #endregion diff --git a/ZeroLevel/Services/DOM/Model/Identifier.cs b/ZeroLevel/Services/DOM/Model/Identifier.cs index 4ad20d8..b8c81e2 100644 --- a/ZeroLevel/Services/DOM/Model/Identifier.cs +++ b/ZeroLevel/Services/DOM/Model/Identifier.cs @@ -10,17 +10,15 @@ namespace ZeroLevel.DocumentObjectModel #region Fields /// - /// Версия документа + /// Version /// public int Version; /// - /// Идентификатор по дате выхода, дает возможность идентифицировать - /// последнюю полученную по запросу новость, для последующих запросов - /// обновлений + /// Timestamp ID /// - public string Timestamp; + public long Timestamp; /// - /// Идентификатор по дате выхода с масштабированием до дня (20161024) + /// Label with day accurcy /// public string DateLabel; #endregion @@ -29,14 +27,14 @@ namespace ZeroLevel.DocumentObjectModel public void Serialize(IBinaryWriter writer) { writer.WriteInt32(this.Version); - writer.WriteString(this.Timestamp); + writer.WriteLong(this.Timestamp); writer.WriteString(this.DateLabel); } public void Deserialize(IBinaryReader reader) { this.Version = reader.ReadInt32(); - this.Timestamp = reader.ReadString(); + this.Timestamp = reader.ReadLong(); this.DateLabel = reader.ReadString(); } #endregion diff --git a/ZeroLevel/Services/DOM/Model/Priority.cs b/ZeroLevel/Services/DOM/Model/Priority.cs index 451d1a2..c374912 100644 --- a/ZeroLevel/Services/DOM/Model/Priority.cs +++ b/ZeroLevel/Services/DOM/Model/Priority.cs @@ -3,21 +3,13 @@ using System.ComponentModel; namespace ZeroLevel.DocumentObjectModel { - public enum Priority : Int32 + public enum Priority + : Int32 { - /// - /// Обычный - /// [Description("Normal")] Normal = 0, - /// - /// Срочный - /// [Description("Express")] Express = 1, - /// - /// Молния - /// [Description("Flash")] Flash = 2 } diff --git a/ZeroLevel/Services/DOM/Model/Tag.cs b/ZeroLevel/Services/DOM/Model/Tag.cs index be59820..eba21d3 100644 --- a/ZeroLevel/Services/DOM/Model/Tag.cs +++ b/ZeroLevel/Services/DOM/Model/Tag.cs @@ -6,13 +6,7 @@ namespace ZeroLevel.DocumentObjectModel IBinarySerializable { #region Fields - /// - /// Название - /// public string Name; - /// - /// Значение - /// public string Value; #endregion diff --git a/ZeroLevel/Services/DOM/Model/TagMetadata.cs b/ZeroLevel/Services/DOM/Model/TagMetadata.cs index 3910679..139f889 100644 --- a/ZeroLevel/Services/DOM/Model/TagMetadata.cs +++ b/ZeroLevel/Services/DOM/Model/TagMetadata.cs @@ -19,19 +19,18 @@ namespace ZeroLevel.DocumentObjectModel #region Fields /// - /// Упоминаемые места + /// Placec (city, country, etc) /// public List Places; /// - /// Упоминаемые компании + /// Companies /// public List Companies; /// - /// Упоминаемые персоны + /// Persons /// public List Persons; - /// - /// Ключевые слова + /// Keywords /// public List Keywords; #endregion diff --git a/ZeroLevel/Services/DOM/Services/ContentBuilder.cs b/ZeroLevel/Services/DOM/Services/ContentBuilder.cs index 65ef152..52031ac 100644 --- a/ZeroLevel/Services/DOM/Services/ContentBuilder.cs +++ b/ZeroLevel/Services/DOM/Services/ContentBuilder.cs @@ -236,14 +236,12 @@ namespace DOM.Services private void RaiseIncorrectTypeException(ContentElementType received, ContentElementType expected) { - throw new InvalidCastException(string.Format("Type {0} received instead of {1}", - received.ToString(), expected.ToString())); + throw new InvalidCastException($"Type {received} received instead of {expected}"); } private void RaiseIncorrectContainerType(ContentElementType containerType, ContentElementType elementType) { - throw new Exception(string.Format("Type {0} can not be written to a container of type {1}", - elementType.ToString(), containerType.ToString())); + throw new Exception($"Type {elementType} can not be written to a container of type {containerType}"); } private void ReduceContainers() @@ -278,7 +276,7 @@ namespace DOM.Services LeaveRow(); break; default: - throw new Exception(string.Format("Uncknown container type {0}", current.Type.ToString())); + throw new Exception($"Uncknown container type {current.Type}"); } } } @@ -463,7 +461,7 @@ namespace DOM.Services WriteElement(column); } - public void WriteText(ZeroLevel.DocumentObjectModel.Flow.Text text) + public void WriteText(Text text) { if (text == null) { @@ -473,15 +471,15 @@ namespace DOM.Services } public void WriteText(string text) { - WriteElement(new ZeroLevel.DocumentObjectModel.Flow.Text(text)); + WriteElement(new Text(text)); } public void WriteText(string text, TextStyle style) { - WriteElement(new ZeroLevel.DocumentObjectModel.Flow.Text(text) { Style = style }); + WriteElement(new Text(text) { Style = style }); } public void WriteHeader(string text) { - WriteElement(new ZeroLevel.DocumentObjectModel.Flow.Text(text) { Style = new TextStyle { Size = TextSize.MediumHeader, Formatting = TextFormatting.None } }); + WriteElement(new Text(text) { Style = new TextStyle { Size = TextSize.MediumHeader, Formatting = TextFormatting.None } }); } public void WriteQuote(Quote quote) { diff --git a/ZeroLevel/Services/DOM/Services/DocumentContentReader.cs b/ZeroLevel/Services/DOM/Services/DocumentContentReader.cs index 91161fa..cc2005d 100644 --- a/ZeroLevel/Services/DOM/Services/DocumentContentReader.cs +++ b/ZeroLevel/Services/DOM/Services/DocumentContentReader.cs @@ -192,12 +192,12 @@ namespace DOM.Services reader.LeaveHeaders(doc.DescriptiveMetadata.Headers); reader.LeaveDescriptioveBlock(doc.DescriptiveMetadata); - reader.EnterAsides(doc.Aside); - for (int i = 0; i < doc.Aside.Count; i++) + reader.EnterAsides(doc.Attachments); + for (int i = 0; i < doc.Attachments.Count; i++) { - reader.ReadAside(doc.Aside[i], i); + reader.ReadAside(doc.Attachments[i], i); } - reader.LeaveAsides(doc.Aside); + reader.LeaveAsides(doc.Attachments); reader.EnterAssotiations(doc.Assotiations); for (int i = 0; i < doc.Assotiations.Count; i++) diff --git a/ZeroLevel/Services/DependencyInjection/Container.cs b/ZeroLevel/Services/DependencyInjection/Container.cs index 8cb8316..17516f6 100644 --- a/ZeroLevel/Services/DependencyInjection/Container.cs +++ b/ZeroLevel/Services/DependencyInjection/Container.cs @@ -84,14 +84,14 @@ namespace ZeroLevel.Patterns.DependencyInjection private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim(); /// - /// Маппинг контракт - резрешения + /// Map - contract - dependency resolving /// private readonly Dictionary> _resolvingMap = new Dictionary>(); private readonly object _constructorCacheeLocker = new object(); /// - /// Кэш данных о контрукторах типа + /// Types constructors cache /// private readonly Dictionary> _constructorCachee = new Dictionary>(); @@ -99,11 +99,11 @@ namespace ZeroLevel.Patterns.DependencyInjection #region Private /// - /// Создание экземпляра объекта по указанному разрешению зависимости + /// Creating an instance of an object at the specified dependency resolution /// - /// Метаданные разрешения зависимости - /// Аргументы конструктора - /// Экземпляр объекта + /// Dependency resolving metadata + /// Ctor args + /// Instance private object MakeResolving(ResolveTypeInfo resolveType, object[] args, bool compose = true) { Type instanceType = resolveType.ImplementationType; @@ -127,12 +127,12 @@ namespace ZeroLevel.Patterns.DependencyInjection return sessionInstance; } /// - /// Создание экземпляра объекта по указанному разрешению зависимости, для обобщенного типа контракта + /// Creating an instance of the object at the specified dependency resolution, for a generic type of contract /// - /// Метаданные разрешения зависимости - /// Обобщенный тип контракта - /// Аргументы конструктора - /// Экземпляр объекта + /// Dependency resolving metadata + /// Generic contract + /// Ctor args + /// Instance private object MakeGenericResolving(ResolveTypeInfo resolveType, Type genericType, object[] args, bool compose = true) { if (null == resolveType.GenericCachee) @@ -171,31 +171,31 @@ namespace ZeroLevel.Patterns.DependencyInjection return sessionInstance; } /// - /// Сбор свойств типа помеченных аттрибутом разрешения зависимости + /// Collecting properties of the type marked with attribute dependency resolution /// - /// Тип - /// Список свойств отмеченных аттрибутом Resolve + /// Type + /// List of properties marked with "Resolve" attribute private static IEnumerable CollectResolvingProperties(Type type) { return type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy). Where(p => p.GetCustomAttribute() != null); } /// - /// Сбор полей типа помеченных аттрибутом разрешения зависимости + /// Collecting fields of type marked with an attribute of dependency resolution /// - /// Тип - /// Список полей отмеченных аттрибутом Resolve + /// Type + /// List of properties marked with "Resolve" attribute private static IEnumerable CollectResolvingFields(Type type) { return type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy). Where(p => p.GetCustomAttribute() != null); } /// - /// Поиск разрешения зависимости + /// Search for dependency resolution /// - /// Тип контракта - /// Имя разрешения зависимости - /// Переопределенный тип контракта + /// Contract + /// Dependency name + /// Redefined contract type /// private ResolveTypeInfo FindResolving(Type type, string resolveName, Type contractType) { @@ -227,15 +227,14 @@ namespace ZeroLevel.Patterns.DependencyInjection _rwLock.ExitReadLock(); } } - throw new KeyNotFoundException(string.Format("Не удалось разрешить зависимость для типа {0} по ключу '{1}'", - type.FullName, resolveName)); + throw new KeyNotFoundException($"Can't resolve dependency by type '{type.FullName}' and dependency name '{resolveName}'"); } /// - /// Разрешение зависимости по аттрибуту Resolve + /// Resolving dependency on attribute "Resolve /// - /// Тип контракта - /// Аттрибут - /// Экземпляр объекта + /// Contract + /// Resolve attribute + /// Instance private object MakeInstanceBy(Type type, ResolveAttribute resolveAttribute) { var is_generic = false; @@ -256,16 +255,14 @@ namespace ZeroLevel.Patterns.DependencyInjection } catch (Exception ex) { - throw new Exception( - string.Format("Не удалось создать экземпляр типа {0} для разрешения зависимости типа {1} по ключу {2}", - type.FullName, type.FullName, resolveAttribute?.ResolveName), ex); + throw new Exception($"Can't create type '{type.FullName}' instance for contract type {type.FullName}. Dependency key: '{resolveAttribute?.ResolveName}'", ex); } } /// - /// Сбор интерфейсов и абстрактных классов от которых унаследован тип + /// Collection of interfaces and abstract classes from which the type is inherited /// - /// Тип - /// Список интерфейсов и абстрактных классов + /// Type + /// List of interfaces and abstract classes private static IEnumerable GetInterfacesAndAbstracts(Type sourceType) { var interfaces = sourceType.GetInterfaces().ToList(); @@ -279,10 +276,10 @@ namespace ZeroLevel.Patterns.DependencyInjection return interfaces; } /// - /// Получение списка метаданных по конструкторам типа + /// Getting a list of metadata by type constructors /// - /// Тип - /// Метаданные о конструкторах типа + /// Type + /// Metadata type constructors private IEnumerable GetConstructors(Type type) { lock (_constructorCacheeLocker) @@ -301,11 +298,11 @@ namespace ZeroLevel.Patterns.DependencyInjection return _constructorCachee[type]; } /// - /// Создание экземпляра объекта, в том числе с непубличными конструкторами + /// Creating an instance of an object, including with non-public constructors /// - /// Тип - /// Аргументы конструктора - /// Экземпляр типа + /// Type + /// Ctor args + /// Instance private object MakeInstance(Type type, object[] args) { ConstructorInfo constructor = null; @@ -331,10 +328,10 @@ namespace ZeroLevel.Patterns.DependencyInjection } } /// - /// Регистрация разрешения зависимости + /// Dependency resolution registration /// - /// Тип контракта - /// Метаданные разрешения + /// Contract + /// Dependency resolving metadata private void Register(Type contractType, ResolveTypeInfo resolveType) { try @@ -357,14 +354,12 @@ namespace ZeroLevel.Patterns.DependencyInjection if (resolveType.IsDefault && _resolvingMap[contractType].Any(it => it.IsDefault)) { - throw new Exception( - string.Format("Default resolve type already has been defined. Contract: {0}", contractType.FullName)); + throw new Exception($"Default resolve type already has been defined. Contract: {contractType.FullName}"); } if (_resolvingMap[contractType]. Any(it => it.ResolveKey.Equals(resolveType.ResolveKey, StringComparison.OrdinalIgnoreCase))) { - throw new Exception( - string.Format("Resolve type with the same name '{0}' already has been defined. Contract: {1}", resolveType.ResolveKey, contractType.FullName)); + throw new Exception($"Resolve type with the same name '{resolveType.ResolveKey}' already has been defined. Contract: { contractType.FullName}"); } } try @@ -590,10 +585,10 @@ namespace ZeroLevel.Patterns.DependencyInjection #region Register instance /// - /// Регистрация готового экземпляра (синглтон) + /// Register singletone /// - /// Тип контракта - /// Экземпляр + /// Contract + /// Instance public void Register(TContract implementation) { var resolveType = new ResolveTypeInfo @@ -961,8 +956,7 @@ namespace ZeroLevel.Patterns.DependencyInjection { var resolve = GetResolvedType(type, resolveName); if (null == resolve.Item1) - throw new KeyNotFoundException(string.Format("Can'r resolve type {0} on key '{1}'", - type.FullName, resolveName)); + throw new KeyNotFoundException($"Can'r resolve type {type.FullName} on key '{resolveName}'"); // Detect instance type try { @@ -974,9 +968,7 @@ namespace ZeroLevel.Patterns.DependencyInjection } catch (Exception ex) { - throw new Exception( - string.Format("Can't create instance for type {0} for resolved dependency {1} by key {2}", - type.FullName, type.FullName, resolveName), ex); + throw new Exception($"Can't create instance for type {type.FullName} for resolved dependency {type.FullName} by key {resolveName}", ex); } } #endregion @@ -1069,8 +1061,7 @@ namespace ZeroLevel.Patterns.DependencyInjection catch (Exception ex) { Log.SystemWarning( - string.Format("Не удалось создать экземпляр типа {0} для разрешения зависимости типа {1} по ключу {2}", - type.FullName, type.FullName, resolveName), ex); + $"Can't create type '{type.FullName}' instance for resolve dependency with contract type '{type.FullName}' and dependency name '{resolveName}'", ex); } result = null; return false; @@ -1079,7 +1070,7 @@ namespace ZeroLevel.Patterns.DependencyInjection #region Composition /// - /// Заполнение полей и свойств объекта отмеченных флагом автоподставновки значений из параметров контейнера + /// Filling in the fields and properties of an object with auto-set values flagged from the container parameters /// private void FillParametrizedFieldsAndProperties(object instance) { @@ -1165,7 +1156,10 @@ namespace ZeroLevel.Patterns.DependencyInjection Compose(instanse, recursive); return true; } - catch { } + catch (Exception ex) + { + Log.SystemError(ex, $"[Container] TryCompose error. Instance: '{instanse?.GetType()?.FullName ?? string.Empty}'. Recursive: {recursive}"); + } return false; } #endregion @@ -1184,7 +1178,10 @@ namespace ZeroLevel.Patterns.DependencyInjection { (item.SharedInstance as IDisposable)?.Dispose(); } - catch { } + catch (Exception ex) + { + Log.SystemError(ex, $"[Container] Singletone dispose error. Instance: '{item?.GetType()?.FullName ?? string.Empty}'"); + } if (item.GenericInstanceCachee != null) { foreach (var gitem in item.GenericInstanceCachee.Values) @@ -1193,12 +1190,19 @@ namespace ZeroLevel.Patterns.DependencyInjection { (gitem as IDisposable)?.Dispose(); } - catch { } + catch(Exception ex) + { + Log.SystemError(ex, $"[Container] Generic singletone dispose error. Instance: '{gitem?.GetType()?.FullName ?? string.Empty}'"); + } } } } } } + catch (Exception ex) + { + Log.SystemError(ex, $"[Container] Dispose error"); + } finally { _rwLock.ExitWriteLock(); diff --git a/ZeroLevel/Services/DependencyInjection/Contracts/ICompositionProvider.cs b/ZeroLevel/Services/DependencyInjection/Contracts/ICompositionProvider.cs index fcceadc..5c8f154 100644 --- a/ZeroLevel/Services/DependencyInjection/Contracts/ICompositionProvider.cs +++ b/ZeroLevel/Services/DependencyInjection/Contracts/ICompositionProvider.cs @@ -1,21 +1,21 @@ namespace ZeroLevel.Patterns.DependencyInjection { /// - /// Интерфейс с методами проведения композиций + /// Provides object composition /// public interface ICompositionProvider { #region Composition /// - /// Композиция, выполняет подстановку зарегистрированных контрактов в полях и свойствах объекта + /// Object compositions, insert contract implementation /// - /// Инстанс объекта + /// Object instance void Compose(object instanse, bool recursive = true); /// - /// Безопасная композиция, выполняет подстановку зарегистрированных контрактов в полях и свойствах объекта + /// Object compositions, insert contract implementation /// - /// Инстанс объекта - /// /// false - при сбое в попытке композиции объекта + /// Object instance + /// /// false if composition fault bool TryCompose(object instanse, bool recursive = true); #endregion } diff --git a/ZeroLevel/Services/DependencyInjection/Contracts/IContainerInstanceRegister.cs b/ZeroLevel/Services/DependencyInjection/Contracts/IContainerInstanceRegister.cs index 11214f9..e99397d 100644 --- a/ZeroLevel/Services/DependencyInjection/Contracts/IContainerInstanceRegister.cs +++ b/ZeroLevel/Services/DependencyInjection/Contracts/IContainerInstanceRegister.cs @@ -3,37 +3,37 @@ namespace ZeroLevel.Patterns.DependencyInjection { /// - /// Интерфейс с методами регистрации зависимостей с явным указанием экземпляров - /// (синглтон) + /// Methods for register contact implementations + /// (singletone) /// public interface IContainerInstanceRegister { #region Register instance /// - /// Регистрация готового экземпляра (синглтон) + /// Register instance for contract . (singletone) /// - /// Тип контракта - /// Экземпляр + /// Contract + /// Instance void Register(TContract implementation); /// - /// Регистрация готового экземпляра (синглтон) + /// Register instance for contract . (singletone) /// - /// Тип контракта - /// Экземпляр - /// Имя разрешения зависимости + /// Contract + /// Instance + /// Dependency name void Register(TContract implementation, string resolveName); /// - /// Регистрация готового экземпляра (синглтон) + /// Register instance for contract (singletone) /// - /// Тип контракта - /// Экземпляр + /// Contract + /// Instance void Register(Type contractType, object implementation); /// - /// Регистрация готового экземпляра (синглтон) + /// Register instance for contract (singletone) /// - /// Тип контракта - /// Имя разрешения зависимости - /// Экземпляр + /// Contract + /// Dependency name + /// Instance void Register(Type contractType, string resolveName, object implementation); #endregion } diff --git a/ZeroLevel/Services/DependencyInjection/Contracts/IContainerRegister.cs b/ZeroLevel/Services/DependencyInjection/Contracts/IContainerRegister.cs index 3fcee5f..75a00a8 100644 --- a/ZeroLevel/Services/DependencyInjection/Contracts/IContainerRegister.cs +++ b/ZeroLevel/Services/DependencyInjection/Contracts/IContainerRegister.cs @@ -3,293 +3,293 @@ namespace ZeroLevel.Patterns.DependencyInjection { /// - /// Интерфейс с методами регистрации зависимостей с указанием типов контракта и зависимости - /// (синглтоны и мультитоны) + /// Methods for register contact resolvings + /// (singletones and multitones) /// public interface IContainerRegister : IDisposable { #region Register /// - /// Регистрация разрешения зависимости + /// Dependency resolution registration /// - /// Тип контракта - /// Тип разрешения + /// Contract + /// Dependency resolution void Register(); /// - /// Регистрация разрешения зависимости + /// Dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости + /// Contract + /// Dependency resolution + /// Dependency name void Register(string resolveName); /// - /// Регистрация разрешения зависимости + /// Dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// true - для синглтонов + /// Contract + /// Dependency resolution + /// true - for singletone void Register(bool shared); /// - /// Регистрация разрешения зависимости + /// Dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// true - для синглтонов + /// Contract + /// Dependency resolution + /// Dependency name + /// true - for singletone void Register(string resolveName, bool shared); /// - /// Регистрация разрешения зависимости + /// Dependency resolution registration /// - /// Тип контракта - /// Тип разрешения + /// Contract + /// Dependency resolution void Register(Type contractType, Type implementationType); /// - /// Регистрация разрешения зависимости + /// Dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости + /// Contract + /// Dependency resolution + /// Dependency name void Register(Type contractType, Type implementationType, string resolveName); /// - /// Регистрация разрешения зависимости + /// Dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// true - для синглтонов + /// Contract + /// Dependency resolution + /// true - for singletone void Register(Type contractType, Type implementationType, bool shared); /// - /// Регистрация разрешения зависимости + /// Dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// true - для синглтонов + /// Contract + /// Dependency resolution + /// Dependency name + /// true - for singletone void Register(Type contractType, Type implementationType, string resolveName, bool shared); #endregion #region Register with parameters /// - /// Регистрация разрешения зависимости с указанием параметров конструктора + /// Dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// Аргументы конструктора + /// Contract + /// Dependency resolution + /// Ctor args void ParameterizedRegister(object[] constructorParameters); /// - /// Регистрация разрешения зависимости с указанием параметров конструктора + /// Dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// Аргументы конструктора + /// Contract + /// Dependency resolution + /// Dependency name + /// Ctor args void ParameterizedRegister(string resolveName, object[] constructorParameters); /// - /// Регистрация разрешения зависимости с указанием параметров конструктора + /// Dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// true - для синглтонов - /// Аргументы конструктора + /// Contract + /// Dependency resolution + /// true - for singletone + /// Ctor args void ParameterizedRegister(bool shared, object[] constructorParameters); /// - /// Регистрация разрешения зависимости с указанием параметров конструктора + /// Dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// true - для синглтонов - /// Аргументы конструктора + /// Contract + /// Dependency resolution + /// Dependency name + /// true - for singletone + /// Ctor args void ParameterizedRegister(string resolveName, bool shared, object[] constructorParameters); /// - /// Регистрация разрешения зависимости с указанием параметров конструктора + /// Dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// Аргументы конструктора + /// Contract + /// Dependency resolution + /// Ctor args void ParameterizedRegister(Type contractType, Type implementationType, object[] constructorParameters); /// - /// Регистрация разрешения зависимости с указанием параметров конструктора + /// Dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// Аргументы конструктора + /// Contract + /// Dependency resolution + /// Dependency name + /// Ctor args void ParameterizedRegister(Type contractType, Type implementationType, string resolveName, object[] constructorParameters); /// - /// Регистрация разрешения зависимости с указанием параметров конструктора + /// Dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// true - для синглтонов - /// Аргументы конструктора + /// Contract + /// Dependency resolution + /// true - for singletone + /// Ctor args void ParameterizedRegister(Type contractType, Type implementationType, bool shared, object[] constructorParameters); /// - /// Регистрация разрешения зависимости с указанием параметров конструктора + /// Dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// true - для синглтонов - /// Аргументы конструктора + /// Contract + /// Dependency resolution + /// Dependency name + /// true - for singletone + /// Ctor args void ParameterizedRegister(Type contractType, Type implementationType, string resolveName, bool shared, object[] constructorParameters); #endregion #region Safe register /// - /// Безопасная регистрация разрешения зависимости + /// Safe dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// Error handler + /// true - registration successfully completed bool TryRegister(Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости + /// Safe dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// Dependency name + /// Error handler + /// true - registration successfully completed bool TryRegister(string resolveName, Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости + /// Safe dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// true - для синглтонов - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// true - for singletone + /// Error handler + /// true - registration successfully completed bool TryRegister(bool shared, Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости + /// Safe dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// true - для синглтонов - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// Dependency name + /// true - for singletone + /// Error handler + /// true - registration successfully completed bool TryRegister(string resolveName, bool shared, Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости + /// Safe dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// Error handler + /// true - registration successfully completed bool TryRegister(Type contractType, Type implementationType, Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости + /// Safe dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// Dependency name + /// Error handler + /// true - registration successfully completed bool TryRegister(Type contractType, Type implementationType, string resolveName, Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости + /// Safe dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// true - для синглтонов - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// true - for singletone + /// Error handler + /// true - registration successfully completed bool TryRegister(Type contractType, Type implementationType, bool shared, Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости + /// Safe dependency resolution registration /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// true - для синглтонов - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// Dependency name + /// true - for singletone + /// Error handler + /// true - registration successfully completed bool TryRegister(Type contractType, Type implementationType, string resolveName, bool shared, Action fallback = null); #endregion #region Safe register with parameters /// - /// Безопасная регистрация разрешения зависимости с указанием параметров конструктора + /// Safe dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// Аргументы конструктора - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// Ctor args + /// Error handler + /// true - registration successfully completed bool TryParameterizedRegister(object[] constructorParameters, Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости с указанием параметров конструктора + /// Safe dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// Аргументы конструктора - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// Dependency name + /// Ctor args + /// Error handler + /// true - registration successfully completed bool TryParameterizedRegister(string resolveName, object[] constructorParameters, Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости с указанием параметров конструктора + /// Safe dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// true - для синглтонов - /// Аргументы конструктора - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// true - for singletone + /// Ctor args + /// Error handler + /// true - registration successfully completed bool TryParameterizedRegister(bool shared, object[] constructorParameters, Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости с указанием параметров конструктора + /// Safe dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// true - для синглтонов - /// Аргументы конструктора - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// Dependency name + /// true - for singletone + /// Ctor args + /// Error handler + /// true - registration successfully completed bool TryParameterizedRegister(string resolveName, bool shared, object[] constructorParameters, Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости с указанием параметров конструктора + /// Safe dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// Аргументы конструктора - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// Ctor args + /// Error handler + /// true - registration successfully completed bool TryParameterizedRegister(Type contractType, Type implementationType, object[] constructorParameters, Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости с указанием параметров конструктора + /// Safe dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// Аргументы конструктора - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// Dependency name + /// Ctor args + /// Error handler + /// true - registration successfully completed bool TryParameterizedRegister(Type contractType, Type implementationType, string resolveName, object[] constructorParameters, Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости с указанием параметров конструктора + /// Safe dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// true - для синглтонов - /// Аргументы конструктора - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// true - for singletone + /// Ctor args + /// Error handler + /// true - registration successfully completed bool TryParameterizedRegister(Type contractType, Type implementationType, bool shared, object[] constructorParameters, Action fallback = null); /// - /// Безопасная регистрация разрешения зависимости с указанием параметров конструктора + /// Safe dependency resolution registration with constructor parameters /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// true - для синглтонов - /// Аргументы конструктора - /// Обработчик исключения - /// true - в случае успешной регистрации + /// Contract + /// Dependency resolution + /// Dependency name + /// true - for singletone + /// Ctor args + /// Error handler + /// true - registration successfully completed bool TryParameterizedRegister(Type contractType, Type implementationType, string resolveName, bool shared, object[] constructorParameters, Action fallback = null); #endregion } diff --git a/ZeroLevel/Services/DependencyInjection/Contracts/IParameterStorage.cs b/ZeroLevel/Services/DependencyInjection/Contracts/IParameterStorage.cs index c01be96..04d7006 100644 --- a/ZeroLevel/Services/DependencyInjection/Contracts/IParameterStorage.cs +++ b/ZeroLevel/Services/DependencyInjection/Contracts/IParameterStorage.cs @@ -3,69 +3,65 @@ namespace ZeroLevel.Patterns.DependencyInjection { /// - /// Интерфейс с методами для реализации хранения параметров - /// (хранилище ключ-значение, где в качестве ключа используется сущность типа string, а в качестве значения объект любого типа) + /// DI parameters stogare (string key and anytype value) /// public interface IParameterStorage { #region IEverythingStorage /// - /// Сохранение параметра + /// Save parameter /// - /// Тип параметра - /// Ключ - /// Значение параметра + /// Parameter type + /// Key + /// Parameter value void Save(string key, T value); /// - /// Сохранение или обновление параметра + /// Save or update parameter /// - /// Тип параметра - /// Ключ - /// Значение параметра + /// Parameter type + /// Key + /// Parameter value void SaveOrUpdate(string key, T value); /// - /// Безопасное сохранение параметра + /// Safe save parameter /// - /// Тип параметра - /// Ключ - /// Значение параметра - /// true - в случае успеха + /// Parameter type + /// Key + /// Parameter value bool TrySave(string key, T value); /// - /// Удаление параметра + /// Remove parameter by key /// - /// Тип параметра - /// Ключ + /// Parameter type + /// Key void Remove(string key); /// - /// Безопасное удаление параметра + /// Safe remove parameter by key /// - /// Тип параметра - /// Ключ - /// true - в случае успеха + /// Parameter type + /// Key bool TryRemove(string key); /// - /// Запрос сохраненного параметра + /// Get parameter value by key /// - /// Тип параметра - /// Ключ - /// Значение параметра + /// Parameter type + /// Key + /// Parameter value T Get(string key); T GetOrDefault(string key); T GetOrDefault(string key, T defaultValue); /// - /// Запрос сохраненного параметра + /// Get parameter value by key /// - /// Тип параметра - /// Ключ - /// Значение параметра + /// Parameter type + /// Key + /// Parameter value object Get(Type type, string key); /// - /// Проверка наличия параметра с указанным именем + /// Check for parameter existence by key /// - /// Тип параметра - /// Ключ - /// Указывает наличие параметра с заданным именем + /// Parameter type + /// Key bool Contains(string key); #endregion } diff --git a/ZeroLevel/Services/DependencyInjection/Contracts/IPoolContainer.cs b/ZeroLevel/Services/DependencyInjection/Contracts/IPoolContainer.cs deleted file mode 100644 index 4cbbe7f..0000000 --- a/ZeroLevel/Services/DependencyInjection/Contracts/IPoolContainer.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; - -namespace ZeroLevel.Patterns.DependencyInjection -{ - /// - /// Интерфейс с методами для реализации паттерна пул объектов в контейнере - /// - public interface IPoolContainer - { - #region Register poolable dependencies - /// - /// Регистрация пула - /// - /// Тип контракта - /// Начальное количество объектов в пуле - /// Максимальное количество объектов в пуле (при -1 пул не ограничен) - void RegisterPool(int initialCount, int capacity); - /// - /// Регистрация разрешения зависимости - /// - /// Тип контракта - /// Тип разрешения - void RegisterPoolable(); - /// - /// Регистрация разрешения зависимости - /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - void RegisterPoolable(string resolveName); - /// - /// Регистрация разрешения зависимости - /// - /// Тип контракта - /// Тип разрешения - void RegisterPoolable(Type contractType, Type implementationType); - /// - /// Регистрация разрешения зависимости - /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - void RegisterPoolable(Type contractType, Type implementationType, string resolveName); - /// - /// Регистрация разрешения зависимости - /// - /// Тип контракта - /// Экземпляр - void RegisterPoolable(TContract implementation); - /// - /// Регистрация разрешения зависимости - /// - /// Тип контракта - /// Экземпляр - void RegisterPoolable(Type contractType, object implementation); - #endregion - - #region Register poolable parametrizied dependencies - /// - /// Регистрация разрешения зависимости с указанием параметров конструктора - /// - /// Тип контракта - /// Тип разрешения - /// Аргументы конструктора - void RegisterPoolableParametrizied(object[] constructorParameters); - /// - /// Регистрация разрешения зависимости с указанием параметров конструктора - /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// Аргументы конструктора - void RegisterPoolableParametrizied(string resolveName, object[] constructorParameters); - /// - /// Регистрация разрешения зависимости с указанием параметров конструктора - /// - /// Тип контракта - /// Тип разрешения - /// Аргументы конструктора - void RegisterPoolableParametrizied(Type contractType, Type implementationType, object[] constructorParameters); - /// - /// Регистрация разрешения зависимости с указанием параметров конструктора - /// - /// Тип контракта - /// Тип разрешения - /// Имя разрешения зависимости - /// Аргументы конструктора - void RegisterPoolableParametrizied(Type contractType, Type implementationType, string resolveName, object[] constructorParameters); - #endregion - } -} diff --git a/ZeroLevel/Services/DependencyInjection/Contracts/IResolver.cs b/ZeroLevel/Services/DependencyInjection/Contracts/IResolver.cs index ce42421..a1c2808 100644 --- a/ZeroLevel/Services/DependencyInjection/Contracts/IResolver.cs +++ b/ZeroLevel/Services/DependencyInjection/Contracts/IResolver.cs @@ -3,107 +3,107 @@ namespace ZeroLevel.Patterns.DependencyInjection { /// - /// Интерфейс с методами разрешений зависимостей + /// Dependency resolver /// public interface IResolver { #region Activator /// - /// Создание экземпляра объекта указанного типа + /// Creating an instance of an object of the specified type /// - /// Тип объекта - /// Имя разрешения зависимости - /// Экземпляр объекта + /// Contract or instance type + /// Dependency name + /// Instance T CreateInstance(string resolveName = ""); /// - /// Создание экземпляра объекта указанного типа + /// Creating an instance of an object of the specified type /// - /// Тип объекта - /// Аргументы конструктора - /// Имя разрешения зависимости - /// Экземпляр объекта + /// Contract or instance type + /// Ctor agrs + /// Dependency name + /// Instance T CreateInstance(object[] args, string resolveName = ""); /// - /// Создание экземпляра объекта указанного типа + /// Creating an instance of an object of the specified type /// - /// Тип объекта - /// Имя разрешения зависимости - /// Экземпляр объекта + /// Contract or instance type + /// Dependency name + /// Instance object CreateInstance(Type type, string resolveName = ""); /// - /// Создание экземпляра объекта указанного типа + /// Creating an instance of an object of the specified type /// - /// Тип объекта - /// Аргументы конструктора - /// Имя разрешения зависимости - /// Экземпляр объекта + /// Contract or instance type + /// Ctor agrs + /// Dependency name + /// Instance object CreateInstance(Type type, object[] args, string resolveName = ""); #endregion #region Resolving /// - /// Разрешение зависимости + /// Dependency resolve /// - /// Тип контракта - /// Указание провести композицию при построении объектов - /// Инстанс + /// Contract + /// Compose the object when true + /// Instance T Resolve(bool compose = true); /// - /// Разрешение зависимости + /// Dependency resolve /// - /// Тип контракта - /// Имя разрешения зависимости - /// Указание провести композицию при построении объектов - /// Инстанс + /// Contract + /// Dependency name + /// Compose the object when true + /// Instance T Resolve(string resolveName, bool compose = true); /// - /// Разрешение зависимости + /// Dependency resolve /// - /// Тип контракта - /// Аргументы конструктора - /// Указание провести композицию при построении объектов - /// Инстанс + /// Contract + /// Ctor agrs + /// Compose the object when true + /// Instance T Resolve(object[] args, bool compose = true); /// - /// Разрешение зависимости + /// Dependency resolve /// - /// Тип контракта - /// Имя разрешения зависимости - /// Аргументы конструктора - /// Указание провести композицию при построении объектов - /// Инстанс + /// Contract + /// Dependency name + /// Ctor agrs + /// Compose the object when true + /// Instance T Resolve(string resolveName, object[] args, bool compose = true); /// - /// Разрешение зависимости + /// Dependency resolve /// - /// Тип контракта - /// Указание провести композицию при построении объектов - /// Инстанс + /// Contract + /// Compose the object when true + /// Instance object Resolve(Type type, bool compose = true); /// - /// Разрешение зависимости + /// Dependency resolve /// - /// Тип контракта - /// Имя разрешения зависимости - /// Указание провести композицию при построении объектов - /// Инстанс + /// Contract + /// Dependency name + /// Compose the object when true + /// Instance object Resolve(Type type, string resolveName, bool compose = true); /// - /// Разрешение зависимости + /// Dependency resolve /// - /// Тип контракта - /// Аргументы конструктора - /// Указание провести композицию при построении объектов - /// Инстанс + /// Contract + /// Ctor agrs + /// Compose the object when true + /// Instance object Resolve(Type type, object[] args, bool compose = true); /// - /// Разрешение зависимости + /// Dependency resolve /// - /// Тип контракта - /// Имя разрешения зависимости - /// Аргументы конструктора - /// Указание провести композицию при построении объектов - /// Инстанс + /// Contract + /// Dependency name + /// Ctor agrs + /// Compose the object when true + /// Instance object Resolve(Type type, string resolveName, object[] args, bool compose = true); #endregion diff --git a/ZeroLevel/Services/DependencyInjection/Internal/ConstructorMetadata.cs b/ZeroLevel/Services/DependencyInjection/Internal/ConstructorMetadata.cs index eaac6c6..e98a6dc 100644 --- a/ZeroLevel/Services/DependencyInjection/Internal/ConstructorMetadata.cs +++ b/ZeroLevel/Services/DependencyInjection/Internal/ConstructorMetadata.cs @@ -6,7 +6,7 @@ using System.Reflection; namespace ZeroLevel.Patterns.DependencyInjection { /// - /// Метаданные конструктора + /// Constructor metadata /// internal class ConstructorMetadata { @@ -26,16 +26,16 @@ namespace ZeroLevel.Patterns.DependencyInjection var resolveAttribute = p.GetCustomAttribute(); var kind = (parameterAttribute != null) ? ConstructorParameterKind.Parameter : - (resolveAttribute != null) ? ConstructorParameterKind.Resolve : ConstructorParameterKind.None; + (resolveAttribute != null) ? ConstructorParameterKind.Dependency : ConstructorParameterKind.None; return new ConstructorParameter { Type = p.ParameterType, ParameterKind = kind, ParameterResolveName = (kind == ConstructorParameterKind.Parameter) ? parameterAttribute?.Name ?? p.Name : - (kind == ConstructorParameterKind.Resolve) ? resolveAttribute?.ResolveName : null, + (kind == ConstructorParameterKind.Dependency) ? resolveAttribute?.ResolveName : null, ParameterResolveType = (kind == ConstructorParameterKind.Parameter) ? parameterAttribute?.Type ?? p.ParameterType : - (kind == ConstructorParameterKind.Resolve) ? resolveAttribute?.ContractType ?? p.ParameterType : null, + (kind == ConstructorParameterKind.Dependency) ? resolveAttribute?.ContractType ?? p.ParameterType : null, IsNullable = IsNullable(p.ParameterType) }; }).ToList(); @@ -48,11 +48,11 @@ namespace ZeroLevel.Patterns.DependencyInjection return false; // value-type } /// - /// Определение, подходит ли конструктор под указанные аргументы + /// Determining whether the constructor is suitable for the specified arguments /// - /// Аргументы - /// Подготовленные массив аргументов для вызова конструктора - /// true - если конструктор можно вызвать с переданными аргументами + /// Arguments + /// Prepared arguments for constructor call + /// true - if the constructor can be called with the arguments passed public bool IsMatch(object[] args, out object[] parameters) { parameters = null; @@ -67,7 +67,7 @@ namespace ZeroLevel.Patterns.DependencyInjection case ConstructorParameterKind.Parameter: parameters[i] = _parent.Get(Parameters[i].ParameterResolveType, Parameters[i].ParameterResolveName); break; - case ConstructorParameterKind.Resolve: + case ConstructorParameterKind.Dependency: parameters[i] = _parent.Resolve(Parameters[i].ParameterResolveType, Parameters[i].ParameterResolveName); break; default: diff --git a/ZeroLevel/Services/DependencyInjection/Internal/ConstructorParameter.cs b/ZeroLevel/Services/DependencyInjection/Internal/ConstructorParameter.cs index dad1334..e8955e4 100644 --- a/ZeroLevel/Services/DependencyInjection/Internal/ConstructorParameter.cs +++ b/ZeroLevel/Services/DependencyInjection/Internal/ConstructorParameter.cs @@ -3,47 +3,47 @@ namespace ZeroLevel.Patterns.DependencyInjection { /// - /// Тип аргумента конструктора в контексте иньекции зависимостей + /// Constructor argument type /// internal enum ConstructorParameterKind { /// - /// Аргумент задается из переданных значений + /// Constant /// None, /// - /// Аргумент задается из параметров контейнера + /// DI parameter /// Parameter, /// - /// Аргумент задается разрешением зависимости + /// Dependency /// - Resolve + Dependency } /// - /// Метаданные для описания аргумента конструктора + /// Constructor argument metadata /// internal sealed class ConstructorParameter { /// - /// Тип аргумента в рамках DI + /// Argument DI-type /// public ConstructorParameterKind ParameterKind; /// - /// Тип для определения аргумента через DI + /// Argument contract type /// public Type ParameterResolveType; /// - /// Имя для определения аргумента через DI + /// Dependency name /// public string ParameterResolveName; /// - /// Флаг определяющий допустимость записи null в качестве значения аргумента + /// Allow null /// public bool IsNullable; /// - /// Тип аргумента + /// Argument CLR type /// public Type Type; } diff --git a/ZeroLevel/Services/DependencyInjection/Internal/IPoolable.cs b/ZeroLevel/Services/DependencyInjection/Internal/IPoolable.cs deleted file mode 100644 index 9428cca..0000000 --- a/ZeroLevel/Services/DependencyInjection/Internal/IPoolable.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ZeroLevel.Patterns.DependencyInjection -{ - public interface IPoolable - { - T Instance { get; } - void Cleanup(); - void Release(); - } -} diff --git a/ZeroLevel/Services/DependencyInjection/Internal/ResolveTypeInfo.cs b/ZeroLevel/Services/DependencyInjection/Internal/ResolveTypeInfo.cs index 0359813..c67a8b5 100644 --- a/ZeroLevel/Services/DependencyInjection/Internal/ResolveTypeInfo.cs +++ b/ZeroLevel/Services/DependencyInjection/Internal/ResolveTypeInfo.cs @@ -4,40 +4,40 @@ using System.Collections.Generic; namespace ZeroLevel.Patterns.DependencyInjection { /// - /// Метаданные разрешения зависимости + /// Dependency resolving metadata /// internal sealed class ResolveTypeInfo { /// - /// Разрешение зависимости по умолчанию + /// Default - without dependency name /// public bool IsDefault; /// - /// Создается только один экземпляр (в случае true) + /// Singletone when true /// public bool IsShared; /// - /// Тип инстанса (в том числе обобщенный) + /// Instance type (may be generic) /// public Type ImplementationType; /// - /// Ключ определения зависимости + /// Dependency resolving key /// public string ResolveKey; /// - /// Кэш экземпляра + /// Instance cache /// public object SharedInstance; /// - /// Кэш обобщенных типов + /// Generic types cahce /// public Dictionary GenericCachee; /// - /// Кэш обобщенных экземпляров + /// Generic instances cahce /// public Dictionary GenericInstanceCachee; /// - /// Параметры конструктора объекта + /// Constructor parameters /// public object[] ConstructorParameters; } diff --git a/ZeroLevel/Services/Drawing/TextPainter.cs b/ZeroLevel/Services/Drawing/TextPainter.cs index 2c26934..6e398bd 100644 --- a/ZeroLevel/Services/Drawing/TextPainter.cs +++ b/ZeroLevel/Services/Drawing/TextPainter.cs @@ -6,7 +6,7 @@ namespace ZeroLevel.Services.Drawing { public static class TextPainter { - #region Отрисовка текста вдоль линий + #region Drawing text along lines public static void DrawOnSegment(Graphics gr, Font font, PointF start_point, PointF end_point, diff --git a/ZeroLevel/Services/Extensions/ArrayExtensions.cs b/ZeroLevel/Services/Extensions/ArrayExtensions.cs index ae4c33b..097daf1 100644 --- a/ZeroLevel/Services/Extensions/ArrayExtensions.cs +++ b/ZeroLevel/Services/Extensions/ArrayExtensions.cs @@ -6,7 +6,7 @@ namespace ZeroLevel public static class ArrayExtensions { /// - /// Глубокое копирование массива + /// Deep copy array /// public static T[] DeepCopy(this T[] array) where T : ICloneable @@ -38,10 +38,8 @@ namespace ZeroLevel } } /// - /// Проверяет вхождение одного массива в другой + /// Checks whether one array is in another /// - /// Тиа элементов массивов - /// true - массив содержит указанный подмассив public static bool Contains(this T[] array, T[] candidate) { if (IsEmptyLocate(array, candidate)) diff --git a/ZeroLevel/Services/Extensions/CollectionComparsionExtensions.cs b/ZeroLevel/Services/Extensions/CollectionComparsionExtensions.cs index 7782f96..7957ff2 100644 --- a/ZeroLevel/Services/Extensions/CollectionComparsionExtensions.cs +++ b/ZeroLevel/Services/Extensions/CollectionComparsionExtensions.cs @@ -24,7 +24,7 @@ namespace ZeroLevel } /// - /// Проверяет на одинаковое содержание коллекции строк, в том числе по разному отсортированные + /// Checks for the same content of a collection of strings, including sorted in different ways /// public static bool StringEnumerableEquals(this IEnumerable A, IEnumerable B) { @@ -34,7 +34,7 @@ namespace ZeroLevel } /// - /// Проверяет на одинаковое содержание коллекций, в том числе по разному отсортированных + /// Checks for the same content of collections, including sorted in different ways /// public static bool NoOrderingEquals(this IEnumerable A, IEnumerable B) { @@ -51,7 +51,7 @@ namespace ZeroLevel } /// - /// Проверяет на одинаковое содержание коллекций + /// Checks for the same content collections /// public static bool OrderingEquals(this IEnumerable A, IEnumerable B) { @@ -85,7 +85,7 @@ namespace ZeroLevel return true; } /// - /// Расчет хеша для коллекции + /// Calculate hash for collection /// public static int GetEnumHashCode(this IEnumerable A) { diff --git a/ZeroLevel/Services/Extensions/DateTimeExtensions.cs b/ZeroLevel/Services/Extensions/DateTimeExtensions.cs index b677b09..40299e6 100644 --- a/ZeroLevel/Services/Extensions/DateTimeExtensions.cs +++ b/ZeroLevel/Services/Extensions/DateTimeExtensions.cs @@ -5,10 +5,8 @@ namespace ZeroLevel public static class DateTimeExtensions { /// - /// Огругляет дату до указанного масштаба - /// - /// Необходимость: округление дат при сохранении в модель, которая будет использоваться для SqlServer, - /// т.к. sqlserver не может точность - Datetime values are rounded to increments of .000, .003, or .007 seconds + /// Rounds the date to the specified scale. + /// Example: sqlserver - Datetime values are rounded to increments of .000, .003, or .007 seconds /// public static DateTime Truncate(this DateTime dateTime, TimeSpan timeSpan) { diff --git a/ZeroLevel/Services/Extensions/FPCommon.cs b/ZeroLevel/Services/Extensions/FPCommon.cs index 076a7f0..8ee5502 100644 --- a/ZeroLevel/Services/Extensions/FPCommon.cs +++ b/ZeroLevel/Services/Extensions/FPCommon.cs @@ -4,7 +4,7 @@ using System.Runtime.Serialization; namespace ZeroLevel.Services.Extensions { /// - /// Обобщенные возможности из ФП + /// FP /// public static class FPCommon { diff --git a/ZeroLevel/Services/Extensions/Monades.cs b/ZeroLevel/Services/Extensions/Monades.cs index 1206e12..3392056 100644 --- a/ZeroLevel/Services/Extensions/Monades.cs +++ b/ZeroLevel/Services/Extensions/Monades.cs @@ -2,9 +2,6 @@ namespace ZeroLevel { - /// - /// Сборник монад - /// public static class Monades { #region With diff --git a/ZeroLevel/Services/FileSystem/FSUtils.cs b/ZeroLevel/Services/FileSystem/FSUtils.cs index 280e8ce..c9aadcf 100644 --- a/ZeroLevel/Services/FileSystem/FSUtils.cs +++ b/ZeroLevel/Services/FileSystem/FSUtils.cs @@ -42,12 +42,12 @@ namespace ZeroLevel.Services.FileSystem } /// - /// Задает права доступа к каталогу для учетной записи + /// Sets the directory permissions for the account /// - /// Путь к каталогу - /// Аккаунт - /// Права доступа - /// Тип доступа + /// Directory path + /// Account + /// Access rights + /// Access type public static void SetupFolderPermission(string folderPath, string account, FileSystemRights right, AccessControlType controlType) { @@ -63,7 +63,7 @@ namespace ZeroLevel.Services.FileSystem private static string _invalid_path_characters = new string(Path.GetInvalidPathChars()); private static string _invalid_filename_characters = new string(Path.GetInvalidFileNameChars()); /// - /// Удаляет из переданного пути недопустимые символы + /// Removes invalid characters from the passed path /// public static string PathCorrection(string path) { @@ -82,7 +82,7 @@ namespace ZeroLevel.Services.FileSystem return new string(result, 0, index); } /// - /// Удаляет из переданного имени файла недопустимые символы + /// Removes invalid characters from the passed file name /// /// /// @@ -105,7 +105,7 @@ namespace ZeroLevel.Services.FileSystem #endregion /// - /// Выполняет проверку на доступность файла для обработки + /// Performs a file accessibility check for processing /// public static bool IsFileLocked(FileInfo file) { diff --git a/ZeroLevel/Services/FileSystem/FileArchive.cs b/ZeroLevel/Services/FileSystem/FileArchive.cs index a316588..e627dcc 100644 --- a/ZeroLevel/Services/FileSystem/FileArchive.cs +++ b/ZeroLevel/Services/FileSystem/FileArchive.cs @@ -227,20 +227,20 @@ namespace ZeroLevel.Services.FileSystem } while (_disposed == false); } /// - /// Сохранение текста в архив + /// Save text to archive /// - /// Текст - /// Имя файла в архиве (по умолчанию HH_mm_ss_fff_counter.{ext}) + /// Text + /// Archive file name (HH_mm_ss_fff_counter.{ext} by default) /// public void StoreText(string text, string subfolder_name = null, string file_name = null) { Apply(new StoreText(text, CreateArchiveFilePath(subfolder_name, file_name))); } /// - /// Сохранение указанного файла в архив + /// Saving the specified file to the archive /// - /// Путь к файлу - /// Имя файла в архиве (по умолчанию оригинальное имя файла) + /// File path + /// Archive file name (original file name by default) /// public void Store(string file_path, string subfolder_name = null, string file_name = null) { @@ -259,20 +259,20 @@ namespace ZeroLevel.Services.FileSystem } } /// - /// Сохранение данных из потока в архив + /// Saving data from stream to archive /// - /// Поток с данными для чтения - /// Имя файла в архиве (по умолчанию HH_mm_ss_fff_counter.{ext}) + /// Data stream for reading + /// Archive file name (HH_mm_ss_fff_counter.{ext} by default) /// public void Store(Stream stream, string subfolder_name = null, string file_name = null) { Apply(new StoreStream(stream, CreateArchiveFilePath(subfolder_name, file_name))); } /// - /// Сохранение данных в бинарном виде в архив + /// Saving data in binary form in the archive /// - /// Данные - /// Имя файла в архиве (по умолчанию HH_mm_ss_fff_counter.{ext}) + /// Data + /// Archive file name (HH_mm_ss_fff_counter.{ext} by default) /// public void StoreData(byte[] data, string subfolder_name = null, string file_name = null) { @@ -333,8 +333,7 @@ namespace ZeroLevel.Services.FileSystem if (Directory.Exists(path) == false) { Directory.CreateDirectory(path); - FSUtils.SetupFolderPermission(path, - string.Format("{0}\\{1}", Environment.UserDomainName, Environment.UserName), + FSUtils.SetupFolderPermission(path,$"{Environment.UserDomainName}\\{Environment.UserName}", FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify, AccessControlType.Allow); } @@ -398,31 +397,31 @@ namespace ZeroLevel.Services.FileSystem } } /// - /// Сохранение текста в архив + /// Save text to archive /// - /// Текст - /// Имя файла в архиве (по умолчанию HH_mm_ss_fff_counter.{ext}) + /// Text + /// Archive file name (HH_mm_ss_fff_counter.{ext} by default) /// public void StoreText(string text, string name = null) { Apply(new StoreText(text, CreateArchiveFilePath(name))); } /// - /// Сохранение указанного файла в архив + /// Saving the specified file to the archive /// - /// Путь к файлу - /// Имя файла в архиве (по умолчанию оригинальное имя файла) + /// File path + /// Archive file name (original file name by default) /// public void Store(string file_path, string name = null) { Apply(new StoreFile(file_path, CreateArchiveFilePath(name))); } /// - /// охранение указанного файла в архив, синхронно + /// Sync saving the specified file to the archive /// - /// - /// - /// + /// File path + /// Archive file name (original file name by default) + /// public void Store(string file_path, bool immediate, string name = null) { if (immediate) @@ -435,10 +434,10 @@ namespace ZeroLevel.Services.FileSystem } } /// - /// Сохранение данных из потока в архив + /// Saving data from stream to archive /// - /// Поток с данными для чтения - /// Имя файла в архиве (по умолчанию HH_mm_ss_fff_counter.{ext}) + /// Data stream for reading + /// Archive file name (HH_mm_ss_fff_counter.{ext} by default) /// public void Store(Stream stream, string name = null) { @@ -447,8 +446,8 @@ namespace ZeroLevel.Services.FileSystem /// /// Сохранение данных в бинарном виде в архив /// - /// Данные - /// Имя файла в архиве (по умолчанию HH_mm_ss_fff_counter.{ext}) + /// Data + /// Archive file name (HH_mm_ss_fff_counter.{ext} by default) /// public void StoreData(byte[] data, string name = null) { @@ -475,7 +474,7 @@ namespace ZeroLevel.Services.FileSystem { Directory.CreateDirectory(path); FSUtils.SetupFolderPermission(path, - string.Format("{0}\\{1}", Environment.UserDomainName, Environment.UserName), + $"{Environment.UserDomainName}\\{Environment.UserName}", FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify, AccessControlType.Allow); } diff --git a/ZeroLevel/Services/FileSystem/PeriodicFileSystemWatcher.cs b/ZeroLevel/Services/FileSystem/PeriodicFileSystemWatcher.cs index 2ec9689..905c574 100644 --- a/ZeroLevel/Services/FileSystem/PeriodicFileSystemWatcher.cs +++ b/ZeroLevel/Services/FileSystem/PeriodicFileSystemWatcher.cs @@ -72,7 +72,7 @@ namespace ZeroLevel.Services.FileSystem } catch (Exception ex) { - Log.SystemError(ex, "Сбой при попытке перемещения файла '{0}' во временный каталог '{1}'", file, _temporaryFolder); + Log.SystemError(ex, $"[PeriodicFileSystemWatcher] Failed to attempt to move file '{file}' to temporary directory '{_temporaryFolder}'"); continue; } Log.Debug($"[PeriodicFileSystemWatcher] Handle file {file}"); @@ -87,12 +87,12 @@ namespace ZeroLevel.Services.FileSystem } catch (Exception ex) { - Log.SystemError(ex, "Сбой при обработке входного каталога '{0}'", _sourceFolder); + Log.SystemError(ex, $"[PeriodicFileSystemWatcher] Failed to process input directory '{_sourceFolder}'"); } } /// - /// Перемещение файла во временный каталог + /// Moving a file to a temporary directory /// public string MoveToTemporary(string from) { @@ -110,8 +110,7 @@ namespace ZeroLevel.Services.FileSystem return tempFile; } /// - /// Разрешение коллизий в именах файлов во временном каталоге - /// (требуется если в источнике могут появляться файлы в разное время с одинаковыми именами) + /// Resolving collisions in filenames in the temporary directory /// private static string TrySolveCollision(string file) { @@ -141,7 +140,7 @@ namespace ZeroLevel.Services.FileSystem throw new ArgumentException("folder"); } /// - /// Получение списка файлов из входного каталога + /// Getting a list of files from the input directory /// public string[] GetFilesFromSource() { @@ -150,7 +149,7 @@ namespace ZeroLevel.Services.FileSystem return files; } /// - /// Сравнение названий файлов + /// File Name Comparison /// private static int FileNameSortCompare(string x, string y) { diff --git a/ZeroLevel/Services/Impersonation/IImpersonationExecutor.cs b/ZeroLevel/Services/Impersonation/IImpersonationExecutor.cs index ebf172e..8622116 100644 --- a/ZeroLevel/Services/Impersonation/IImpersonationExecutor.cs +++ b/ZeroLevel/Services/Impersonation/IImpersonationExecutor.cs @@ -3,7 +3,7 @@ namespace ZeroLevel.Services.Impersonation { /// - /// Интерфейс для классов исполняющих произвольный код от прав пользователя или процесса + /// Interface for classes executing code from user or process rights /// public interface IImpersonationExecutor { diff --git a/ZeroLevel/Services/Impersonation/Impersonation.cs b/ZeroLevel/Services/Impersonation/Impersonation.cs index dd369e6..d5e04ab 100644 --- a/ZeroLevel/Services/Impersonation/Impersonation.cs +++ b/ZeroLevel/Services/Impersonation/Impersonation.cs @@ -7,7 +7,7 @@ using System.Security.Principal; namespace ZeroLevel.Services.Impersonation { /// - /// Класс реализует перевод исполнения программы на права указанного пользователя + /// The class implements the translation of the program execution to the rights of the specified user. /// [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)] [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] @@ -17,20 +17,20 @@ namespace ZeroLevel.Services.Impersonation #region Private methods /// - /// Назначение текущему процессу прав от указанного процесса, путем копирования его токена + /// Assigning rights to the current process from the specified process, by copying its token /// - /// Указатель на процесс + /// Process pointer private void ImpersonateByProcess(IntPtr hProcess) { MySafeTokenHandle token; if (!ImpersonationNativeMethods.OpenProcessToken(hProcess, ImpersonationNativeMethods.TokenDesiredAccess.TOKEN_DUPLICATE, out token)) - throw new ApplicationException("Не удалось получить токен процесса. Win32 код ошибки: " + Marshal.GetLastWin32Error()); + throw new ApplicationException("Failed to get the process token. Win32 error code: " + Marshal.GetLastWin32Error()); ImpersonateToken(token); } /// - /// Метод назначает текущему процессу дубликат переданного токена + /// The method assigns a duplicate token to the current process. /// - /// Токен + /// Token private void ImpersonateToken(MySafeTokenHandle token) { MySafeTokenHandle tokenDuplicate; @@ -50,19 +50,19 @@ namespace ZeroLevel.Services.Impersonation } } else - throw new Exception("Не удалось создать дубликат указанного токена. Win32 код ошибки: " + Marshal.GetLastWin32Error()); + throw new Exception("Failed to create a duplicate of the specified token. Win32 error code: " + Marshal.GetLastWin32Error()); } } #endregion #region Public methods /// - /// Вход от имени указанного пользователя + /// Login as a specified user /// - /// Имя пользователя - /// Домен - /// Пароль - /// false - если не удалось выполнить вход по указанным данным + /// User name + /// User domain + /// User password + /// false - if failed to log in with the specified data public void ImpersonateByUser(String userName, String domain, String password) { MySafeTokenHandle token; @@ -111,9 +111,9 @@ namespace ZeroLevel.Services.Impersonation } } /// - /// Копирование прав указанного процесса + /// Copying the rights of the specified process /// - /// Идентификатор процесса + /// Process id public void ImpersonateByProcess(int ProcessID) { Process[] myProcesses = Process.GetProcesses(); @@ -129,7 +129,7 @@ namespace ZeroLevel.Services.Impersonation #endregion /// - /// При освобождении рессурсов вернем предыдущего пользователя + /// When releasing resources, we will return the previous user right /// public void Dispose() { diff --git a/ZeroLevel/Services/Impersonation/ImpersonationNativeMethods.cs b/ZeroLevel/Services/Impersonation/ImpersonationNativeMethods.cs index 8add77b..7272d56 100644 --- a/ZeroLevel/Services/Impersonation/ImpersonationNativeMethods.cs +++ b/ZeroLevel/Services/Impersonation/ImpersonationNativeMethods.cs @@ -10,7 +10,7 @@ namespace ZeroLevel.Services.Impersonation { #region P/Invoke enums /// - /// Провайдер авторизации + /// Authorization provider /// public enum LogonProvider : int { @@ -23,7 +23,7 @@ namespace ZeroLevel.Services.Impersonation LOGON32_PROVIDER_DEFAULT = 0, } /// - /// Способ авторизации + /// Authorization method /// public enum LogonType : int { @@ -74,7 +74,7 @@ namespace ZeroLevel.Services.Impersonation LOGON32_LOGON_NEW_CREDENTIALS = 9, } /// - /// Желаемый уровень доступа к токену + /// Desired access level to token /// public struct TokenDesiredAccess { @@ -82,7 +82,7 @@ namespace ZeroLevel.Services.Impersonation public static uint STANDARD_RIGHTS_READ = 0x00020000; public static uint TOKEN_ASSIGN_PRIMARY = 0x0001; /// - /// Позволяет создать копию + /// Allows to create a copy /// public static uint TOKEN_DUPLICATE = 0x0002; public static uint TOKEN_IMPERSONATE = 0x0004; @@ -99,7 +99,7 @@ namespace ZeroLevel.Services.Impersonation TOKEN_ADJUST_SESSIONID); } /// - /// Тип безопасности применяется при операции дублирования токена(в текущей задаче) + /// The security type is used during the token duplication operation (in the current task) /// public enum SecurityImpersonationLevel : int { @@ -132,14 +132,14 @@ namespace ZeroLevel.Services.Impersonation #region P/Invoke /// - /// Авторизация от имени указанного пользователя + /// Authorization on behalf of the specified user /// - /// Имя пользователя - /// Домен в котором зарегистрирован пользователь - /// Пароль - /// Тип авторизации - /// Провайдер (всегда 0) - /// Токен - результат входа + /// Username + /// Domain + /// Password + /// Authorization Type + /// Provider (always 0) + /// Token - login result /// [DllImport("advapi32.dll")] internal static extern int LogonUserA(String lpszUserName, @@ -149,9 +149,9 @@ namespace ZeroLevel.Services.Impersonation int dwLogonProvider, out MySafeTokenHandle phToken); /// - /// Создание дубликата токена + /// Creating a duplicate token /// - /// Исходный токен + /// Original token /// /// /// @@ -164,11 +164,11 @@ namespace ZeroLevel.Services.Impersonation [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal static extern bool CloseHandle(IntPtr handle); /// - /// Попытка получения токена работающего процесса + /// Attempt to get a token running process /// - /// Указатель на процесс + /// Process pointer /// - /// Токен - результат + /// Token - result /// [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] diff --git a/ZeroLevel/Services/Impersonation/MySafeTokenHandle.cs b/ZeroLevel/Services/Impersonation/MySafeTokenHandle.cs index 01ec1da..ec56d63 100644 --- a/ZeroLevel/Services/Impersonation/MySafeTokenHandle.cs +++ b/ZeroLevel/Services/Impersonation/MySafeTokenHandle.cs @@ -5,7 +5,7 @@ using System.Security.Permissions; namespace ZeroLevel.Services.Impersonation { /// - /// Реализация безопасного указателя + /// Implementing a safe pointer /// [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)] [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)] diff --git a/ZeroLevel/Services/Impersonation/ProcessImpersonationExecutor.cs b/ZeroLevel/Services/Impersonation/ProcessImpersonationExecutor.cs index 30f5747..21899e6 100644 --- a/ZeroLevel/Services/Impersonation/ProcessImpersonationExecutor.cs +++ b/ZeroLevel/Services/Impersonation/ProcessImpersonationExecutor.cs @@ -3,7 +3,7 @@ namespace ZeroLevel.Services.Impersonation { /// - /// Реализует исполнение произвольного кода от прав указанного процесса + /// Implements the execution of an code from the rights of the specified process /// public class ProcessImpersonationExecutor : IImpersonationExecutor @@ -21,11 +21,8 @@ namespace ZeroLevel.Services.Impersonation _pid = pid; } /// - /// Исполнение кода + /// Code execution /// - /// Тип передаваемого аргумента - /// Делегат - /// Аргумент public void ExecuteCode(Action action, T arg) { using (Impersonation imp = new Impersonation()) @@ -40,16 +37,14 @@ namespace ZeroLevel.Services.Impersonation } else { - throw new Exception("Нет данных для идентификации процесса. Для копирования прав процесса требуется указать его имя или идентификатор."); + throw new Exception("No data to identify the process. To copy the rights of a process, you must specify its name or identifier"); } action(arg); } } /// - /// Исполнение кода + /// Code execution /// - /// Тип передаваемого аргумента - /// Делегат public void ExecuteCode(Action action) { using (Impersonation imp = new Impersonation()) @@ -64,7 +59,7 @@ namespace ZeroLevel.Services.Impersonation } else { - throw new Exception("Нет данных для идентификации процесса. Для копирования прав процесса требуется указать его имя или идентификатор."); + throw new Exception("No data to identify the process. To copy the rights of a process, you must specify its name or identifier"); } action(); } diff --git a/ZeroLevel/Services/Impersonation/UserImpersonationExecutor.cs b/ZeroLevel/Services/Impersonation/UserImpersonationExecutor.cs index be89384..ba92b8e 100644 --- a/ZeroLevel/Services/Impersonation/UserImpersonationExecutor.cs +++ b/ZeroLevel/Services/Impersonation/UserImpersonationExecutor.cs @@ -3,7 +3,7 @@ namespace ZeroLevel.Services.Impersonation { /// - /// Класс исполняющий произвольный код с правами указанного пользователя + /// Class executing code with the rights of the specified user /// public class UserImpersonationExecutor : IImpersonationExecutor @@ -22,11 +22,8 @@ namespace ZeroLevel.Services.Impersonation } /// - /// Исполнение кода + /// Code execution /// - /// Тип передаваемого аргумента - /// Делегат - /// Аргумент public void ExecuteCode(Action action, T arg) { using (Impersonation imp = new Impersonation()) @@ -36,10 +33,8 @@ namespace ZeroLevel.Services.Impersonation } } /// - /// Исполнение кода + /// Code execution /// - /// Тип передаваемого аргумента - /// Делегат public void ExecuteCode(Action action) { using (Impersonation imp = new Impersonation()) diff --git a/ZeroLevel/Services/Invokation/InvokeWrapper.cs b/ZeroLevel/Services/Invokation/InvokeWrapper.cs index d6a7ea1..3895faf 100644 --- a/ZeroLevel/Services/Invokation/InvokeWrapper.cs +++ b/ZeroLevel/Services/Invokation/InvokeWrapper.cs @@ -8,31 +8,31 @@ using System.Text; namespace ZeroLevel.Services.Invokation { /// - /// Обертка для вызова методов + /// Method call wrapper /// public class InvokeWrapper : IInvokeWrapper { /// - /// Кэш делегатов + /// Cahce /// protected readonly Dictionary _invokeCachee = new Dictionary(); #region Static helpers /// - /// Создает скомпилированное выражение для быстрого вызова метода, возвращает идентификатор выражения и делегат для вызова + /// Creates a compiled expression for a quick method call, returns the identifier of the expression and a delegate for the call. /// - /// Оборачиваемый метод - /// Кортеж с идентификатором выражения и делегатом + /// Wrapped method + /// Expression ID and Delegate Tuple protected static Tuple CreateCompiledExpression(MethodInfo method) { - var targetArg = Expression.Parameter(typeof(object)); // Цель на которой происходит вызов - var argsArg = Expression.Parameter(typeof(object[])); // Аргументы метода + var targetArg = Expression.Parameter(typeof(object)); + var argsArg = Expression.Parameter(typeof(object[])); var parameters = method.GetParameters(); Expression body = Expression.Call( method.IsStatic ? null - : Expression.Convert(targetArg, method.DeclaringType), // тип в котором объявлен метод + : Expression.Convert(targetArg, method.DeclaringType), // the type in which the method is declared method, parameters.Select((p, i) => Expression.Convert(Expression.ArrayIndex(argsArg, Expression.Constant(i)), p.ParameterType))); @@ -46,10 +46,10 @@ namespace ZeroLevel.Services.Invokation } /// - /// Оборачивает вызов делегата + /// Wraps Delegate Call /// - /// Оборачиваемый делегат - /// Кортеж с идентификатором выражения и делегатом + /// Wrapped delegate + /// Expression ID and Delegate Tuple protected static Tuple CreateCompiledExpression(Delegate handler) { return CreateCompiledExpression(handler.GetMethodInfo()); @@ -60,10 +60,10 @@ namespace ZeroLevel.Services.Invokation #region Helpers /// - /// Идентификатр однозначно определяющий метод на уровне типа (но не на глобальном уровне) + /// ID uniquely identifying method at the type level (but not at the global level) /// - /// Имя метода - /// Типы аргументов метода + /// Method name + /// Method Argument Types /// internal static string CreateMethodIdentity(string name, params Type[] argsTypes) { @@ -190,10 +190,10 @@ namespace ZeroLevel.Services.Invokation #region Configure by MethodInfo /// - /// Вносит в кэш вызов указанного метода + /// Cache the specified method /// - /// Метод - /// Идентификатор для вызова + /// Method + /// Call ID public string Configure(MethodInfo method) { var invoke = CreateCompiledExpression(method); @@ -202,10 +202,10 @@ namespace ZeroLevel.Services.Invokation } /// - /// Вносит в кэш вызов указанного делегата + /// Cache the specified delegate /// - /// Делегат - /// Идентификатор вызова + /// Delegate + /// Call ID public string Configure(Delegate handler) { var invoke = CreateCompiledExpression(handler); @@ -230,7 +230,7 @@ namespace ZeroLevel.Services.Invokation #region Configuration /// - /// Наполнение кэша из списка методов с идентификаторами + /// Filling the cache from the list of methods with identifiers /// protected void Configure(IEnumerable> list) { @@ -241,7 +241,7 @@ namespace ZeroLevel.Services.Invokation } /// - /// Добавление вызова в кэш + /// Adding a call to the cache /// protected void Configure(Tuple invoke) { @@ -253,11 +253,11 @@ namespace ZeroLevel.Services.Invokation #region Invoking /// - /// Вызов статического метода по идентификатору, в случае отсутствия метода в кеше будет брошено исключение KeyNotFoundException + /// Calling a static method by identifier, if there is no method in the cache, a KeyNotFoundException exception will be thrown /// - /// Идентификатор метода - /// Аргументы метода - /// Результат выполнения + /// Call ID + /// Method Arguments + /// Execution result public object InvokeStatic(string identity, object[] args) { if (_invokeCachee.ContainsKey(identity)) @@ -269,12 +269,12 @@ namespace ZeroLevel.Services.Invokation } /// - /// Вызов метода по идентификатору, в случае отсутствия метода в кеше будет брошено исключение KeyNotFoundException + /// Calling a method by identifier; if there is no method in the cache, KeyNotFoundException will be thrown. /// - /// Инстанс на котором вызывается метод - /// Идентификатор метода - /// Аргументы метода - /// Результат выполнения + /// The instance on which the method is called + /// Call ID + /// Method Arguments + /// Execution result public object Invoke(object target, string identity, object[] args) { if (_invokeCachee.ContainsKey(identity)) @@ -282,7 +282,7 @@ namespace ZeroLevel.Services.Invokation return _invokeCachee[identity](target, args); } - throw new KeyNotFoundException(String.Format("Not found method with identity '{0}'", identity)); + throw new KeyNotFoundException($"Not found method with identity '{identity}'"); } public object Invoke(object target, string identity) @@ -292,15 +292,15 @@ namespace ZeroLevel.Services.Invokation return _invokeCachee[identity](target, null); } - throw new KeyNotFoundException(String.Format("Not found method with identity '{0}'", identity)); + throw new KeyNotFoundException($"Not found method with identity '{identity}'"); } /// - /// Выполнение статического закэшированного метода + /// Execution of a static cached method /// - /// Имя метода - /// Аргументы метода - /// /// Результат выполнения + /// Method name + /// Method Arguments + /// /// Execution result public object Invoke(string methodName, object[] args) { return InvokeStatic(CreateMethodIdentity(methodName, args.Select(a => a.GetType()).ToArray()), args); @@ -311,21 +311,21 @@ namespace ZeroLevel.Services.Invokation #region Helpers /// - /// Запрос идентификатора для метода + /// Request call id for method /// - /// Имя метода - /// Список типов аргументов метода - /// Идентификатор + /// Method name + /// Method argument type list + /// Call ID public string GetInvokerIdentity(string methodName, params Type[] argsTypes) { return CreateMethodIdentity(methodName, argsTypes); } /// - /// Запрос делегата оборачивающего метод + /// Request for delegate to wrap method /// - /// Идентификатор метода - /// Делегат + /// Call ID + /// Delegate public Invoker GetInvoker(string identity) { if (_invokeCachee.ContainsKey(identity)) @@ -337,11 +337,11 @@ namespace ZeroLevel.Services.Invokation } /// - /// Запрос делегата оборачивающего метод + /// Request for delegate to wrap method /// - /// Имя метода - /// Список типов аргументов метода - /// Делегат + /// Method name + /// Method argument type list + /// Delegate public Invoker GetInvoker(string methodName, params Type[] argsTypes) { return GetInvoker(CreateMethodIdentity(methodName, argsTypes)); diff --git a/ZeroLevel/Services/Invokation/Invoker.cs b/ZeroLevel/Services/Invokation/Invoker.cs index 03df5a7..a8a7820 100644 --- a/ZeroLevel/Services/Invokation/Invoker.cs +++ b/ZeroLevel/Services/Invokation/Invoker.cs @@ -1,10 +1,10 @@ namespace ZeroLevel.Services.Invokation { /// - /// Делегат описывающий вызов метода + /// Delegate describing the method call /// - /// Цель на которой вызывается метод - /// Аргументы метода - /// Результат + /// The target on which the method is called + /// Method Arguments + /// Result public delegate object Invoker(object target, params object[] args); } diff --git a/ZeroLevel/Services/Logging/ILog.cs b/ZeroLevel/Services/Logging/ILog.cs index da2791e..2a94025 100644 --- a/ZeroLevel/Services/Logging/ILog.cs +++ b/ZeroLevel/Services/Logging/ILog.cs @@ -5,39 +5,39 @@ namespace ZeroLevel.Services.Logging public interface ILog { /// - /// Вывод сообщения как есть, без добавления уровня логирования и даты + /// Message output as is, without adding a logging level and date /// void Raw(string line, params object[] args); /// - /// Сообщение + /// Message /// void Info(string line, params object[] args); /// - /// Предупреждение + /// Warning /// void Warning(string line, params object[] args); /// - /// Ошибка + /// Error /// void Error(string line, params object[] args); /// - /// Ошибка + /// Error /// void Error(Exception ex, string line, params object[] args); /// - /// Фатальный сбой + /// Fatal crash /// void Fatal(string line, params object[] args); /// - /// Фатальный сбой + /// Fatal crash /// void Fatal(Exception ex, string line, params object[] args); /// - /// Отладочная информация + /// Debug info /// void Debug(string line, params object[] args); /// - /// Низкоуровневая отладочная информация + /// Low Level Debug info /// void Verbose(string line, params object[] args); } diff --git a/ZeroLevel/Services/Logging/ILogMessageBuffer.cs b/ZeroLevel/Services/Logging/ILogMessageBuffer.cs index 5eed7c3..2239461 100644 --- a/ZeroLevel/Services/Logging/ILogMessageBuffer.cs +++ b/ZeroLevel/Services/Logging/ILogMessageBuffer.cs @@ -3,22 +3,19 @@ namespace ZeroLevel.Services.Logging { /// - /// Очередь сообщений для вывода в лог + /// Message queue for logging /// internal interface ILogMessageBuffer : IDisposable { /// - /// Количество сообщений в очереди + /// Number of messages in the queue /// long Count { get; } /// - /// Запись сообщения в очередь + /// Write message to the queue /// void Push(LogLevel level, string message); - /// - /// Запрос сообщения из очереди для вывода в лог, подразумевается блокирующая работа метода, - /// пока очередь пустая, метод ожидает появления сообщения не возвращая результат. - /// + Tuple Take(); } } diff --git a/ZeroLevel/Services/Logging/Implementation/EncryptedFileLog.cs b/ZeroLevel/Services/Logging/Implementation/EncryptedFileLog.cs index fcba1dd..8d21269 100644 --- a/ZeroLevel/Services/Logging/Implementation/EncryptedFileLog.cs +++ b/ZeroLevel/Services/Logging/Implementation/EncryptedFileLog.cs @@ -50,15 +50,15 @@ namespace ZeroLevel.Services.Logging.Implementation private readonly EncryptedFileLogOptions _options; private int _todayCountLogFiles = 0; /// - /// Текущий лог-файл + /// Current log file /// private string _currentLogFile; /// - /// Поток для вывода в файл + /// Stream to output to file /// private Stream _writer; /// - /// Лок на пересоздание файла + /// Lock on re-create file /// private readonly object _fileRecreating = new object(); @@ -85,7 +85,7 @@ namespace ZeroLevel.Services.Logging.Implementation var dir = Directory.CreateDirectory(_options.Folder); if (dir.Exists == false) { - throw new ArgumentException(string.Format("Can't create or found directory '{0}'", _options.Folder)); + throw new ArgumentException($"Can't create or found directory '{_options.Folder}'"); } } _obfuscator = new FastObfuscator(options.Key); @@ -97,7 +97,7 @@ namespace ZeroLevel.Services.Logging.Implementation #region Utils /// - /// Проверка имени лог-файла (изменяется при смене даты на следующий день) + /// Checking the name of the log file (changes when the date changes to the next day) /// private void RecreateLogFile() { @@ -122,7 +122,7 @@ namespace ZeroLevel.Services.Logging.Implementation } } /// - /// Закрытие текущего лога + /// Closing the current log /// private void CloseCurrentWriter() { @@ -165,9 +165,6 @@ namespace ZeroLevel.Services.Logging.Implementation #region IDisposable private bool _disposed = false; - /// - /// Освобождение рессурсов - /// public void Dispose() { Sheduller.Remove(_taskRename); diff --git a/ZeroLevel/Services/Logging/Implementation/TextFileLogger.cs b/ZeroLevel/Services/Logging/Implementation/TextFileLogger.cs index d26d3b5..ce277ef 100644 --- a/ZeroLevel/Services/Logging/Implementation/TextFileLogger.cs +++ b/ZeroLevel/Services/Logging/Implementation/TextFileLogger.cs @@ -26,15 +26,15 @@ namespace ZeroLevel.Services.Logging.Implementation internal long LimitFileSize { get; private set; } internal Encoding TextEncoding { get; private set; } /// - /// Удалять файлы старее чем (период устаревания) + /// Delete files older than (aging period) /// internal TimeSpan RemoveOlderThen { get; private set; } /// - /// Удалять устаревшие файлы + /// Delete outdate files /// internal bool RemoveOldFiles { get; private set; } /// - /// Архивировать файлы + /// Archive files /// internal bool ZipOldFiles { get; private set; } @@ -48,7 +48,7 @@ namespace ZeroLevel.Services.Logging.Implementation } /// - /// Включить автоматическое архивирование + /// Enable automatic archiving /// public TextFileLoggerOptions EnableAutoArchiving() { @@ -56,9 +56,9 @@ namespace ZeroLevel.Services.Logging.Implementation return this; } /// - /// Включить автоматическое удаление устаревших файлов + ///Enable automatic deletion of outdate files. /// - /// Возраст файла лога по достижении которого требуется удаление + /// The age of the log file at which removal is required public TextFileLoggerOptions EnableAutoCleaning(TimeSpan age) { this.RemoveOldFiles = true; @@ -98,21 +98,21 @@ namespace ZeroLevel.Services.Logging.Implementation var options = new TextFileLoggerOptions(). SetFolderPath(config.First(logPrefix)); - config.DoWithFirst(string.Format("{0}.backlog", logPrefix), backlog => + config.DoWithFirst($"{logPrefix}.backlog", backlog => { if (backlog > 0) { Log.Backlog(backlog); } }); - config.DoWithFirst(string.Format("{0}.archive", logPrefix), enable => + config.DoWithFirst($"{logPrefix}.archive", enable => { if (enable) { options.EnableAutoArchiving(); } }); - config.DoWithFirst(string.Format("{0}.sizeinkb", logPrefix), size => + config.DoWithFirst($"{logPrefix}.sizeinkb", size => { if (size >= 1) { @@ -120,7 +120,7 @@ namespace ZeroLevel.Services.Logging.Implementation } }); - config.DoWithFirst(string.Format("{0}.cleanolderdays", logPrefix), days => + config.DoWithFirst($"{logPrefix}.cleanolderdays", days => { if (days > 0) { @@ -140,15 +140,15 @@ namespace ZeroLevel.Services.Logging.Implementation private int _todayCountLogFiles = 0; /// - /// Текущий лог-файл + /// Current log file /// private string _currentLogFile; /// - /// Поток для вывода в файл + /// Stream to output to file /// private TextWriter _writer; /// - /// Лок на пересоздание файла + /// Lock on re-create file /// private readonly object _fileRecreating = new object(); @@ -160,9 +160,8 @@ namespace ZeroLevel.Services.Logging.Implementation #region Ctors /// - /// Конструктор с указанием каталога для записи лог-файлов, кодировка задается по умолчанию как Unicode + /// Constructor indicating the directory for recording log files, the encoding is set to Unicode by default. /// - /// public TextFileLogger(TextFileLoggerOptions options) { _options = options.Commit(); @@ -171,12 +170,11 @@ namespace ZeroLevel.Services.Logging.Implementation var dir = Directory.CreateDirectory(_options.Folder); if (dir.Exists == false) { - throw new ArgumentException(string.Format("Can't create or found directory '{0}'", _options.Folder)); + throw new ArgumentException($"Can't create or found directory '{_options.Folder}'"); } } RecreateLogFile(); - // Задачи обслуживания - // Пересоздание лог-файла при достижении размера больше указанного + // Maintenance tasks if (_options.LimitFileSize > 0) { _taskKeys.Add(Sheduller.RemindEvery(TimeSpan.FromSeconds(20), CheckRecreateFileLogByOversize)); @@ -212,7 +210,7 @@ namespace ZeroLevel.Services.Logging.Implementation } /// - /// Закрытие текущего лога + /// Closing the current log /// private void CloseCurrentWriter() { @@ -264,7 +262,7 @@ namespace ZeroLevel.Services.Logging.Implementation fi = null; } /// - /// Проверка имени лог-файла (изменяется при смене даты на следующий день) + /// Checking the name of the log file (changes when the date changes to the next day) /// private void RecreateLogFile() { @@ -296,7 +294,7 @@ namespace ZeroLevel.Services.Logging.Implementation { if (null != filePath && File.Exists(filePath) && _options.ZipOldFiles) { - using (var stream = new FileStream(string.Format("{0}.{1}", filePath, "zip"), FileMode.Create)) + using (var stream = new FileStream($"{filePath}.zip", FileMode.Create)) { using (var zipStream = new GZipStream(stream, CompressionLevel.Optimal, false)) { @@ -344,9 +342,6 @@ namespace ZeroLevel.Services.Logging.Implementation #region IDisposable private bool _disposed = false; - /// - /// Освобождение рессурсов - /// public void Dispose() { foreach (var tk in _taskKeys) @@ -366,18 +361,13 @@ namespace ZeroLevel.Services.Logging.Implementation { #region Fields /// - /// Поток для вывода в файл + /// Stream to output to file /// private TextWriter _writer; public static readonly Encoding DEFAULT_ENCODING = Encoding.UTF8; #endregion #region Ctors - - /// - /// Конструктор с указанием каталога для записи лог-файлов, кодировка задается по умолчанию как Unicode - /// - /// public FileLogger(string path) { CreateLogFile(PreparePath(path)); @@ -391,7 +381,7 @@ namespace ZeroLevel.Services.Logging.Implementation { Directory.CreateDirectory(path); FSUtils.SetupFolderPermission(path, - string.Format("{0}\\{1}", Environment.UserDomainName, Environment.UserName), + $"{Environment.UserDomainName}\\{Environment.UserName}", FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify, AccessControlType.Allow); } @@ -409,7 +399,7 @@ namespace ZeroLevel.Services.Logging.Implementation } /// - /// Закрытие текущего лога + /// Closing the current log /// private void CloseCurrentWriter() { @@ -464,9 +454,6 @@ namespace ZeroLevel.Services.Logging.Implementation #region IDisposable private bool _disposed = false; - /// - /// Освобождение рессурсов - /// public void Dispose() { if (false == _disposed) diff --git a/ZeroLevel/Services/Logging/Log.cs b/ZeroLevel/Services/Logging/Log.cs index 1c6f363..b9fa044 100644 --- a/ZeroLevel/Services/Logging/Log.cs +++ b/ZeroLevel/Services/Logging/Log.cs @@ -36,56 +36,56 @@ namespace ZeroLevel _router.Write(LogLevel.Raw, FormatMessage(line, args)); } /// - /// Сообщение + /// Info message /// public static void Info(string line, params object[] args) { _router.Write(LogLevel.Info, FormatMessage(line, args)); } /// - /// Предупреждение + /// Warning message /// public static void Warning(string line, params object[] args) { _router.Write(LogLevel.Warning, FormatMessage(line, args)); } /// - /// Ошибка + /// Error message /// public static void Error(string line, params object[] args) { _router.Write(LogLevel.Error, FormatMessage(line, args)); } /// - /// Ошибка + /// Error message /// public static void Error(Exception ex, string line, params object[] args) { _router.Write(LogLevel.Error, FormatMessage(line, args) + "\r\n" + ex.ToString()); } /// - /// Фатальный сбой + /// Fatal crash /// public static void Fatal(string line, params object[] args) { _router.Write(LogLevel.Fatal, FormatMessage(line, args)); } /// - /// Фатальный сбой + /// Fatal message (mean stop app after crash) /// public static void Fatal(Exception ex, string line, params object[] args) { _router.Write(LogLevel.Fatal, FormatMessage(line, args) + "\r\n" + ex.ToString()); } /// - /// Отладочная информация + /// Debug message /// public static void Debug(string line, params object[] args) { _router.Write(LogLevel.Debug, FormatMessage(line, args)); } /// - /// Низкоуровневая отладолчная информация + /// Low-level debug message /// public static void Verbose(string line, params object[] args) { @@ -94,47 +94,33 @@ namespace ZeroLevel /// - /// Сообщение + /// System message /// public static void SystemInfo(string line, params object[] args) { _router.Write(LogLevel.SystemInfo, FormatMessage(line, args)); } /// - /// Предупреждение + /// System warning /// public static void SystemWarning(string line, params object[] args) { _router.Write(LogLevel.SystemWarning, FormatMessage(line, args)); } /// - /// Ошибка + /// System error /// public static void SystemError(string line, params object[] args) { _router.Write(LogLevel.SystemError, FormatMessage(line, args)); } /// - /// Ошибка + /// System error /// public static void SystemError(Exception ex, string line, params object[] args) { _router.Write(LogLevel.SystemError, FormatMessage(line, args) + "\r\n" + ex.ToString()); } - /// - /// Фатальный сбой - /// - public static void SystemFatal(string line, params object[] args) - { - _router.Write(LogLevel.SystemFatal, FormatMessage(line, args)); - } - /// - /// Фатальный сбой - /// - public static void SystemFatal(Exception ex, string line, params object[] args) - { - _router.Write(LogLevel.SystemFatal, FormatMessage(line, args) + "\r\n" + ex.ToString()); - } #endregion #region Register loggers @@ -217,7 +203,7 @@ namespace ZeroLevel } } /// - /// Установка максимального количества сообщений в очереди + /// Set mam count log-messages in queue /// public static void Backlog(long backlog) { diff --git a/ZeroLevel/Services/Logging/LogLevel.cs b/ZeroLevel/Services/Logging/LogLevel.cs index f908ff8..37c3317 100644 --- a/ZeroLevel/Services/Logging/LogLevel.cs +++ b/ZeroLevel/Services/Logging/LogLevel.cs @@ -3,63 +3,62 @@ namespace ZeroLevel.Services.Logging { /// - /// Перечисление, содержит возможные типы сообщений, для записи в лог + /// Enum contains possible types of messages to write to the log /// [Flags] public enum LogLevel : int { None = 0, /// - /// Сообщение + /// Message /// Info = 1 << 0, /// - /// Предупреждение о возможной неполадке + /// Warning /// Warning = 1 << 1, /// - /// Ошибка в выполнении (некритичная) + /// Error /// Error = 1 << 2, /// - /// Ошибка приводящая к аварийному завершению программы + /// Fatal /// Fatal = 1 << 3, /// - /// Отладочная информация + /// Debug /// Debug = 1 << 4, /// - /// Низкоуровневое логирование + /// LowLevel Debug /// Verbose = 1 << 5, /// - /// Стандартный уровень логирования, сообщения, предупреждения, ошибки и падения + /// Info | Warning | Error | Fatal /// Standart = Info | Warning | Error | Fatal, /// - /// Вывод сообщения как есть, без даты и уровня логирования + /// Message output as is, without date and logging level /// Raw = 1 << 6, /// - /// Запиcь проблем, предупреждения, ошибки, сбои + /// Error | Fatal | Warning /// Problem = Error | Fatal | Warning, /// - /// Запись всех стандартных уровней, не включая отладочные + /// Info | Problem | Raw /// All = Info | Problem | Raw, /// - /// Все сообщения, включая отладочные и низкоуровневые + /// All | Verbose | Debug /// FullDebug = All | Verbose | Debug, SystemInfo = 1 << 6, SystemWarning = 1 << 7, SystemError = 1 << 8, - SystemFatal = 1 << 9, - System = SystemInfo | SystemError | SystemWarning | SystemFatal, + System = SystemInfo | SystemError | SystemWarning, FullStandart = Standart | System } diff --git a/ZeroLevel/Services/Logging/LogLevelNameMapping.cs b/ZeroLevel/Services/Logging/LogLevelNameMapping.cs index 332bc7a..837640a 100644 --- a/ZeroLevel/Services/Logging/LogLevelNameMapping.cs +++ b/ZeroLevel/Services/Logging/LogLevelNameMapping.cs @@ -16,8 +16,7 @@ namespace ZeroLevel.Services.Logging { LogLevel.SystemInfo, "SYSINF"}, { LogLevel.SystemError, "SYSERR"}, - { LogLevel.SystemWarning, "SYSWRN"}, - { LogLevel.SystemFatal, "SYSFLT"} + { LogLevel.SystemWarning, "SYSWRN"} }; private static readonly Dictionary _full = new Dictionary { @@ -31,8 +30,7 @@ namespace ZeroLevel.Services.Logging { LogLevel.SystemInfo, " system info"}, { LogLevel.SystemError, " system error"}, - { LogLevel.SystemWarning, " systm warning"}, - { LogLevel.SystemFatal, " system fatal"} + { LogLevel.SystemWarning, " systm warning"} }; public static string CompactName(LogLevel level) { return _compact[level]; } diff --git a/ZeroLevel/Services/Trees/ItemFieldToTreeConverter.cs b/ZeroLevel/Services/Trees/ItemFieldToTreeConverter.cs deleted file mode 100644 index 32aa8d7..0000000 --- a/ZeroLevel/Services/Trees/ItemFieldToTreeConverter.cs +++ /dev/null @@ -1,304 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ZeroLevel.Services.Collections; - -namespace ZeroLevel.Services.Trees -{ - /// - /// Выполняет преобразование набора элементов в дерево (в набор ветвей) - /// - /// Тип элемента - /// Тип связующих компонентов элемента - public class ItemFieldToTreeConverter - { - #region Inner classes - private struct BranchTestResult - { - public bool HasInteraction; - public NodeBranch NewBranch; - } - - private struct Node - { - public T Value; - public TKey In; - public TKey Out; - - internal Node Clone() - { - return new Node - { - In = this.In, - Out = this.Out, - Value = this.Value - }; - } - - public bool Eq(Node other, Func comparer, Func key_comparer) - { - if (ReferenceEquals(this, other)) - return true; - return comparer(this.Value, other.Value) && - key_comparer(this.In, other.In) && - key_comparer(this.Out, other.Out); - } - - public override int GetHashCode() - { - return this.Value?.GetHashCode() ?? 0 ^ this.In.GetHashCode() ^ this.Out.GetHashCode(); - } - } - - private class NodeBranch - { - private List _nodes = new List(); - private readonly Func _key_comparer; - private readonly Func _comparer; - public IEnumerable Nodes - { - get - { - return _nodes; - } - } - - public NodeBranch(Node first, Func comparer, Func key_comparer) - { - _nodes.Add(first); - _key_comparer = key_comparer; - _comparer = comparer; - } - - public NodeBranch(IEnumerable nodes, Func comparer, Func key_comparer) - { - _nodes.AddRange(nodes); - _key_comparer = key_comparer; - _comparer = comparer; - } - - public List Extract() - { - return _nodes.Select(n => n.Value).ToList(); - } - - public BranchTestResult Test(Node node) - { - var result = new BranchTestResult { HasInteraction = false, NewBranch = null }; - if (_key_comparer(_nodes.Last().Out, node.In)) - { - _nodes.Add(node); - result.HasInteraction = true; - } - else if (_key_comparer(_nodes.First().In, node.Out)) - { - _nodes.Insert(0, node); - result.HasInteraction = true; - } - else - { - for (int i = 0; i < _nodes.Count; i++) - { - var current = _nodes[i]; - if (_key_comparer(current.Out, node.In)) - { - var list = _nodes.Take(i + 1).ToList(); - list.Add(node); - result.NewBranch = new NodeBranch(list, _comparer, _key_comparer); - result.HasInteraction = true; - break; - } - else if (_key_comparer(current.In, node.Out)) - { - var list = _nodes.Skip(i).ToList(); - list.Insert(0, node); - result.NewBranch = new NodeBranch(list, _comparer, _key_comparer); - result.HasInteraction = true; - break; - } - } - } - return result; - } - /// - /// Проверка возможности объединения с другой ветвью, если текущая является ее началом или продолжением - /// - public bool TryJoin(NodeBranch other) - { - if (other == null) - { - return false; - } - if (this._nodes.First().Eq(other._nodes.Last(), _comparer ,_key_comparer)) - { - this._nodes = other._nodes.Union(this._nodes).ToList(); - return true; - } - else if (this._nodes.Last().Eq(other._nodes.First(), _comparer, _key_comparer)) - { - this._nodes = this._nodes.Union(other._nodes).ToList(); - return true; - } - return false; - } - - public override bool Equals(object obj) - { - return this.Equals(obj as NodeBranch); - } - - public override int GetHashCode() - { - return this._nodes.GetEnumHashCode(); - } - - public bool Equals(NodeBranch other) - { - if (other == null) - return false; - if (ReferenceEquals(this, other)) - return true; - - return this._nodes.OrderingEquals(other._nodes); - } - } - #endregion - - private readonly Func _inKeyExtractor; - private readonly Func _outKeyExtractor; - private readonly Func _comparer; - private readonly Func _key_comparer; - /// - /// Конструктор - /// - /// Экстрактор входной связи элемента - /// Экстрактор исходящей связи элемента - public ItemFieldToTreeConverter(Func inKeyExtractor, - Func outKeyExtractor, - Func comparer = null, - Func key_comparer = null) - { - if (inKeyExtractor == null) - { - throw new ArgumentNullException(nameof(inKeyExtractor)); - } - if (outKeyExtractor == null) - { - throw new ArgumentNullException(nameof(outKeyExtractor)); - } - _inKeyExtractor = inKeyExtractor; - _outKeyExtractor = outKeyExtractor; - _comparer = comparer; - _key_comparer = key_comparer ?? new Func((k1, k2) => - { - if (k1 == null && k2 == null) return true; - if (k1 == null) return false; - if (k2 == null) return false; - return k1.Equals(k2); - }); - } - /// - /// Преобразование набора элементов к набору ветвей - /// - public IEnumerable> Convert(IEnumerable entries) - { - if (entries == null || entries.Any() == false) - { - return Enumerable.Empty>(); - } - var iterator = new SparseIterator(entries); - var result = new List(); - if (iterator.MoveNext() != -1) - { - result.Add(new NodeBranch(new Node - { - Value = iterator.Current, - In = _inKeyExtractor(iterator.Current), - Out = _outKeyExtractor(iterator.Current) - }, _comparer, _key_comparer)); - iterator.Exclude(); - } - else - { - return Enumerable.Empty>(); - } - int index; - var cachee = new Dictionary(); - while ((index = iterator.MoveNext()) != -1) - { - if (cachee.ContainsKey(index) == false) - { - cachee.Add(index, new Node - { - Value = iterator.Current, - In = _inKeyExtractor(iterator.Current), - Out = _outKeyExtractor(iterator.Current) - }); - } - var node = cachee[index]; - bool included = false; - var include = new List(); - foreach (var branch in result) - { - var tr = branch.Test(node); - if (tr.HasInteraction) - { - included = true; - if (tr.NewBranch != null) - { - include.Add(tr.NewBranch); - } - } - } - if (included == false) - { - result.Add(new NodeBranch(node, _comparer, _key_comparer)); - } - iterator.Exclude(); - if (include.Count > 0) result.AddRange(include); - } - // Проверить, если одна ветка является началом, или продолжением другой, выполнить склейки - for (int i = 0; i < result.Count - 1; i++) - { - var left = result[i]; - for (int j = i + 1; j < result.Count; j++) - { - var right = result[j]; - if (IsNodeBrunchEquals(left, right) || left.TryJoin(right)) - { - result.RemoveAt(j); j--; - } - } - } - return result.Select(e => e.Extract()); - } - - private bool IsNodeBrunchEquals(NodeBranch first, NodeBranch second) - { - if (first == null && second == null) - return true; - if (first == null) - return false; - if (second == null) - return false; - if (_comparer == null) - return first.Equals(second); - if (ReferenceEquals(first, second)) - return true; - - var f_arr = first.Nodes.ToArray(); - var s_arr = second.Nodes.ToArray(); - if (f_arr.Length != s_arr.Length) - return false; - for (int i = 0; i < f_arr.Length; i++) - { - var fi = f_arr[i]; - var si = s_arr[i]; - if (_key_comparer(fi.In, si.In) == false) return false; - if (_key_comparer(fi.Out, si.Out) == false) return false; - if (_comparer(fi.Value, si.Value) == false) return false; - } - return true; - } - } -} diff --git a/ZeroLevel/ZeroLevel.csproj b/ZeroLevel/ZeroLevel.csproj index 20beaad..d392b22 100644 --- a/ZeroLevel/ZeroLevel.csproj +++ b/ZeroLevel/ZeroLevel.csproj @@ -86,7 +86,6 @@ - @@ -95,12 +94,10 @@ - - @@ -137,7 +134,7 @@ - + @@ -365,7 +362,6 @@ - diff --git a/ZeroLevel/obj/Debug/ZeroLevel.csproj.CoreCompileInputs.cache b/ZeroLevel/obj/Debug/ZeroLevel.csproj.CoreCompileInputs.cache index e04f251..463c314 100644 --- a/ZeroLevel/obj/Debug/ZeroLevel.csproj.CoreCompileInputs.cache +++ b/ZeroLevel/obj/Debug/ZeroLevel.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -c7012002005514f37ffc568f2998758c453405e9 +3af5ac7a6b742028005a8a0757e8f6fbb4fd20fa diff --git a/ZeroLevel/obj/Debug/ZeroLevel.csprojAssemblyReference.cache b/ZeroLevel/obj/Debug/ZeroLevel.csprojAssemblyReference.cache index f96a474c7013dfdcc468b8920feaa0dfb4418a79..55850f9cfb6e9bd6556534aa992dbacb5b18550a 100644 GIT binary patch literal 20909 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