start localization

pull/1/head
Ogoun 6 years ago
parent 0b4de16640
commit 4d6a7f5e27

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<appSettings>
<!-- Logging -->
<add key="log" value="logs" />
<add key="console" value="true" />
<!-- Service parameters -->
<add key="ServiceName" value="MyZeroService" />
<add key="ServiceDescription" value="ZeroService example" />
<add key="ServiceStartType" value="Automatic" />
<add key="ServiceAccountType" value="LocalSystem" />
</appSettings>
</configuration>

@ -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<MyFirstApp>(args);
}
}
}

@ -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")]

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{50CEBEC2-2571-4592-AFD2-970BDB41947B}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>ZeroExample</RootNamespace>
<AssemblyName>ZeroExample</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="ZeroLevel, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ZeroLevel.1.0.3\lib\net47\ZeroLevel.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config">
<SubType>Designer</SubType>
</None>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ZeroLevel" version="1.0.3" targetFramework="net472" />
</packages>

@ -1 +1 @@
02ab5562f7a9f633d41e073aff759527ff59696c 4f0bbfe8ac44b56784f7eeaa3cdef96609d6b97e

@ -1 +1 @@
1a68033c72e3e719a45c8165f48f4effb88b5e68 48781ba1f58e845d50aedda0cbff5881dfe0563f

@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroLevel.Microservices", "
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroLevel.Discovery", "ZeroLevel.Discovery\ZeroLevel.Discovery.csproj", "{4F55B23F-938C-4DA2-B6DC-B6BC66D36073}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroLevel.Discovery", "ZeroLevel.Discovery\ZeroLevel.Discovery.csproj", "{4F55B23F-938C-4DA2-B6DC-B6BC66D36073}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroExample", "ZeroExample\ZeroExample.csproj", "{50CEBEC2-2571-4592-AFD2-970BDB41947B}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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|x64.Build.0 = Release|Any CPU
{4F55B23F-938C-4DA2-B6DC-B6BC66D36073}.Release|x86.ActiveCfg = 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 {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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

@ -10,7 +10,7 @@ namespace ZeroLevel.Models
#region Equal #region Equal
public bool Equals(BaseModel other) public bool Equals(BaseModel other)
{ {
if (this == null) // и так бывает if (this == null)
throw new NullReferenceException(); throw new NullReferenceException();
if (other == null) if (other == null)
return false; return false;

@ -6,7 +6,7 @@ using ZeroLevel.Services.Serialization;
namespace ZeroLevel.Models namespace ZeroLevel.Models
{ {
/// <summary> /// <summary>
/// Документ в бинарном представлении /// Binary data represantation
/// </summary> /// </summary>
public class BinaryDocument : public class BinaryDocument :
IBinarySerializable, IBinarySerializable,
@ -14,31 +14,31 @@ namespace ZeroLevel.Models
ICloneable ICloneable
{ {
/// <summary> /// <summary>
/// Идентификатор /// Id
/// </summary> /// </summary>
public Guid Id { get; set; } public Guid Id { get; set; }
/// <summary> /// <summary>
/// Имя файла /// File name
/// </summary> /// </summary>
public string FileName { get; set; } public string FileName { get; set; }
/// <summary> /// <summary>
/// Тип содержимого (pdf, doc и т.п.) /// Content type (pdf, doc, etc.)
/// </summary> /// </summary>
public string ContentType { get; set; } public string ContentType { get; set; }
/// <summary> /// <summary>
/// Содержимое /// Content
/// </summary> /// </summary>
public byte[] Document { get; set; } public byte[] Document { get; set; }
/// <summary> /// <summary>
/// Дата создания /// Creation date
/// </summary> /// </summary>
public DateTime Created { get; set; } public DateTime Created { get; set; }
/// <summary> /// <summary>
/// Опциональные заголовки /// Optional headers
/// </summary> /// </summary>
public List<Header> Headers { get; set; } public List<Header> Headers { get; set; }
/// <summary> /// <summary>
/// Категории /// Categories
/// </summary> /// </summary>
public List<Category> Categories { get; set; } public List<Category> Categories { get; set; }

@ -5,7 +5,7 @@ using ZeroLevel.Services.Serialization;
namespace ZeroLevel.Models namespace ZeroLevel.Models
{ {
/// <summary> /// <summary>
/// Результат выполнения действий /// Action result
/// </summary> /// </summary>
[DataContract] [DataContract]
public class InvokeResult : public class InvokeResult :
@ -29,12 +29,12 @@ namespace ZeroLevel.Models
#region Properties #region Properties
/// <summary> /// <summary>
/// Успех выполнения операции /// true when action successfully invoked
/// </summary> /// </summary>
[DataMember] [DataMember]
public bool Success; public bool Success;
/// <summary> /// <summary>
/// Комментарий (сообщение об ошибке при сбое, или доп. информация) /// Comment
/// </summary> /// </summary>
[DataMember] [DataMember]
public string Comment; public string Comment;
@ -42,15 +42,15 @@ namespace ZeroLevel.Models
#region Fabric methods #region Fabric methods
/// <summary> /// <summary>
/// Сбой при выполнении плана действий /// Error when action invoking
/// </summary> /// </summary>
public static InvokeResult Fault(string comment) { return new InvokeResult(false, comment); } public static InvokeResult Fault(string comment) { return new InvokeResult(false, comment); }
/// <summary> /// <summary>
/// Успешное выполнение /// Successfully
/// </summary> /// </summary>
public static InvokeResult Succeeding(string comment = "") { return new InvokeResult(true, comment); } public static InvokeResult Succeeding(string comment = "") { return new InvokeResult(true, comment); }
/// <summary> /// <summary>
/// Успешное выполнение /// Successfully
/// </summary> /// </summary>
public static InvokeResult Succeeding() { return _successResultWitoutComment; } public static InvokeResult Succeeding() { return _successResultWitoutComment; }
#endregion #endregion
@ -91,7 +91,7 @@ namespace ZeroLevel.Models
#region Fabric methods #region Fabric methods
public static InvokeResult<T> Succeeding(T value, string comment = "") { return new InvokeResult<T>(value, true, comment); } public static InvokeResult<T> Succeeding(T value, string comment = "") { return new InvokeResult<T>(value, true, comment); }
public static InvokeResult<T> Fault<T>(string comment) { return new InvokeResult<T>(false, comment); } public static InvokeResult<T> Fault(string comment) { return new InvokeResult<T>(false, comment); }
#endregion #endregion
public override void Serialize(IBinaryWriter writer) public override void Serialize(IBinaryWriter writer)

@ -54,7 +54,7 @@ namespace ZeroLevel.Services.Applications
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.SystemFatal(ex, $"[{Name}] Failed to start service"); Log.Fatal(ex, $"[{Name}] Failed to start service");
Stop(); Stop();
} }
} }
@ -72,7 +72,7 @@ namespace ZeroLevel.Services.Applications
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.SystemFatal(ex, $"[{Name}] Failed to pause service"); Log.Fatal(ex, $"[{Name}] Failed to pause service");
Stop(); Stop();
} }
} }
@ -90,7 +90,7 @@ namespace ZeroLevel.Services.Applications
} }
catch (Exception ex) 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(); Stop();
} }
} }
@ -108,7 +108,7 @@ namespace ZeroLevel.Services.Applications
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.SystemFatal(ex, $"[{Name}] Failed to stop service"); Log.Fatal(ex, $"[{Name}] Failed to stop service");
} }
finally finally
{ {

@ -1,5 +1,6 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.ServiceProcess; using System.ServiceProcess;
using ZeroLevel.Services.Applications; using ZeroLevel.Services.Applications;
@ -10,7 +11,7 @@ namespace ZeroLevel
{ {
static Bootstrap() static Bootstrap()
{ {
// Хак, чтобы не переписывать runtime секцию конфига при каждом обновлении Newtonsoft пакета // Tricks for minimize config changes for dependency resolve
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
} }
@ -27,6 +28,11 @@ namespace ZeroLevel
{ {
return Assembly.LoadFile(Path.Combine(Configuration.BaseDirectory, "Microsoft.Owin.dll")); 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) catch (Exception ex)
{ {
@ -36,7 +42,7 @@ namespace ZeroLevel
} }
/// <summary> /// <summary>
/// Установка приложения в качестве службы /// Self-install as windows service
/// </summary> /// </summary>
private static void InstallApplication() private static void InstallApplication()
{ {
@ -48,11 +54,11 @@ namespace ZeroLevel
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.SystemFatal(ex, "[Bootstrap] Fault service install"); Log.Fatal(ex, "[Bootstrap] Fault service install");
} }
} }
/// <summary> /// <summary>
/// Удаление приложения из служб /// Uninstall from windows services
/// </summary> /// </summary>
private static void UninstallApplication() private static void UninstallApplication()
{ {
@ -64,7 +70,7 @@ namespace ZeroLevel
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.SystemFatal(ex, "[Bootstrap] Fault service uninstall"); Log.Fatal(ex, "[Bootstrap] Fault service uninstall");
} }
} }
@ -125,7 +131,6 @@ namespace ZeroLevel
return; return;
} }
} }
// Исключения в процессе работы приложения перехыватываются уровнем ниже
if (Environment.UserInteractive) if (Environment.UserInteractive)
{ {
try try
@ -136,7 +141,7 @@ namespace ZeroLevel
} }
catch (Exception ex) 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 else
@ -149,7 +154,7 @@ namespace ZeroLevel
} }
catch (Exception ex) 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");
} }
} }
} }

@ -6,17 +6,8 @@ namespace ZeroLevel.Services.Applications
public enum ZeroServiceState : int public enum ZeroServiceState : int
{ {
Initialized = 0, Initialized = 0,
/// <summary>
/// Сервис работает
/// </summary>
Started = 1, Started = 1,
/// <summary>
/// Работа сервиса приостановлена
/// </summary>
Paused = 2, Paused = 2,
/// <summary>
/// Сервис остановлен (ресурсы освобождены)
/// </summary>
Stopped = 3 Stopped = 3
} }
} }

@ -3,9 +3,6 @@ using System.Collections.Generic;
namespace ZeroLevel.Services.Collections namespace ZeroLevel.Services.Collections
{ {
/// <summary>
/// Очередь фиксированной длины
/// </summary>
public sealed class FixSizeQueue<T> : public sealed class FixSizeQueue<T> :
IFixSizeQueue<T> IFixSizeQueue<T>
{ {
@ -26,8 +23,7 @@ namespace ZeroLevel.Services.Collections
_count = 0; _count = 0;
} }
/// <summary> /// <summary>
/// Добавление элемента в очередь, при достижении предела по размеру, /// If count is limited when intem adding, oldest item replace with new item
/// перезаписывается самый старый элемент
/// </summary> /// </summary>
public void Push(T item) public void Push(T item)
{ {

@ -5,6 +5,11 @@ using System.Threading;
namespace ZeroLevel.Services.Collections namespace ZeroLevel.Services.Collections
{ {
/// <summary>
/// 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]
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class RoundRobinCollection<T> : public sealed class RoundRobinCollection<T> :
IDisposable IDisposable
{ {

@ -1,82 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace ZeroLevel.Services.Collections
{
/// <summary>
/// Циклический разреженный итератор
/// позволяет выполнять циклический обход массива, с возможностью отмечать элементы
/// которые требуется прпускать при следующих обходах.
/// </summary>
public class SparseIterator<T>
{
private readonly T[] _array;
private readonly HashSet<int> _removed = new HashSet<int>();
private int index = -1;
public SparseIterator(IEnumerable<T> items)
{
_array = items.ToArray();
}
/// <summary>
/// Текущий элемент последовательности
/// </summary>
public T Current
{
get
{
if (index >= 0 && index < _array.Length)
{
return _array[index];
}
throw new IndexOutOfRangeException();
}
}
/// <summary>
/// Указывает на отсутствие элементов в последовательности или на
/// то что все элементы были отмечены для пропуска
/// </summary>
public bool IsEmpty
{
get
{
return _array.Length == 0 || _array.Length == _removed.Count;
}
}
/// <summary>
/// Сдвиг на следующий элемент, если достигнут конец последовательности,
/// переключается на первый неотмеченный для пропуска элемент
/// </summary>
/// <returns>вернет -1 если последовательность пуста, или если не осталось элементов не отмеченных для пропуска</returns>
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;
}
/// <summary>
/// Отмечает текущий элемент для пропуска при следующем обходе
/// </summary>
/// <returns></returns>
public bool Exclude()
{
if (index >= 0)
{
return _removed.Add(index);
}
return false;
}
}
}

@ -8,27 +8,27 @@ using ZeroLevel.Services.Serialization;
namespace ZeroLevel.Services.Config namespace ZeroLevel.Services.Config
{ {
/// <summary> /// <summary>
/// Упрощенная конфигурация, без разделения параметров по секциям /// Base configuration
/// </summary> /// </summary>
internal sealed class BaseConfiguration : internal sealed class BaseConfiguration :
IConfiguration IConfiguration
{ {
#region Private members #region Private members
/// <summary> /// <summary>
/// Указывает на заморозку конфигурации, все изменения запрещены /// When true, any changes disallow
/// </summary> /// </summary>
private bool _freezed = false; private bool _freezed = false;
/// <summary> /// <summary>
/// Указывает на перманентную заморозку конфигурации, разморозка запрещена /// When true, freeze permanent, can't be canceled
/// </summary> /// </summary>
private bool _permanentFreezed = false; private bool _permanentFreezed = false;
private readonly object _freezeLock = new object(); private readonly object _freezeLock = new object();
/// <summary> /// <summary>
/// Список вида ключ-значение /// Key-values dictionary
/// </summary> /// </summary>
private readonly ConcurrentDictionary<string, IList<string>> _keyValues = new ConcurrentDictionary<string, IList<string>>(); private readonly ConcurrentDictionary<string, IList<string>> _keyValues = new ConcurrentDictionary<string, IList<string>>();
/// <summary> /// <summary>
/// Пустой список /// Empty list
/// </summary> /// </summary>
private static readonly IEnumerable<string> EmptyValuesList = new List<string>(0); private static readonly IEnumerable<string> EmptyValuesList = new List<string>(0);
@ -44,10 +44,10 @@ namespace ZeroLevel.Services.Config
#region Properties #region Properties
/// <summary> /// <summary>
/// Список значений по ключу /// Get values by key
/// </summary> /// </summary>
/// <param name="key">Ключ</param> /// <param name="key">key</param>
/// <returns>Список значений</returns> /// <returns>Values list</returns>
public IEnumerable<string> this[string key] public IEnumerable<string> this[string key]
{ {
get get
@ -62,7 +62,7 @@ namespace ZeroLevel.Services.Config
} }
} }
/// <summary> /// <summary>
/// Список ключей /// Keys list
/// </summary> /// </summary>
public IEnumerable<string> Keys public IEnumerable<string> Keys
{ {
@ -240,10 +240,10 @@ namespace ZeroLevel.Services.Config
#endregion #endregion
/// <summary> /// <summary>
/// Добавление ключа и связанного с ним значения /// Add key-value
/// </summary> /// </summary>
/// <param name="key">Ключ</param> /// <param name="key">Key</param>
/// <param name="value">Значение</param> /// <param name="value">Value</param>
public IConfiguration Append(string key, string value) public IConfiguration Append(string key, string value)
{ {
if (false == _freezed) if (false == _freezed)
@ -258,8 +258,7 @@ namespace ZeroLevel.Services.Config
return this; return this;
} }
/// <summary> /// <summary>
/// Задает значение в единственном числе, /// Set unique value for key
/// существующее значение будет перезаписано
/// </summary> /// </summary>
public IConfiguration SetUnique(string key, string value) public IConfiguration SetUnique(string key, string value)
{ {
@ -270,15 +269,18 @@ namespace ZeroLevel.Services.Config
{ {
_keyValues.TryAdd(key, new List<string>()); _keyValues.TryAdd(key, new List<string>());
} }
else
{
_keyValues[key].Clear(); _keyValues[key].Clear();
}
_keyValues[key].Add(value?.Trim() ?? null); _keyValues[key].Add(value?.Trim() ?? null);
} }
return this; return this;
} }
/// <summary> /// <summary>
/// Очистка связанного с ключом списка значений /// Clean values binded with key
/// </summary> /// </summary>
/// <param name="key">Ключ</param> /// <param name="key">Key</param>
public IConfiguration Clear(string key) public IConfiguration Clear(string key)
{ {
if (false == _freezed) if (false == _freezed)
@ -292,7 +294,7 @@ namespace ZeroLevel.Services.Config
return this; return this;
} }
/// <summary> /// <summary>
/// Очистка конфигурации /// Configuration drop
/// </summary> /// </summary>
public IConfiguration Clear() public IConfiguration Clear()
{ {
@ -303,9 +305,9 @@ namespace ZeroLevel.Services.Config
return this; return this;
} }
/// <summary> /// <summary>
/// Удаление ключа и связанных с ним значений /// Remove key and binded values
/// </summary> /// </summary>
/// <param name="key">Ключ</param> /// <param name="key">Key</param>
public IConfiguration Remove(string key) public IConfiguration Remove(string key)
{ {
if (false == _freezed) if (false == _freezed)

@ -7,14 +7,14 @@ using ZeroLevel.Services.Serialization;
namespace ZeroLevel.Services.Config namespace ZeroLevel.Services.Config
{ {
/// <summary> /// <summary>
/// Наборы именованых конфигураций (секций) /// Named configuration sections array
/// </summary> /// </summary>
internal sealed class BaseConfigurationSet : internal sealed class BaseConfigurationSet :
IConfigurationSet IConfigurationSet
{ {
#region Private members #region Private members
/// <summary> /// <summary>
/// Список секций /// Sections
/// </summary> /// </summary>
private readonly ConcurrentDictionary<string, IConfiguration> _sections = new ConcurrentDictionary<string, IConfiguration>(); private readonly ConcurrentDictionary<string, IConfiguration> _sections = new ConcurrentDictionary<string, IConfiguration>();

@ -12,7 +12,7 @@ namespace ZeroLevel
public static class Configuration public static class Configuration
{ {
/// <summary> /// <summary>
/// Путь к каталогу приложения /// Application folder path
/// </summary> /// </summary>
public static string BaseDirectory = public static string BaseDirectory =
Path.GetDirectoryName(Assembly.GetExecutingAssembly()?.CodeBase)?. Path.GetDirectoryName(Assembly.GetExecutingAssembly()?.CodeBase)?.

@ -5,7 +5,7 @@ using ZeroLevel.Services.Serialization;
namespace ZeroLevel namespace ZeroLevel
{ {
/// <summary> /// <summary>
/// Интерфейс конфигурационных данных /// Configuration section
/// </summary> /// </summary>
public interface IConfiguration : public interface IConfiguration :
IEquatable<IConfiguration>, IEquatable<IConfiguration>,
@ -13,103 +13,101 @@ namespace ZeroLevel
{ {
#region Properties #region Properties
/// <summary> /// <summary>
/// Получение списка значений по ключу /// Get values by key
/// </summary> /// </summary>
IEnumerable<string> this[string key] { get; } IEnumerable<string> this[string key] { get; }
/// <summary> /// <summary>
/// Перечисление ключей /// Keys
/// </summary> /// </summary>
IEnumerable<string> Keys { get; } IEnumerable<string> Keys { get; }
/// <summary> /// <summary>
/// Указывает что конфигурация заблокирована на изменения /// Configuration is locked for change when true
/// </summary> /// </summary>
bool Freezed { get; } bool Freezed { get; }
#endregion #endregion
#region Methods #region Methods
/// <summary> /// <summary>
/// Получение списка значений параметра по ключу /// Get values by key
/// </summary> /// </summary>
/// <param name="key">Имя параметра</param> /// <param name="key">Key</param>
/// <returns>Список значений</returns> /// <returns>Values list</returns>
IEnumerable<string> Items(string key); IEnumerable<string> Items(string key);
/// <summary> /// <summary>
/// Получение одного(первого) значения параметра по ключу /// Get first value by key
/// </summary> /// </summary>
string First(string key); string First(string key);
/// <summary> /// <summary>
/// Получить первое значение в виде объекта типа T /// Get first value by key with cast to <typeparamref name="T"/>
/// </summary> /// </summary>
T First<T>(string key); T First<T>(string key);
/// <summary> /// <summary>
/// Получить первое значение или значение по умолчанию /// Get first or default value by key
/// </summary> /// </summary>
string FirstOrDefault(string name, string defaultValue); string FirstOrDefault(string name, string defaultValue);
/// <summary> /// <summary>
/// Получить первое значение в виде объекта типа T или получить значение по умолчанию /// Get first or default value by key with cast to <typeparamref name="T"/>
/// </summary> /// </summary>
T FirstOrDefault<T>(string name); T FirstOrDefault<T>(string name);
/// <summary> /// <summary>
/// Получить первое значение в виде объекта типа T или получить переданное значение по умолчанию /// Get first or default value by key with cast to <typeparamref name="T"/>
/// </summary> /// </summary>
T FirstOrDefault<T>(string name, T defaultValue); T FirstOrDefault<T>(string name, T defaultValue);
/// <summary> /// <summary>
/// Проверка наличия ключа /// Check key exists
/// </summary> /// </summary>
bool Contains(string key); bool Contains(string key);
/// <summary> /// <summary>
/// Проверка наличия одного из ключей /// Check one of key exists
/// </summary> /// </summary>
bool Contains(params string[] keys); bool Contains(params string[] keys);
/// <summary> /// <summary>
/// Проверка наличия значения по ключу /// true if exists one or more values by key
/// </summary> /// </summary>
bool ContainsValue(string key, string value); bool ContainsValue(string key, string value);
/// <summary> /// <summary>
/// Количество значений параметра /// Count values by key
/// </summary> /// </summary>
int Count(string key); int Count(string key);
/// <summary> /// <summary>
/// Выполняет указанное действие только в случае если в конфигурации есть ключ /// Do action if key exists, action takes first value
/// </summary> /// </summary>
void DoWithFirst(string key, Action<string> action); void DoWithFirst(string key, Action<string> action);
/// <summary> /// <summary>
/// Выполняет указанное действие только в случае если в конфигурации есть ключ /// Do action if key exists, action takes first value with cast to <typeparamref name="T"/>
/// </summary> /// </summary>
void DoWithFirst<T>(string key, Action<T> action); void DoWithFirst<T>(string key, Action<T> action);
#endregion #endregion
#region Create, Clean, Delete #region Create, Clean, Delete
/// <summary> /// <summary>
/// Очистка всей секции /// Clean
/// </summary> /// </summary>
IConfiguration Clear(); IConfiguration Clear();
/// <summary> /// <summary>
/// Очистка значения ключа /// Clean values by key
/// </summary> /// </summary>
IConfiguration Clear(string key); IConfiguration Clear(string key);
/// <summary> /// <summary>
/// Удаление ключа и значений /// Remove key and binded values
/// </summary> /// </summary>
IConfiguration Remove(string key); IConfiguration Remove(string key);
/// <summary> /// <summary>
/// Добавление параметра /// Append key and value
/// </summary> /// </summary>
IConfiguration Append(string key, string value); IConfiguration Append(string key, string value);
/// <summary> /// <summary>
/// Задает значение в единственном числе, /// Set key with one value, if any values by key exists, they will be dropped
/// существующее значение будет перезаписано
/// </summary> /// </summary>
IConfiguration SetUnique(string key, string value); IConfiguration SetUnique(string key, string value);
/// <summary> /// <summary>
/// Запрещает вносить какие-либо изменения в конфигурацию /// Sets a prohibition on changing
/// </summary> /// </summary>
/// <returns>false - если уже установлен запрет</returns> /// <returns>false - prohibition was set already</returns>
bool Freeze(bool permanent = false); bool Freeze(bool permanent = false);
/// <summary> /// <summary>
/// Убирает запрет на внесение изменений в конфигурацию /// Remove a prohibition on changing
/// </summary> /// </summary>
/// <returns>false - если запрет снят</returns>
bool Unfreeze(); bool Unfreeze();
#endregion #endregion
} }

@ -5,7 +5,7 @@ using ZeroLevel.Services.Serialization;
namespace ZeroLevel namespace ZeroLevel
{ {
/// <summary> /// <summary>
/// Интерфейс набора конфигурационных данных /// Named configuration sections array
/// </summary> /// </summary>
public interface IConfigurationSet : public interface IConfigurationSet :
IEquatable<IConfigurationSet>, IEquatable<IConfigurationSet>,
@ -13,72 +13,64 @@ namespace ZeroLevel
{ {
#region Properties #region Properties
/// <summary> /// <summary>
/// Получение конфигурации по умолчанию /// Default section, always exists
/// </summary> /// </summary>
IConfiguration Default { get; } IConfiguration Default { get; }
/// <summary> /// <summary>
/// Получение конфигурации по имени /// Get configuration section by name
/// </summary> /// </summary>
IConfiguration this[string sectionName] { get; } IConfiguration this[string sectionName] { get; }
/// <summary> /// <summary>
/// Получение имен конфигураций /// Get configuration section names
/// </summary> /// </summary>
IEnumerable<string> SectionNames { get; } IEnumerable<string> SectionNames { get; }
/// <summary> /// <summary>
/// Получение всех конфигураций /// Get all sections
/// </summary> /// </summary>
IEnumerable<IConfiguration> Sections { get; } IEnumerable<IConfiguration> Sections { get; }
/// <summary> /// <summary>
/// Указывает, заблокирован или нет набор секций /// true if changing disallow
/// </summary> /// </summary>
bool SectionsFreezed { get; } bool SectionsFreezed { get; }
#endregion #endregion
#region Methods #region Methods
/// <summary> /// <summary>
/// Создание секции параметров /// Create section
/// </summary> /// </summary>
/// <param name="sectionName">Название секции</param> /// <param name="sectionName">Section name</param>
IConfiguration CreateSection(string sectionName); IConfiguration CreateSection(string sectionName);
/// <summary> /// <summary>
/// Запрос секции данных по имени секции /// Get configuration section by name
/// </summary> /// </summary>
/// <param name="sectionName">Название секции</param> /// <param name="sectionName">Название секции</param>
/// <returns>Секция с данными</returns> /// <returns>Секция с данными</returns>
IConfiguration GetSection(string sectionName); IConfiguration GetSection(string sectionName);
/// <summary> /// <summary>
/// Проверка наличия секции с указанным именем /// Check for a section by name
/// </summary> /// </summary>
/// <param name="sectionName">Название секции</param> /// <param name="sectionName">Section name</param>
/// <returns>true - секция существует</returns>
bool ContainsSection(string sectionName); bool ContainsSection(string sectionName);
/// <summary> /// <summary>Remove section by name
/// Удаление секции
/// </summary> /// </summary>
/// <param name="sectionName">Название секции</param> /// <param name="sectionName">Section name</param>
/// <returns>false - если секция уже удалена или не существует</returns>
bool RemoveSection(string sectionName); bool RemoveSection(string sectionName);
/// <summary> /// <summary>
/// Запрещает вносить какие-либо изменения в существующую конфигурацию во всех секциях /// Sets a prohibition on changing configurations
/// а также менять набор секций
/// </summary> /// </summary>
/// <returns>false - если уже установлен запрет</returns>
bool FreezeConfiguration(bool permanent = false); bool FreezeConfiguration(bool permanent = false);
/// <summary> /// <summary>
/// Запрещает вносить какие-либо изменения в существующий набор секций /// Sets a prohibition on changing sections
/// </summary> /// </summary>
/// <returns>false - если уже установлен запрет</returns>
bool FreezeSections(bool permanent = false); bool FreezeSections(bool permanent = false);
/// <summary> /// <summary>
/// Убирает запрет на внесение изменений в существующую конфигурацию во всех секциях /// Remove a prohibition on changing configurations
/// а также разрешает менять набор секций
/// </summary> /// </summary>
/// <returns>false - если запрет снят</returns> /// <returns>false - если запрет снят</returns>
bool UnfreezeConfiguration(); bool UnfreezeConfiguration();
/// <summary> /// <summary>
/// Убирает запрет на внесение изменений в существующий набор секций /// Sets a prohibition on changing sections
/// </summary> /// </summary>
/// <returns>false - если запрет снят</returns>
bool UnfreezeSections(); bool UnfreezeSections();
#endregion #endregion
} }

@ -40,7 +40,7 @@ namespace ZeroLevel.Services.Config.Implementation
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new InvalidOperationException("Не удалось создать конфигурацию из аргументов командной строки", ex); throw new InvalidOperationException("Can't read configuration from command line arguments", ex);
} }
} }
return result; return result;

@ -15,13 +15,13 @@ namespace ZeroLevel.Services.Config.Implementation
internal IniFileReader(string configPath) internal IniFileReader(string configPath)
{ {
if (String.IsNullOrWhiteSpace(configPath)) if (String.IsNullOrWhiteSpace(configPath))
throw new ArgumentNullException("configPath", "Не указан путь к конфигурационному файлу"); throw new ArgumentNullException("configPath", "File path not found");
if (!File.Exists(configPath)) if (!File.Exists(configPath))
{ {
configPath = Path.Combine(Configuration.BaseDirectory, configPath); configPath = Path.Combine(Configuration.BaseDirectory, configPath);
if (!File.Exists(configPath)) if (!File.Exists(configPath))
{ {
throw new FileNotFoundException("Не существует конфигурационный файл: " + configPath); throw new FileNotFoundException("File path not exists: " + configPath);
} }
} }
_iniPath = configPath; _iniPath = configPath;

@ -3,27 +3,23 @@
namespace ZeroLevel.Services.Config.Implementation namespace ZeroLevel.Services.Config.Implementation
{ {
/// <summary> /// <summary>
/// Запись конфигурации в ini-файл /// Write config to ini-file
/// </summary> /// </summary>
public class IniFileWriter public class IniFileWriter
: IConfigurationWriter : IConfigurationWriter
{ {
/// <summary> /// <summary>
/// Путь к ini-файлу /// Config file path
/// </summary> /// </summary>
private readonly string _iniPath; private readonly string _iniPath;
/// <summary>
/// Инициализирует новый экземпляр класса <see cref="IniFileWriter"/>
/// </summary>
/// <param name="iniPath">Путь к ini-файлу</param>
public IniFileWriter(string iniPath) public IniFileWriter(string iniPath)
{ {
_iniPath = iniPath; _iniPath = iniPath;
} }
/// <summary> /// <summary>
/// Запись простой конфигурации /// Write config to file
/// </summary> /// </summary>
/// <param name="configuration">Конфигурация</param>
public void WriteConfiguration(IConfiguration configuration) public void WriteConfiguration(IConfiguration configuration)
{ {
using (TextWriter writer = new StreamWriter(_iniPath, false)) using (TextWriter writer = new StreamWriter(_iniPath, false))
@ -46,9 +42,8 @@ namespace ZeroLevel.Services.Config.Implementation
} }
} }
/// <summary> /// <summary>
/// Запись конфигурации разбитой по секциям /// Write configuration set to file
/// </summary> /// </summary>
/// <param name="configuration">Конфигурация</param>
public void WriteConfigurationSet(IConfigurationSet configuration) public void WriteConfigurationSet(IConfigurationSet configuration)
{ {
using (TextWriter writer = new StreamWriter(_iniPath, false)) using (TextWriter writer = new StreamWriter(_iniPath, false))

@ -11,7 +11,7 @@ namespace ZeroLevel.DocumentObjectModel
void EnterIdentifier(Identifier identifier); void EnterIdentifier(Identifier identifier);
void ReadVersion(int version); void ReadVersion(int version);
void ReadTimestamp(string timestamp); void ReadTimestamp(long timestamp);
void ReadDateLabel(string datelabel); void ReadDateLabel(string datelabel);
void LeaveIdentifier(Identifier identifier); void LeaveIdentifier(Identifier identifier);
@ -44,9 +44,9 @@ namespace ZeroLevel.DocumentObjectModel
void LeaveHeaders(IEnumerable<Header> headers); void LeaveHeaders(IEnumerable<Header> headers);
void LeaveDescriptioveBlock(DescriptiveMetadata metadata); void LeaveDescriptioveBlock(DescriptiveMetadata metadata);
void EnterAsides(IEnumerable<AsideContent> asides); void EnterAsides(IEnumerable<AttachContent> asides);
void ReadAside(AsideContent aside, int order); void ReadAside(AttachContent aside, int order);
void LeaveAsides(IEnumerable<AsideContent> asides); void LeaveAsides(IEnumerable<AttachContent> asides);
void EnterAssotiations(IEnumerable<Assotiation> assotiations); void EnterAssotiations(IEnumerable<Assotiation> assotiations);
void ReadAssotiation(Assotiation assotiation, int order); void ReadAssotiation(Assotiation assotiation, int order);

@ -6,7 +6,7 @@ namespace DOM.DSL.Contracts
public interface ISpecialTableBuilder public interface ISpecialTableBuilder
{ {
/// <summary> /// <summary>
/// Указывает что ожидается запись тела ячейки таблицы /// Indicates that a table cell body entry is expected.
/// </summary> /// </summary>
bool WaitCellBody { get; } bool WaitCellBody { get; }
void WriteToCell(string part); void WriteToCell(string part);

@ -305,13 +305,13 @@ namespace DOM.DSL.Model
case "ignore": case "ignore":
TablePrefix = TablePostfix = null; TablePrefix = TablePostfix = null;
break; break;
case "special": // Использование захардкоженного преобразования таблицы case "special": // Using a hardcoded table conversion
//TablePrefix = TablePostfix = null; //TablePrefix = TablePostfix = null;
ColumnsPrefix = ColumnsPostfix = null; ColumnsPrefix = ColumnsPostfix = null;
ColumnPrefix = ColumnTemplate = ColumnPostfix = null; ColumnPrefix = ColumnTemplate = ColumnPostfix = null;
RowPrefix = RowPostfix = null; RowPrefix = RowPostfix = null;
CellPrefix = CellPostfix = null; CellPrefix = CellPostfix = null;
// Аргументы: (style, paddings l-t-r-b, maxcellwidth, maxtablewidth) // Args: (style, paddings l-t-r-b, maxcellwidth, maxtablewidth)
UseSpecialTableBuilder = true; UseSpecialTableBuilder = true;
SpecialTableBuilder = SpecialTableBuilderFactory.CreateSpecialTableBuilder(special); SpecialTableBuilder = SpecialTableBuilderFactory.CreateSpecialTableBuilder(special);
if (SpecialTableBuilder == null) UseSpecialTableBuilder = false; if (SpecialTableBuilder == null) UseSpecialTableBuilder = false;

@ -17,12 +17,12 @@ namespace DOM.DSL.Services
case "plaintext": case "plaintext":
// (Borders, 1-0-1-0, 0, 96) // (Borders, 1-0-1-0, 0, 96)
var options = new TextTableRenderOptions(); var options = new TextTableRenderOptions();
if (args.Length > 1) // Стиль if (args.Length > 1) // Style
{ {
if (Enum.TryParse(args[1], out options.Style) == false) if (Enum.TryParse(args[1], out options.Style) == false)
options.Style = TextTableStyle.Borders; options.Style = TextTableStyle.Borders;
} }
if (args.Length > 2) // Паддинги if (args.Length > 2) // Paddings
{ {
var paddings = args[2].Split(' '); var paddings = args[2].Split(' ');
int buffer; int buffer;
@ -40,7 +40,7 @@ namespace DOM.DSL.Services
} }
} }
} }
if (args.Length > 3) // Ширина ячейки if (args.Length > 3) // Cell width
{ {
int buffer; int buffer;
if (true == int.TryParse(args[3].Trim(), out buffer)) if (true == int.TryParse(args[3].Trim(), out buffer))
@ -48,7 +48,7 @@ namespace DOM.DSL.Services
options.MaxCellWidth = buffer; options.MaxCellWidth = buffer;
} }
} }
if (args.Length > 4) // Ширина таблицы if (args.Length > 4) // Table width
{ {
int buffer; int buffer;
if (true == int.TryParse(args[4].Trim(), out buffer)) if (true == int.TryParse(args[4].Trim(), out buffer))

@ -7,6 +7,7 @@ using System.Linq;
using System.Security; using System.Security;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using ZeroLevel;
using ZeroLevel.DocumentObjectModel; using ZeroLevel.DocumentObjectModel;
using ZeroLevel.DocumentObjectModel.Flow; using ZeroLevel.DocumentObjectModel.Flow;
using ZeroLevel.Services.FileSystem; using ZeroLevel.Services.FileSystem;
@ -56,7 +57,7 @@ namespace DOM.DSL.Services
} }
else else
{ {
// Добавляются элементы разных типов, в этом случае все элементы приводим к string // Added elements of different types. All elements casts to string
var list = new List<string>(); var list = new List<string>();
foreach (var i in _list) list.Add(i.ToString()); foreach (var i in _list) list.Add(i.ToString());
_elementType = typeof(string); _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 Category) SelectProperty((Category)_current, propertyName, propertyIndex);
else if (_current is Header) SelectProperty((Header)_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 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 Assotiation) SelectProperty((Assotiation)_current, propertyName, propertyIndex);
else if (_current is List<Header>) SelectProperty((List<Header>)_current, propertyName, propertyIndex); else if (_current is List<Header>) SelectProperty((List<Header>)_current, propertyName, propertyIndex);
else if (_current is Identifier) SelectProperty((Identifier)_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); 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); return default(T);
} }
} }
@ -273,8 +275,9 @@ namespace DOM.DSL.Services
{ {
return Convert.ChangeType(_current, type); 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); 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()) 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 Category) return ((Category)_current).Title ?? string.Empty;
else if (_current is Header) return ((Header)_current).Value ?? 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 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 Assotiation) return ((Assotiation)_current).Title ?? string.Empty;
else if (_current is List<Header>) return string.Join("; ", ((List<Header>)_current).Select(h => h.Name)); else if (_current is List<Header>) return string.Join("; ", ((List<Header>)_current).Select(h => h.Name));
else if (_current is Identifier) return string.Empty; else if (_current is Identifier) return string.Empty;

@ -43,64 +43,30 @@ namespace DOM.DSL.Services
{ {
private readonly Document _document; private readonly Document _document;
private readonly TEnvironment _environment; private readonly TEnvironment _environment;
private readonly DOMRenderElementCounter _counter;
private readonly TRenderOptions _options = new TRenderOptions();
private readonly TContainerFactory _factory;
private readonly IDictionary<string, object> _buffer =
new Dictionary<string, object>();
private readonly CustomBlocks _blocks = new CustomBlocks(); private readonly CustomBlocks _blocks = new CustomBlocks();
internal TContainerFactory Factory { get; }
internal TContainerFactory Factory internal IDictionary<string, object> BufferDictionary { get; } = new Dictionary<string, object>();
{ internal DOMRenderElementCounter Counter { get; }
get internal TRenderOptions Options { get; } = new TRenderOptions();
{
return _factory;
}
}
internal IDictionary<string, object> BufferDictionary
{
get
{
return _buffer;
}
}
internal DOMRenderElementCounter Counter
{
get
{
return _counter;
}
}
internal TRenderOptions Options
{
get
{
return _options;
}
}
public TRender(Document document, TEnvironment environment) public TRender(Document document, TEnvironment environment)
{ {
_document = document; _document = document;
_environment = environment; _environment = environment;
_counter = new DOMRenderElementCounter(); Counter = new DOMRenderElementCounter();
_factory = new TContainerFactory(this); Factory = new TContainerFactory(this);
} }
public void Resolve(TToken token, Action<TContainer> handler, bool release = true, TContainer self = null) public void Resolve(TToken token, Action<TContainer> 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 try
{ {
if (token is TTextToken) if (token is TTextToken)
{ {
var container = _factory.Get(token.AsTextToken().Text); var container = Factory.Get(token.AsTextToken().Text);
handler(container); handler(container);
if (release) _factory.Release(container); if (release) Factory.Release(container);
} }
else if (token is TElementToken) else if (token is TElementToken)
{ {
@ -108,7 +74,7 @@ namespace DOM.DSL.Services
foreach (var c in containers) foreach (var c in containers)
{ {
handler(c); handler(c);
if (release) _factory.Release(c); if (release) Factory.Release(c);
} }
} }
else if (token is TBlockToken) else if (token is TBlockToken)
@ -117,13 +83,13 @@ namespace DOM.DSL.Services
foreach (var c in containers) foreach (var c in containers)
{ {
handler(c); handler(c);
if (release) _factory.Release(c); if (release) Factory.Release(c);
} }
} }
} }
finally finally
{ {
_factory.Release(self_copy); Factory.Release(self_copy);
} }
} }
@ -133,56 +99,56 @@ namespace DOM.DSL.Services
switch (token.ElementName.Trim().ToLowerInvariant()) switch (token.ElementName.Trim().ToLowerInvariant())
{ {
// External // External
case "now": container = _factory.Get(DateTime.Now); break; case "now": container = Factory.Get(DateTime.Now); break;
case "utc": container = _factory.Get(DateTime.Now.ToUniversalTime()); break; case "utc": container = Factory.Get(DateTime.Now.ToUniversalTime()); break;
case "guid": container = _factory.Get(Guid.NewGuid()); break; case "guid": container = Factory.Get(Guid.NewGuid()); break;
case "nowutc": container = _factory.Get(DateTime.UtcNow); break; case "nowutc": container = Factory.Get(DateTime.UtcNow); break;
// Document // Document
case "id": container = _factory.Get(_document.Id); break; case "id": container = Factory.Get(_document.Id); break;
case "summary": container = _factory.Get(_document.Summary); break; case "summary": container = Factory.Get(_document.Summary); break;
case "header": container = _factory.Get(_document.Header); break; case "header": container = Factory.Get(_document.Header); break;
case "categories": container = _factory.Get(_document.Categories); break; case "categories": container = Factory.Get(_document.Categories); break;
case "directions": case "directions":
container = _factory.Get(_document.Categories. container = Factory.Get(_document.Categories.
Select(c => c.DirectionCode).Distinct().ToList()); break; Select(c => c.DirectionCode).Distinct().ToList()); break;
// Descriptive // Descriptive
case "desc": case "desc":
case "descriptive": container = _factory.Get(_document.DescriptiveMetadata); break; case "descriptive": container = Factory.Get(_document.DescriptiveMetadata); break;
case "author": container = _factory.Get(_document.DescriptiveMetadata.Byline); break; case "author": container = Factory.Get(_document.DescriptiveMetadata.Byline); break;
case "copyright": container = _factory.Get(_document.DescriptiveMetadata.CopyrightNotice); break; case "copyright": container = Factory.Get(_document.DescriptiveMetadata.CopyrightNotice); break;
case "created": container = _factory.Get(_document.DescriptiveMetadata.Created); break; case "created": container = Factory.Get(_document.DescriptiveMetadata.Created); break;
case "lang": container = _factory.Get(_document.DescriptiveMetadata.Language); break; case "lang": container = Factory.Get(_document.DescriptiveMetadata.Language); break;
case "priority": container = _factory.Get(_document.DescriptiveMetadata.Priority); break; case "priority": container = Factory.Get(_document.DescriptiveMetadata.Priority); break;
case "source": container = _factory.Get(_document.DescriptiveMetadata.Source); break; case "source": container = Factory.Get(_document.DescriptiveMetadata.Source); break;
case "publisher": container = _factory.Get(_document.DescriptiveMetadata.Publisher); break; case "publisher": container = Factory.Get(_document.DescriptiveMetadata.Publisher); break;
case "meta": case "meta":
case "headers": container = _factory.Get(_document.DescriptiveMetadata.Headers); break; case "headers": container = Factory.Get(_document.DescriptiveMetadata.Headers); break;
// Identifier // Identifier
case "identifier": container = _factory.Get(_document.Identifier); break; case "identifier": container = Factory.Get(_document.Identifier); break;
case "timestamp": container = _factory.Get(_document.Identifier.Timestamp); break; case "timestamp": container = Factory.Get(_document.Identifier.Timestamp); break;
case "datelabel": container = _factory.Get(_document.Identifier.DateLabel); break; case "datelabel": container = Factory.Get(_document.Identifier.DateLabel); break;
case "version": container = _factory.Get(_document.Identifier.Version); break; case "version": container = Factory.Get(_document.Identifier.Version); break;
// Tags // Tags
case "tags": container = _factory.Get(_document.TagMetadata); break; case "tags": container = Factory.Get(_document.TagMetadata); break;
case "keywords": container = _factory.Get(_document.TagMetadata.Keywords); break; case "keywords": container = Factory.Get(_document.TagMetadata.Keywords); break;
case "companies": container = _factory.Get(_document.TagMetadata.Companies); break; case "companies": container = Factory.Get(_document.TagMetadata.Companies); break;
case "persons": container = _factory.Get(_document.TagMetadata.Persons); break; case "persons": container = Factory.Get(_document.TagMetadata.Persons); break;
case "places": container = _factory.Get(_document.TagMetadata.Places); break; case "places": container = Factory.Get(_document.TagMetadata.Places); break;
case "var": container = _factory.Get(_environment.CustomVariables); break; case "var": container = Factory.Get(_environment.CustomVariables); break;
case "buf": container = _factory.Get(_buffer); break; case "buf": container = Factory.Get(BufferDictionary); break;
case "env": container = _factory.Get(_environment); break; case "env": container = Factory.Get(_environment); break;
case "counter": container = _factory.Get(_counter); break; case "counter": container = Factory.Get(Counter); break;
case "self": container = _factory.Get(self.Current, self.Index); break; case "self": container = Factory.Get(self.Current, self.Index); break;
case "content": container = _factory.Get(new TContentElement(_document)); break; case "content": container = Factory.Get(new TContentElement(_document)); break;
case "aside": container = _factory.Get(_document.Aside); break; case "aside": container = Factory.Get(_document.Attachments); break;
case "assotiations": container = _factory.Get(_document.Assotiations); break; case "assotiations": container = Factory.Get(_document.Assotiations); break;
case "null": container = _factory.Get(null); break; case "null": container = Factory.Get(null); break;
case "empty": container = _factory.Get(string.Empty); break; case "empty": container = Factory.Get(string.Empty); break;
// Blocks // Blocks
case "build": case "build":
@ -191,15 +157,15 @@ namespace DOM.DSL.Services
{ {
var block = new TBlockToken(_blocks.Get(token.NextToken.AsPropertyToken().PropertyName)); var block = new TBlockToken(_blocks.Get(token.NextToken.AsPropertyToken().PropertyName));
var result = ResolveBlockToken(block, self); 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) foreach (var c in result)
_factory.Release(c); Factory.Release(c);
} }
break; break;
} }
} }
if (container == null) container = _factory.Get(null); if (container == null) container = Factory.Get(null);
if (token.NextToken is TPropertyToken) if (token.NextToken is TPropertyToken)
{ {
@ -286,13 +252,13 @@ namespace DOM.DSL.Services
List<TContainer> result; List<TContainer> result;
if (success) 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); result = ResolveSimpleBlockToken(blockToken, ls);
_factory.Release(ls); Factory.Release(ls);
} }
else else
{ {
result = new List<TContainer> { _factory.Get(null) }; result = new List<TContainer> { Factory.Get(null) };
} }
return result; return result;
} }
@ -308,12 +274,12 @@ namespace DOM.DSL.Services
int index = 0; int index = 0;
foreach (var t in (IEnumerable)self_container.Current) 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) foreach (var bt in blockToken.Body)
{ {
Resolve(bt, c => list.Add(c), false, self); Resolve(bt, c => list.Add(c), false, self);
} }
_factory.Release(self); Factory.Release(self);
index++; index++;
} }
} }
@ -325,7 +291,7 @@ namespace DOM.DSL.Services
} }
} }
} }
_factory.Release(self_container); Factory.Release(self_container);
return list; return list;
} }
} }
@ -366,12 +332,12 @@ namespace DOM.DSL.Services
} }
special = string.Join(",", args.Select(a => a.ToString())); special = string.Join(",", args.Select(a => a.ToString()));
foreach (var a in args) foreach (var a in args)
_factory.Release(a); Factory.Release(a);
} }
rules.UpdateRule(elementName, functionName, rule_token, special); rules.UpdateRule(elementName, functionName, rule_token, special);
} }
} }
return _factory.Get(DocumentContentReader.ReadAs<string>(_document, new TContentToStringConverter(this, rules))); return Factory.Get(DocumentContentReader.ReadAs<string>(_document, new TContentToStringConverter(this, rules)));
} }
private void ApplyRenderCommand(TSystemToken token) private void ApplyRenderCommand(TSystemToken token)
@ -396,13 +362,13 @@ namespace DOM.DSL.Services
switch (args[0].ToString().Trim().ToLowerInvariant()) switch (args[0].ToString().Trim().ToLowerInvariant())
{ {
case "xml": case "xml":
_options.ValidateAsXml = true; Options.ValidateAsXml = true;
break; break;
case "html": case "html":
_options.ValidateAsHtml = true; Options.ValidateAsHtml = true;
break; break;
case "json": case "json":
_options.ValidateAsJson = true; Options.ValidateAsJson = true;
break; break;
} }
} }
@ -414,22 +380,24 @@ namespace DOM.DSL.Services
int width; int width;
if (int.TryParse(args[0].ToString(), out width)) if (int.TryParse(args[0].ToString(), out width))
{ {
_options.MaxStringWidth = width; Options.MaxStringWidth = width;
} }
else else
{ {
_options.MaxStringWidth = -1; Options.MaxStringWidth = -1;
} }
} }
else else
{ {
_options.MaxStringWidth = -1; Options.MaxStringWidth = -1;
} }
} }
break; break;
} }
foreach (var a in args) foreach (var a in args)
_factory.Release(a); {
Factory.Release(a);
}
} }
} }
} }

@ -28,7 +28,7 @@ namespace DOM.DSL
} }
catch (Exception ex) 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<TToken>(); return Enumerable.Empty<TToken>();
@ -69,7 +69,7 @@ namespace DOM.DSL
} }
catch (Exception ex) 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) if (ignore_fault == false)
{ {
throw ex; throw ex;

@ -1,7 +1,7 @@
namespace DOM.DSL.Tokens namespace DOM.DSL.Tokens
{ {
/// <summary> /// <summary>
/// Токен ссылающийся на элемент документа /// Token referring to the document element
/// </summary> /// </summary>
public class TElementToken : public class TElementToken :
TToken TToken
@ -11,7 +11,7 @@
/// </summary> /// </summary>
public string ElementName; public string ElementName;
/// <summary> /// <summary>
/// Опционально, при наличии свойств и/или функций для текущего элемента /// Optionally, next token
/// </summary> /// </summary>
public TToken NextToken; public TToken NextToken;

@ -1,13 +1,13 @@
namespace DOM.DSL.Tokens namespace DOM.DSL.Tokens
{ {
/// <summary> /// <summary>
/// Текстовый токен /// Text token
/// </summary> /// </summary>
public class TTextToken : public class TTextToken :
TToken TToken
{ {
/// <summary> /// <summary>
/// Текст в шаблоне, переносимый в результат без обработки /// Constant text
/// </summary> /// </summary>
public string Text; public string Text;

@ -3,13 +3,13 @@
namespace DOM.DSL.Tokens namespace DOM.DSL.Tokens
{ {
/// <summary> /// <summary>
/// Абстрактная единица шаблона /// Abstract token
/// </summary> /// </summary>
public abstract class TToken : TCloneable public abstract class TToken : TCloneable
{ {
public abstract TToken Clone(); public abstract TToken Clone();
/// <summary> /// <summary>
/// Копия с установкой NextToken в null, для предотвращения циклических расчетов /// Copying token with set NextToken to null, to break cycle
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public abstract TToken CloneLocal(); public abstract TToken CloneLocal();

@ -5,15 +5,15 @@ namespace ZeroLevel.DocumentObjectModel
public class Agency : IBinarySerializable public class Agency : IBinarySerializable
{ {
/// <summary> /// <summary>
/// Название источника /// Agency name
/// </summary> /// </summary>
public string Title; public string Title;
/// <summary> /// <summary>
/// Ссылка на источник /// Agency website
/// </summary> /// </summary>
public string Url; public string Url;
/// <summary> /// <summary>
/// Описание источника /// Description
/// </summary> /// </summary>
public string Description; public string Description;

@ -8,19 +8,19 @@ namespace ZeroLevel.DocumentObjectModel
{ {
#region Fields #region Fields
/// <summary> /// <summary>
/// Заголовок /// Title
/// </summary> /// </summary>
public string Title; public string Title;
/// <summary> /// <summary>
/// Описание (например, что было изменено по сравнению с прошлой версией) /// Description
/// </summary> /// </summary>
public string Description; public string Description;
/// <summary> /// <summary>
/// Ссылка на связанный документ /// Binded document reference
/// </summary> /// </summary>
public Guid DocumentId; public Guid DocumentId;
/// <summary> /// <summary>
/// Тип связи /// Relation type
/// </summary> /// </summary>
public AssotiationRelation Relation; public AssotiationRelation Relation;
#endregion #endregion

@ -5,23 +5,23 @@ namespace ZeroLevel.DocumentObjectModel
public enum AssotiationRelation : Int32 public enum AssotiationRelation : Int32
{ {
/// <summary> /// <summary>
/// Тип отношения не определен /// Relation type not defined
/// </summary> /// </summary>
Uncknown = 0, Uncknown = 0,
/// <summary> /// <summary>
/// Упоминается /// Mentioned
/// </summary> /// </summary>
Mentions = 1, Mentions = 1,
/// <summary> /// <summary>
/// Рассказывается о /// It tells about
/// </summary> /// </summary>
About = 2, About = 2,
/// <summary> /// <summary>
/// Обновление предыдущей версии /// Previous version update
/// </summary> /// </summary>
UpdateOf = 3, UpdateOf = 3,
/// <summary> /// <summary>
/// Основано на /// Based on
/// </summary> /// </summary>
BasedOn = 4 BasedOn = 4
} }

@ -3,33 +3,33 @@ using ZeroLevel.Services.Serialization;
namespace ZeroLevel.DocumentObjectModel namespace ZeroLevel.DocumentObjectModel
{ {
public sealed class AsideContent public sealed class AttachContent
: IBinarySerializable : IBinarySerializable
{ {
/// <summary> /// <summary>
/// Идентификатор /// ID
/// </summary> /// </summary>
public string Identity; public string Identity;
/// <summary> /// <summary>
/// Название содержимого /// Title
/// </summary> /// </summary>
public string Caption; public string Caption;
/// <summary> /// <summary>
/// Описание (опционально) /// Description (optional)
/// </summary> /// </summary>
public string Summary; public string Summary;
/// <summary> /// <summary>
/// Тип содержимого /// Content type
/// </summary> /// </summary>
public ContentType ContentType; public ContentType ContentType;
/// <summary> /// <summary>
/// Содержимое в бинарном представлении /// Binary content
/// </summary> /// </summary>
public byte[] Payload; public byte[] Payload;
public AsideContent() { } public AttachContent() { }
public AsideContent(IBinaryReader reader) { Deserialize(reader); } public AttachContent(IBinaryReader reader) { Deserialize(reader); }
public AsideContent(string identity, string caption, string description) public AttachContent(string identity, string caption, string description)
{ Identity = identity; Summary = description; Caption = caption; } { Identity = identity; Summary = description; Caption = caption; }
#region IBinarySerializable #region IBinarySerializable

@ -43,28 +43,27 @@ namespace ZeroLevel.DocumentObjectModel
#region Fields #region Fields
/// <summary> /// <summary>
/// Название /// Title
/// </summary> /// </summary>
public string Title { get; set; } public string Title { get; set; }
/// <summary> /// <summary>
/// Описание /// Description
/// </summary> /// </summary>
public string Description { get; set; } public string Description { get; set; }
/// <summary> /// <summary>
/// Код категории /// Category code
/// </summary> /// </summary>
public string Code { get; set; } public string Code { get; set; }
/// <summary> /// <summary>
/// Код направления /// Direction code
/// </summary> /// </summary>
public string DirectionCode { get; set; } public string DirectionCode { get; set; }
/// <summary> /// <summary>
/// Указывает на принадлежность категории внутренней части системы /// Is instrnal category
/// Категория не предназначенна для публичного доступа
/// </summary> /// </summary>
public bool IsSystem { get; set; } public bool IsSystem { get; set; }

@ -23,39 +23,39 @@ namespace ZeroLevel.DocumentObjectModel
#region Fields #region Fields
/// <summary> /// <summary>
/// Авторы (подпись) /// Authors
/// </summary> /// </summary>
public string Byline; public string Byline;
/// <summary> /// <summary>
/// Копирайт /// Copyright
/// </summary> /// </summary>
public string CopyrightNotice; public string CopyrightNotice;
/// <summary> /// <summary>
/// Дата создания /// Creation date
/// </summary> /// </summary>
public DateTime Created; public DateTime Created;
/// <summary> /// <summary>
/// Основной язык /// Main language
/// </summary> /// </summary>
public string Language; public string Language;
/// <summary> /// <summary>
/// Важность /// Priority
/// </summary> /// </summary>
public Priority Priority; public Priority Priority;
/// <summary> /// <summary>
/// Источник документа (например, информационное агентство) /// Document source
/// </summary> /// </summary>
public Agency Source; public Agency Source;
/// <summary> /// <summary>
/// Издатель (Агентство) /// Document publisher
/// </summary> /// </summary>
public Agency Publisher; public Agency Publisher;
/// <summary> /// <summary>
/// Ссылка на оригинальную новость, если текущая создана на ее основе /// Reference to original document
/// </summary> /// </summary>
public Tag Original; public Tag Original;
/// <summary> /// <summary>
/// Опциональные заголовки /// Headers (optional)
/// </summary> /// </summary>
public List<Header> Headers; public List<Header> Headers;
#endregion #endregion

@ -35,49 +35,49 @@ namespace ZeroLevel.DocumentObjectModel
Content = new FlowContent(); Content = new FlowContent();
TagMetadata = new TagMetadata(); TagMetadata = new TagMetadata();
DescriptiveMetadata = new DescriptiveMetadata(); DescriptiveMetadata = new DescriptiveMetadata();
Aside = new List<AsideContent>(); Attachments = new List<AttachContent>();
Assotiations = new List<Assotiation>(); Assotiations = new List<Assotiation>();
Categories = new List<Category>(); Categories = new List<Category>();
} }
/// <summary> /// <summary>
/// Идентификатор документа /// ID
/// </summary> /// </summary>
public Guid Id; public Guid Id;
/// <summary> /// <summary>
/// Краткое описание, лид /// Short description
/// </summary> /// </summary>
public string Summary; public string Summary;
/// <summary> /// <summary>
/// Заголовок /// Title
/// </summary> /// </summary>
public string Header; public string Header;
/// <summary> /// <summary>
/// Дополнительные идентификаторы /// Identification block
/// </summary> /// </summary>
public Identifier Identifier; public Identifier Identifier;
/// <summary> /// <summary>
/// Содержимое документа /// Content
/// </summary> /// </summary>
public FlowContent Content; public FlowContent Content;
/// <summary> /// <summary>
/// Теги /// Tags
/// </summary> /// </summary>
public TagMetadata TagMetadata; public TagMetadata TagMetadata;
/// <summary> /// <summary>
/// Метаданные документа /// Metadata
/// </summary> /// </summary>
public DescriptiveMetadata DescriptiveMetadata; public DescriptiveMetadata DescriptiveMetadata;
/// <summary> /// <summary>
/// Вложенные документы /// Attachments
/// </summary> /// </summary>
public List<AsideContent> Aside; public List<AttachContent> Attachments;
/// <summary> /// <summary>
/// Связанные документы /// Binded documents
/// </summary> /// </summary>
public List<Assotiation> Assotiations; public List<Assotiation> Assotiations;
/// <summary> /// <summary>
/// Категории /// Categories
/// </summary> /// </summary>
public List<Category> Categories; public List<Category> Categories;
@ -94,7 +94,7 @@ namespace ZeroLevel.DocumentObjectModel
writer.Write(this.TagMetadata); writer.Write(this.TagMetadata);
writer.Write(this.DescriptiveMetadata); writer.Write(this.DescriptiveMetadata);
writer.WriteCollection<AsideContent>(this.Aside); writer.WriteCollection<AttachContent>(this.Attachments);
writer.WriteCollection<Assotiation>(this.Assotiations); writer.WriteCollection<Assotiation>(this.Assotiations);
writer.WriteCollection<Category>(this.Categories); writer.WriteCollection<Category>(this.Categories);
} }
@ -110,7 +110,7 @@ namespace ZeroLevel.DocumentObjectModel
this.TagMetadata = reader.Read<TagMetadata>(); this.TagMetadata = reader.Read<TagMetadata>();
this.DescriptiveMetadata = reader.Read<DescriptiveMetadata>(); this.DescriptiveMetadata = reader.Read<DescriptiveMetadata>();
this.Aside = reader.ReadCollection<AsideContent>(); this.Attachments = reader.ReadCollection<AttachContent>();
this.Assotiations = reader.ReadCollection<Assotiation>(); this.Assotiations = reader.ReadCollection<Assotiation>();
this.Categories = reader.ReadCollection<Category>(); this.Categories = reader.ReadCollection<Category>();
} }

@ -8,11 +8,11 @@ namespace ZeroLevel.DocumentObjectModel.Flow
{ {
public SourceType Source { get; set; } public SourceType Source { get; set; }
/// <summary> /// <summary>
/// Название /// Title
/// </summary> /// </summary>
public string Title; public string Title;
/// <summary> /// <summary>
/// Ссылка или идентификатор вложения /// Link or Attachment ID
/// </summary> /// </summary>
public string Identifier; public string Identifier;

@ -3,24 +3,24 @@
namespace ZeroLevel.DocumentObjectModel.Flow namespace ZeroLevel.DocumentObjectModel.Flow
{ {
/// <summary> /// <summary>
/// Смещение содержимого в потоке /// Content Offset in flow
/// </summary> /// </summary>
public enum FlowAlign : Int32 public enum FlowAlign : Int32
{ {
/// <summary> /// <summary>
/// Без смещения /// None
/// </summary> /// </summary>
None = 0, None = 0,
/// <summary> /// <summary>
/// Смещение к левой части, допускает продолжение потока справа /// Flow: left
/// </summary> /// </summary>
Left = 1, Left = 1,
/// <summary> /// <summary>
/// Смещение к правой части, допускает продолжение потока слева /// Flow: right
/// </summary> /// </summary>
Right = 2, Right = 2,
/// <summary> /// <summary>
/// Выравнивание по центру /// Block
/// </summary> /// </summary>
Center = 3 Center = 3
} }

@ -4,7 +4,7 @@ using ZeroLevel.Services.Serialization;
namespace ZeroLevel.DocumentObjectModel.Flow namespace ZeroLevel.DocumentObjectModel.Flow
{ {
/// <summary> /// <summary>
/// Отображение вложенного документа или содержимого по внешней ссылке /// Attached document or content by external link
/// </summary> /// </summary>
public sealed class FormContent : ContentElement public sealed class FormContent : ContentElement
{ {

@ -9,11 +9,11 @@ namespace ZeroLevel.DocumentObjectModel.Flow
public SourceType Source { get; set; } public SourceType Source { get; set; }
public FlowAlign Align = FlowAlign.None; public FlowAlign Align = FlowAlign.None;
/// <summary> /// <summary>
/// Название /// Title
/// </summary> /// </summary>
public string Title; public string Title;
/// <summary> /// <summary>
/// Ссылка или идентификатор вложения /// Link or Attachment ID
/// </summary> /// </summary>
public string Identifier; public string Identifier;

@ -5,7 +5,7 @@ using ZeroLevel.Services.Serialization;
namespace ZeroLevel.DocumentObjectModel.Flow namespace ZeroLevel.DocumentObjectModel.Flow
{ {
/// <summary> /// <summary>
/// Параграф /// Paragraph
/// </summary> /// </summary>
public class Paragraph : public class Paragraph :
ContentElement ContentElement

@ -5,7 +5,7 @@ using ZeroLevel.Services.Serialization;
namespace ZeroLevel.DocumentObjectModel.Flow namespace ZeroLevel.DocumentObjectModel.Flow
{ {
/// <summary> /// <summary>
/// Логически завершенный информационный блок /// Document block
/// </summary> /// </summary>
public class Section : public class Section :
ContentElement ContentElement

@ -8,11 +8,11 @@ namespace ZeroLevel.DocumentObjectModel.Flow
{ {
public SourceType Source { get; set; } public SourceType Source { get; set; }
/// <summary> /// <summary>
/// Название /// Title
/// </summary> /// </summary>
public string Title; public string Title;
/// <summary> /// <summary>
/// Ссылка или идентификатор вложения /// Link or Attachment ID
/// </summary> /// </summary>
public string Identifier; public string Identifier;

@ -7,9 +7,6 @@ namespace ZeroLevel.DocumentObjectModel
public class FlowContent : public class FlowContent :
ContentElement ContentElement
{ {
/// <summary>
/// Содержимое
/// </summary>
public List<Section> Sections = new List<Section>(); public List<Section> Sections = new List<Section>();
public FlowContent() : public FlowContent() :

@ -24,21 +24,9 @@ namespace ZeroLevel.DocumentObjectModel
#endregion #endregion
#region Fields #region Fields
/// <summary>
/// Название
/// </summary>
public string Name; public string Name;
/// <summary>
/// Значение
/// </summary>
public string Value; public string Value;
/// <summary>
/// Тип
/// </summary>
public string Type; public string Type;
/// <summary>
/// Дополнительная информация
/// </summary>
public string Tag; public string Tag;
#endregion #endregion

@ -10,17 +10,15 @@ namespace ZeroLevel.DocumentObjectModel
#region Fields #region Fields
/// <summary> /// <summary>
/// Версия документа /// Version
/// </summary> /// </summary>
public int Version; public int Version;
/// <summary> /// <summary>
/// Идентификатор по дате выхода, дает возможность идентифицировать /// Timestamp ID
/// последнюю полученную по запросу новость, для последующих запросов
/// обновлений
/// </summary> /// </summary>
public string Timestamp; public long Timestamp;
/// <summary> /// <summary>
/// Идентификатор по дате выхода с масштабированием до дня (20161024) /// Label with day accurcy
/// </summary> /// </summary>
public string DateLabel; public string DateLabel;
#endregion #endregion
@ -29,14 +27,14 @@ namespace ZeroLevel.DocumentObjectModel
public void Serialize(IBinaryWriter writer) public void Serialize(IBinaryWriter writer)
{ {
writer.WriteInt32(this.Version); writer.WriteInt32(this.Version);
writer.WriteString(this.Timestamp); writer.WriteLong(this.Timestamp);
writer.WriteString(this.DateLabel); writer.WriteString(this.DateLabel);
} }
public void Deserialize(IBinaryReader reader) public void Deserialize(IBinaryReader reader)
{ {
this.Version = reader.ReadInt32(); this.Version = reader.ReadInt32();
this.Timestamp = reader.ReadString(); this.Timestamp = reader.ReadLong();
this.DateLabel = reader.ReadString(); this.DateLabel = reader.ReadString();
} }
#endregion #endregion

@ -3,21 +3,13 @@ using System.ComponentModel;
namespace ZeroLevel.DocumentObjectModel namespace ZeroLevel.DocumentObjectModel
{ {
public enum Priority : Int32 public enum Priority
: Int32
{ {
/// <summary>
/// Обычный
/// </summary>
[Description("Normal")] [Description("Normal")]
Normal = 0, Normal = 0,
/// <summary>
/// Срочный
/// </summary>
[Description("Express")] [Description("Express")]
Express = 1, Express = 1,
/// <summary>
/// Молния
/// </summary>
[Description("Flash")] [Description("Flash")]
Flash = 2 Flash = 2
} }

@ -6,13 +6,7 @@ namespace ZeroLevel.DocumentObjectModel
IBinarySerializable IBinarySerializable
{ {
#region Fields #region Fields
/// <summary>
/// Название
/// </summary>
public string Name; public string Name;
/// <summary>
/// Значение
/// </summary>
public string Value; public string Value;
#endregion #endregion

@ -19,19 +19,18 @@ namespace ZeroLevel.DocumentObjectModel
#region Fields #region Fields
/// <summary> /// <summary>
/// Упоминаемые места /// Placec (city, country, etc)
/// </summary> /// </summary>
public List<Tag> Places; public List<Tag> Places;
/// <summary> /// <summary>
/// Упоминаемые компании /// Companies
/// </summary> /// </summary>
public List<Tag> Companies; public List<Tag> Companies;
/// <summary> /// <summary>
/// Упоминаемые персоны /// Persons
/// </summary> /// </summary>
public List<Tag> Persons; public List<Tag> Persons;
/// <summary> /// <summary>Keywords
/// Ключевые слова
/// </summary> /// </summary>
public List<string> Keywords; public List<string> Keywords;
#endregion #endregion

@ -236,14 +236,12 @@ namespace DOM.Services
private void RaiseIncorrectTypeException(ContentElementType received, ContentElementType expected) private void RaiseIncorrectTypeException(ContentElementType received, ContentElementType expected)
{ {
throw new InvalidCastException(string.Format("Type {0} received instead of {1}", throw new InvalidCastException($"Type {received} received instead of {expected}");
received.ToString(), expected.ToString()));
} }
private void RaiseIncorrectContainerType(ContentElementType containerType, ContentElementType elementType) private void RaiseIncorrectContainerType(ContentElementType containerType, ContentElementType elementType)
{ {
throw new Exception(string.Format("Type {0} can not be written to a container of type {1}", throw new Exception($"Type {elementType} can not be written to a container of type {containerType}");
elementType.ToString(), containerType.ToString()));
} }
private void ReduceContainers() private void ReduceContainers()
@ -278,7 +276,7 @@ namespace DOM.Services
LeaveRow(); LeaveRow();
break; break;
default: 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); WriteElement(column);
} }
public void WriteText(ZeroLevel.DocumentObjectModel.Flow.Text text) public void WriteText(Text text)
{ {
if (text == null) if (text == null)
{ {
@ -473,15 +471,15 @@ namespace DOM.Services
} }
public void WriteText(string text) public void WriteText(string text)
{ {
WriteElement(new ZeroLevel.DocumentObjectModel.Flow.Text(text)); WriteElement(new Text(text));
} }
public void WriteText(string text, TextStyle style) 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) 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) public void WriteQuote(Quote quote)
{ {

@ -192,12 +192,12 @@ namespace DOM.Services
reader.LeaveHeaders(doc.DescriptiveMetadata.Headers); reader.LeaveHeaders(doc.DescriptiveMetadata.Headers);
reader.LeaveDescriptioveBlock(doc.DescriptiveMetadata); reader.LeaveDescriptioveBlock(doc.DescriptiveMetadata);
reader.EnterAsides(doc.Aside); reader.EnterAsides(doc.Attachments);
for (int i = 0; i < doc.Aside.Count; i++) 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); reader.EnterAssotiations(doc.Assotiations);
for (int i = 0; i < doc.Assotiations.Count; i++) for (int i = 0; i < doc.Assotiations.Count; i++)

@ -84,14 +84,14 @@ namespace ZeroLevel.Patterns.DependencyInjection
private readonly ReaderWriterLockSlim _rwLock = private readonly ReaderWriterLockSlim _rwLock =
new ReaderWriterLockSlim(); new ReaderWriterLockSlim();
/// <summary> /// <summary>
/// Маппинг контракт - резрешения /// Map - contract - dependency resolving
/// </summary> /// </summary>
private readonly Dictionary<Type, List<ResolveTypeInfo>> _resolvingMap = private readonly Dictionary<Type, List<ResolveTypeInfo>> _resolvingMap =
new Dictionary<Type, List<ResolveTypeInfo>>(); new Dictionary<Type, List<ResolveTypeInfo>>();
private readonly object _constructorCacheeLocker = new object(); private readonly object _constructorCacheeLocker = new object();
/// <summary> /// <summary>
/// Кэш данных о контрукторах типа /// Types constructors cache
/// </summary> /// </summary>
private readonly Dictionary<Type, IEnumerable<ConstructorMetadata>> _constructorCachee = private readonly Dictionary<Type, IEnumerable<ConstructorMetadata>> _constructorCachee =
new Dictionary<Type, IEnumerable<ConstructorMetadata>>(); new Dictionary<Type, IEnumerable<ConstructorMetadata>>();
@ -99,11 +99,11 @@ namespace ZeroLevel.Patterns.DependencyInjection
#region Private #region Private
/// <summary> /// <summary>
/// Создание экземпляра объекта по указанному разрешению зависимости /// Creating an instance of an object at the specified dependency resolution
/// </summary> /// </summary>
/// <param name="resolveType">Метаданные разрешения зависимости</param> /// <param name="resolveType">Dependency resolving metadata</param>
/// <param name="args">Аргументы конструктора</param> /// <param name="args">Ctor args</param>
/// <returns>Экземпляр объекта</returns> /// <returns>Instance</returns>
private object MakeResolving(ResolveTypeInfo resolveType, object[] args, bool compose = true) private object MakeResolving(ResolveTypeInfo resolveType, object[] args, bool compose = true)
{ {
Type instanceType = resolveType.ImplementationType; Type instanceType = resolveType.ImplementationType;
@ -127,12 +127,12 @@ namespace ZeroLevel.Patterns.DependencyInjection
return sessionInstance; return sessionInstance;
} }
/// <summary> /// <summary>
/// Создание экземпляра объекта по указанному разрешению зависимости, для обобщенного типа контракта /// Creating an instance of the object at the specified dependency resolution, for a generic type of contract
/// </summary> /// </summary>
/// <param name="resolveType">Метаданные разрешения зависимости</param> /// <param name="resolveType">Dependency resolving metadata</param>
/// <param name="genericType">Обобщенный тип контракта</param> /// <param name="genericType">Generic contract</param>
/// <param name="args">Аргументы конструктора</param> /// <param name="args">Ctor args</param>
/// <returns>Экземпляр объекта</returns> /// <returns>Instance</returns>
private object MakeGenericResolving(ResolveTypeInfo resolveType, Type genericType, object[] args, bool compose = true) private object MakeGenericResolving(ResolveTypeInfo resolveType, Type genericType, object[] args, bool compose = true)
{ {
if (null == resolveType.GenericCachee) if (null == resolveType.GenericCachee)
@ -171,31 +171,31 @@ namespace ZeroLevel.Patterns.DependencyInjection
return sessionInstance; return sessionInstance;
} }
/// <summary> /// <summary>
/// Сбор свойств типа помеченных аттрибутом разрешения зависимости /// Collecting properties of the type marked with attribute dependency resolution
/// </summary> /// </summary>
/// <param name="type">Тип</param> /// <param name="type">Type</param>
/// <returns>Список свойств отмеченных аттрибутом Resolve</returns> /// <returns>List of properties marked with "Resolve" attribute</returns>
private static IEnumerable<PropertyInfo> CollectResolvingProperties(Type type) private static IEnumerable<PropertyInfo> CollectResolvingProperties(Type type)
{ {
return type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy). return type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy).
Where(p => p.GetCustomAttribute<ResolveAttribute>() != null); Where(p => p.GetCustomAttribute<ResolveAttribute>() != null);
} }
/// <summary> /// <summary>
/// Сбор полей типа помеченных аттрибутом разрешения зависимости /// Collecting fields of type marked with an attribute of dependency resolution
/// </summary> /// </summary>
/// <param name="type">Тип</param> /// <param name="type">Type</param>
/// <returns>Список полей отмеченных аттрибутом Resolve</returns> /// <returns>List of properties marked with "Resolve" attribute</returns>
private static IEnumerable<FieldInfo> CollectResolvingFields(Type type) private static IEnumerable<FieldInfo> CollectResolvingFields(Type type)
{ {
return type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy). return type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy).
Where(p => p.GetCustomAttribute<ResolveAttribute>() != null); Where(p => p.GetCustomAttribute<ResolveAttribute>() != null);
} }
/// <summary> /// <summary>
/// Поиск разрешения зависимости /// Search for dependency resolution
/// </summary> /// </summary>
/// <param name="type">Тип контракта</param> /// <param name="type">Contract</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="contractType">Переопределенный тип контракта</param> /// <param name="contractType">Redefined contract type</param>
/// <returns></returns> /// <returns></returns>
private ResolveTypeInfo FindResolving(Type type, string resolveName, Type contractType) private ResolveTypeInfo FindResolving(Type type, string resolveName, Type contractType)
{ {
@ -227,15 +227,14 @@ namespace ZeroLevel.Patterns.DependencyInjection
_rwLock.ExitReadLock(); _rwLock.ExitReadLock();
} }
} }
throw new KeyNotFoundException(string.Format("Не удалось разрешить зависимость для типа {0} по ключу '{1}'", throw new KeyNotFoundException($"Can't resolve dependency by type '{type.FullName}' and dependency name '{resolveName}'");
type.FullName, resolveName));
} }
/// <summary> /// <summary>
/// Разрешение зависимости по аттрибуту Resolve /// Resolving dependency on attribute "Resolve
/// </summary> /// </summary>
/// <param name="type">Тип контракта</param> /// <param name="type">Contract</param>
/// <param name="resolveAttribute">Аттрибут</param> /// <param name="resolveAttribute">Resolve attribute</param>
/// <returns>Экземпляр объекта</returns> /// <returns>Instance</returns>
private object MakeInstanceBy(Type type, ResolveAttribute resolveAttribute) private object MakeInstanceBy(Type type, ResolveAttribute resolveAttribute)
{ {
var is_generic = false; var is_generic = false;
@ -256,16 +255,14 @@ namespace ZeroLevel.Patterns.DependencyInjection
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception( throw new Exception($"Can't create type '{type.FullName}' instance for contract type {type.FullName}. Dependency key: '{resolveAttribute?.ResolveName}'", ex);
string.Format("Не удалось создать экземпляр типа {0} для разрешения зависимости типа {1} по ключу {2}",
type.FullName, type.FullName, resolveAttribute?.ResolveName), ex);
} }
} }
/// <summary> /// <summary>
/// Сбор интерфейсов и абстрактных классов от которых унаследован тип /// Collection of interfaces and abstract classes from which the type is inherited
/// </summary> /// </summary>
/// <param name="sourceType">Тип</param> /// <param name="sourceType">Type</param>
/// <returns>Список интерфейсов и абстрактных классов</returns> /// <returns>List of interfaces and abstract classes</returns>
private static IEnumerable<Type> GetInterfacesAndAbstracts(Type sourceType) private static IEnumerable<Type> GetInterfacesAndAbstracts(Type sourceType)
{ {
var interfaces = sourceType.GetInterfaces().ToList(); var interfaces = sourceType.GetInterfaces().ToList();
@ -279,10 +276,10 @@ namespace ZeroLevel.Patterns.DependencyInjection
return interfaces; return interfaces;
} }
/// <summary> /// <summary>
/// Получение списка метаданных по конструкторам типа /// Getting a list of metadata by type constructors
/// </summary> /// </summary>
/// <param name="type">Тип</param> /// <param name="type">Type</param>
/// <returns>Метаданные о конструкторах типа</returns> /// <returns>Metadata type constructors</returns>
private IEnumerable<ConstructorMetadata> GetConstructors(Type type) private IEnumerable<ConstructorMetadata> GetConstructors(Type type)
{ {
lock (_constructorCacheeLocker) lock (_constructorCacheeLocker)
@ -301,11 +298,11 @@ namespace ZeroLevel.Patterns.DependencyInjection
return _constructorCachee[type]; return _constructorCachee[type];
} }
/// <summary> /// <summary>
/// Создание экземпляра объекта, в том числе с непубличными конструкторами /// Creating an instance of an object, including with non-public constructors
/// </summary> /// </summary>
/// <param name="type">Тип</param> /// <param name="type">Type</param>
/// <param name="args">Аргументы конструктора</param> /// <param name="args">Ctor args</param>
/// <returns>Экземпляр типа</returns> /// <returns>Instance</returns>
private object MakeInstance(Type type, object[] args) private object MakeInstance(Type type, object[] args)
{ {
ConstructorInfo constructor = null; ConstructorInfo constructor = null;
@ -331,10 +328,10 @@ namespace ZeroLevel.Patterns.DependencyInjection
} }
} }
/// <summary> /// <summary>
/// Регистрация разрешения зависимости /// Dependency resolution registration
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="resolveType">Метаданные разрешения</param> /// <param name="resolveType">Dependency resolving metadata</param>
private void Register(Type contractType, ResolveTypeInfo resolveType) private void Register(Type contractType, ResolveTypeInfo resolveType)
{ {
try try
@ -357,14 +354,12 @@ namespace ZeroLevel.Patterns.DependencyInjection
if (resolveType.IsDefault && if (resolveType.IsDefault &&
_resolvingMap[contractType].Any(it => it.IsDefault)) _resolvingMap[contractType].Any(it => it.IsDefault))
{ {
throw new Exception( throw new Exception($"Default resolve type already has been defined. Contract: {contractType.FullName}");
string.Format("Default resolve type already has been defined. Contract: {0}", contractType.FullName));
} }
if (_resolvingMap[contractType]. if (_resolvingMap[contractType].
Any(it => it.ResolveKey.Equals(resolveType.ResolveKey, StringComparison.OrdinalIgnoreCase))) Any(it => it.ResolveKey.Equals(resolveType.ResolveKey, StringComparison.OrdinalIgnoreCase)))
{ {
throw new Exception( throw new Exception($"Resolve type with the same name '{resolveType.ResolveKey}' already has been defined. Contract: { contractType.FullName}");
string.Format("Resolve type with the same name '{0}' already has been defined. Contract: {1}", resolveType.ResolveKey, contractType.FullName));
} }
} }
try try
@ -590,10 +585,10 @@ namespace ZeroLevel.Patterns.DependencyInjection
#region Register instance #region Register instance
/// <summary> /// <summary>
/// Регистрация готового экземпляра (синглтон) /// Register singletone
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <param name="implementation">Экземпляр</param> /// <param name="implementation">Instance</param>
public void Register<TContract>(TContract implementation) public void Register<TContract>(TContract implementation)
{ {
var resolveType = new ResolveTypeInfo var resolveType = new ResolveTypeInfo
@ -961,8 +956,7 @@ namespace ZeroLevel.Patterns.DependencyInjection
{ {
var resolve = GetResolvedType(type, resolveName); var resolve = GetResolvedType(type, resolveName);
if (null == resolve.Item1) if (null == resolve.Item1)
throw new KeyNotFoundException(string.Format("Can'r resolve type {0} on key '{1}'", throw new KeyNotFoundException($"Can'r resolve type {type.FullName} on key '{resolveName}'");
type.FullName, resolveName));
// Detect instance type // Detect instance type
try try
{ {
@ -974,9 +968,7 @@ namespace ZeroLevel.Patterns.DependencyInjection
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception( throw new Exception($"Can't create instance for type {type.FullName} for resolved dependency {type.FullName} by key {resolveName}", ex);
string.Format("Can't create instance for type {0} for resolved dependency {1} by key {2}",
type.FullName, type.FullName, resolveName), ex);
} }
} }
#endregion #endregion
@ -1069,8 +1061,7 @@ namespace ZeroLevel.Patterns.DependencyInjection
catch (Exception ex) catch (Exception ex)
{ {
Log.SystemWarning( Log.SystemWarning(
string.Format("Не удалось создать экземпляр типа {0} для разрешения зависимости типа {1} по ключу {2}", $"Can't create type '{type.FullName}' instance for resolve dependency with contract type '{type.FullName}' and dependency name '{resolveName}'", ex);
type.FullName, type.FullName, resolveName), ex);
} }
result = null; result = null;
return false; return false;
@ -1079,7 +1070,7 @@ namespace ZeroLevel.Patterns.DependencyInjection
#region Composition #region Composition
/// <summary> /// <summary>
/// Заполнение полей и свойств объекта отмеченных флагом автоподставновки значений из параметров контейнера /// Filling in the fields and properties of an object with auto-set values flagged from the container parameters
/// </summary> /// </summary>
private void FillParametrizedFieldsAndProperties(object instance) private void FillParametrizedFieldsAndProperties(object instance)
{ {
@ -1165,7 +1156,10 @@ namespace ZeroLevel.Patterns.DependencyInjection
Compose(instanse, recursive); Compose(instanse, recursive);
return true; return true;
} }
catch { } catch (Exception ex)
{
Log.SystemError(ex, $"[Container] TryCompose error. Instance: '{instanse?.GetType()?.FullName ?? string.Empty}'. Recursive: {recursive}");
}
return false; return false;
} }
#endregion #endregion
@ -1184,7 +1178,10 @@ namespace ZeroLevel.Patterns.DependencyInjection
{ {
(item.SharedInstance as IDisposable)?.Dispose(); (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) if (item.GenericInstanceCachee != null)
{ {
foreach (var gitem in item.GenericInstanceCachee.Values) foreach (var gitem in item.GenericInstanceCachee.Values)
@ -1193,11 +1190,18 @@ namespace ZeroLevel.Patterns.DependencyInjection
{ {
(gitem as IDisposable)?.Dispose(); (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 finally
{ {

@ -1,21 +1,21 @@
namespace ZeroLevel.Patterns.DependencyInjection namespace ZeroLevel.Patterns.DependencyInjection
{ {
/// <summary> /// <summary>
/// Интерфейс с методами проведения композиций /// Provides object composition
/// </summary> /// </summary>
public interface ICompositionProvider public interface ICompositionProvider
{ {
#region Composition #region Composition
/// <summary> /// <summary>
/// Композиция, выполняет подстановку зарегистрированных контрактов в полях и свойствах объекта /// Object compositions, insert contract implementation
/// </summary> /// </summary>
/// <param name="instanse">Инстанс объекта</param> /// <param name="instanse">Object instance</param>
void Compose(object instanse, bool recursive = true); void Compose(object instanse, bool recursive = true);
/// <summary> /// <summary>
/// Безопасная композиция, выполняет подстановку зарегистрированных контрактов в полях и свойствах объекта /// Object compositions, insert contract implementation
/// </summary> /// </summary>
/// <param name="instanse">Инстанс объекта</param> /// <param name="instanse">Object instance</param>
/// /// <returns>false - при сбое в попытке композиции объекта</returns> /// /// <returns>false if composition fault</returns>
bool TryCompose(object instanse, bool recursive = true); bool TryCompose(object instanse, bool recursive = true);
#endregion #endregion
} }

@ -3,37 +3,37 @@
namespace ZeroLevel.Patterns.DependencyInjection namespace ZeroLevel.Patterns.DependencyInjection
{ {
/// <summary> /// <summary>
/// Интерфейс с методами регистрации зависимостей с явным указанием экземпляров /// Methods for register contact implementations
/// (синглтон) /// (singletone)
/// </summary> /// </summary>
public interface IContainerInstanceRegister public interface IContainerInstanceRegister
{ {
#region Register instance #region Register instance
/// <summary> /// <summary>
/// Регистрация готового экземпляра (синглтон) /// Register instance for contract <typeparamref name="TContract"/>. (singletone)
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <param name="implementation">Экземпляр</param> /// <param name="implementation">Instance</param>
void Register<TContract>(TContract implementation); void Register<TContract>(TContract implementation);
/// <summary> /// <summary>
/// Регистрация готового экземпляра (синглтон) /// Register instance for contract <typeparamref name="TContract"/>. (singletone)
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <param name="implementation">Экземпляр</param> /// <param name="implementation">Instance</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
void Register<TContract>(TContract implementation, string resolveName); void Register<TContract>(TContract implementation, string resolveName);
/// <summary> /// <summary>
/// Регистрация готового экземпляра (синглтон) /// Register instance for contract (singletone)
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementation">Экземпляр</param> /// <param name="implementation">Instance</param>
void Register(Type contractType, object implementation); void Register(Type contractType, object implementation);
/// <summary> /// <summary>
/// Регистрация готового экземпляра (синглтон) /// Register instance for contract (singletone)
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="implementation">Экземпляр</param> /// <param name="implementation">Instance</param>
void Register(Type contractType, string resolveName, object implementation); void Register(Type contractType, string resolveName, object implementation);
#endregion #endregion
} }

@ -3,293 +3,293 @@
namespace ZeroLevel.Patterns.DependencyInjection namespace ZeroLevel.Patterns.DependencyInjection
{ {
/// <summary> /// <summary>
/// Интерфейс с методами регистрации зависимостей с указанием типов контракта и зависимости /// Methods for register contact resolvings
/// (синглтоны и мультитоны) /// (singletones and multitones)
/// </summary> /// </summary>
public interface IContainerRegister : IDisposable public interface IContainerRegister : IDisposable
{ {
#region Register #region Register
/// <summary> /// <summary>
/// Регистрация разрешения зависимости /// Dependency resolution registration
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
void Register<TContract, TImplementation>(); void Register<TContract, TImplementation>();
/// <summary> /// <summary>
/// Регистрация разрешения зависимости /// Dependency resolution registration
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
void Register<TContract, TImplementation>(string resolveName); void Register<TContract, TImplementation>(string resolveName);
/// <summary> /// <summary>
/// Регистрация разрешения зависимости /// Dependency resolution registration
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
void Register<TContract, TImplementation>(bool shared); void Register<TContract, TImplementation>(bool shared);
/// <summary> /// <summary>
/// Регистрация разрешения зависимости /// Dependency resolution registration
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
void Register<TContract, TImplementation>(string resolveName, bool shared); void Register<TContract, TImplementation>(string resolveName, bool shared);
/// <summary> /// <summary>
/// Регистрация разрешения зависимости /// Dependency resolution registration
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
void Register(Type contractType, Type implementationType); void Register(Type contractType, Type implementationType);
/// <summary> /// <summary>
/// Регистрация разрешения зависимости /// Dependency resolution registration
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
void Register(Type contractType, Type implementationType, string resolveName); void Register(Type contractType, Type implementationType, string resolveName);
/// <summary> /// <summary>
/// Регистрация разрешения зависимости /// Dependency resolution registration
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
void Register(Type contractType, Type implementationType, bool shared); void Register(Type contractType, Type implementationType, bool shared);
/// <summary> /// <summary>
/// Регистрация разрешения зависимости /// Dependency resolution registration
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
void Register(Type contractType, Type implementationType, string resolveName, bool shared); void Register(Type contractType, Type implementationType, string resolveName, bool shared);
#endregion #endregion
#region Register with parameters #region Register with parameters
/// <summary> /// <summary>
/// Регистрация разрешения зависимости с указанием параметров конструктора /// Dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
void ParameterizedRegister<TContract, TImplementation>(object[] constructorParameters); void ParameterizedRegister<TContract, TImplementation>(object[] constructorParameters);
/// <summary> /// <summary>
/// Регистрация разрешения зависимости с указанием параметров конструктора /// Dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
void ParameterizedRegister<TContract, TImplementation>(string resolveName, object[] constructorParameters); void ParameterizedRegister<TContract, TImplementation>(string resolveName, object[] constructorParameters);
/// <summary> /// <summary>
/// Регистрация разрешения зависимости с указанием параметров конструктора /// Dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
void ParameterizedRegister<TContract, TImplementation>(bool shared, object[] constructorParameters); void ParameterizedRegister<TContract, TImplementation>(bool shared, object[] constructorParameters);
/// <summary> /// <summary>
/// Регистрация разрешения зависимости с указанием параметров конструктора /// Dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
void ParameterizedRegister<TContract, TImplementation>(string resolveName, bool shared, object[] constructorParameters); void ParameterizedRegister<TContract, TImplementation>(string resolveName, bool shared, object[] constructorParameters);
/// <summary> /// <summary>
/// Регистрация разрешения зависимости с указанием параметров конструктора /// Dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
void ParameterizedRegister(Type contractType, Type implementationType, object[] constructorParameters); void ParameterizedRegister(Type contractType, Type implementationType, object[] constructorParameters);
/// <summary> /// <summary>
/// Регистрация разрешения зависимости с указанием параметров конструктора /// Dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
void ParameterizedRegister(Type contractType, Type implementationType, string resolveName, object[] constructorParameters); void ParameterizedRegister(Type contractType, Type implementationType, string resolveName, object[] constructorParameters);
/// <summary> /// <summary>
/// Регистрация разрешения зависимости с указанием параметров конструктора /// Dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
void ParameterizedRegister(Type contractType, Type implementationType, bool shared, object[] constructorParameters); void ParameterizedRegister(Type contractType, Type implementationType, bool shared, object[] constructorParameters);
/// <summary> /// <summary>
/// Регистрация разрешения зависимости с указанием параметров конструктора /// Dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
void ParameterizedRegister(Type contractType, Type implementationType, string resolveName, bool shared, object[] constructorParameters); void ParameterizedRegister(Type contractType, Type implementationType, string resolveName, bool shared, object[] constructorParameters);
#endregion #endregion
#region Safe register #region Safe register
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости /// Safe dependency resolution registration
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryRegister<TContract, TImplementation>(Action<Exception> fallback = null); bool TryRegister<TContract, TImplementation>(Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости /// Safe dependency resolution registration
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryRegister<TContract, TImplementation>(string resolveName, Action<Exception> fallback = null); bool TryRegister<TContract, TImplementation>(string resolveName, Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости /// Safe dependency resolution registration
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryRegister<TContract, TImplementation>(bool shared, Action<Exception> fallback = null); bool TryRegister<TContract, TImplementation>(bool shared, Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости /// Safe dependency resolution registration
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryRegister<TContract, TImplementation>(string resolveName, bool shared, Action<Exception> fallback = null); bool TryRegister<TContract, TImplementation>(string resolveName, bool shared, Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости /// Safe dependency resolution registration
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryRegister(Type contractType, Type implementationType, Action<Exception> fallback = null); bool TryRegister(Type contractType, Type implementationType, Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости /// Safe dependency resolution registration
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryRegister(Type contractType, Type implementationType, string resolveName, Action<Exception> fallback = null); bool TryRegister(Type contractType, Type implementationType, string resolveName, Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости /// Safe dependency resolution registration
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryRegister(Type contractType, Type implementationType, bool shared, Action<Exception> fallback = null); bool TryRegister(Type contractType, Type implementationType, bool shared, Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости /// Safe dependency resolution registration
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryRegister(Type contractType, Type implementationType, string resolveName, bool shared, Action<Exception> fallback = null); bool TryRegister(Type contractType, Type implementationType, string resolveName, bool shared, Action<Exception> fallback = null);
#endregion #endregion
#region Safe register with parameters #region Safe register with parameters
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости с указанием параметров конструктора /// Safe dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryParameterizedRegister<TContract, TImplementation>(object[] constructorParameters, Action<Exception> fallback = null); bool TryParameterizedRegister<TContract, TImplementation>(object[] constructorParameters, Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости с указанием параметров конструктора /// Safe dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryParameterizedRegister<TContract, TImplementation>(string resolveName, object[] constructorParameters, Action<Exception> fallback = null); bool TryParameterizedRegister<TContract, TImplementation>(string resolveName, object[] constructorParameters, Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости с указанием параметров конструктора /// Safe dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryParameterizedRegister<TContract, TImplementation>(bool shared, object[] constructorParameters, Action<Exception> fallback = null); bool TryParameterizedRegister<TContract, TImplementation>(bool shared, object[] constructorParameters, Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости с указанием параметров конструктора /// Safe dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam> /// <typeparam name="TContract">Contract</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam> /// <typeparam name="TImplementation">Dependency resolution</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryParameterizedRegister<TContract, TImplementation>(string resolveName, bool shared, object[] constructorParameters, Action<Exception> fallback = null); bool TryParameterizedRegister<TContract, TImplementation>(string resolveName, bool shared, object[] constructorParameters, Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости с указанием параметров конструктора /// Safe dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryParameterizedRegister(Type contractType, Type implementationType, object[] constructorParameters, Action<Exception> fallback = null); bool TryParameterizedRegister(Type contractType, Type implementationType, object[] constructorParameters, Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости с указанием параметров конструктора /// Safe dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryParameterizedRegister(Type contractType, Type implementationType, string resolveName, object[] constructorParameters, Action<Exception> fallback = null); bool TryParameterizedRegister(Type contractType, Type implementationType, string resolveName, object[] constructorParameters, Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости с указанием параметров конструктора /// Safe dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryParameterizedRegister(Type contractType, Type implementationType, bool shared, object[] constructorParameters, Action<Exception> fallback = null); bool TryParameterizedRegister(Type contractType, Type implementationType, bool shared, object[] constructorParameters, Action<Exception> fallback = null);
/// <summary> /// <summary>
/// Безопасная регистрация разрешения зависимости с указанием параметров конструктора /// Safe dependency resolution registration with constructor parameters
/// </summary> /// </summary>
/// <param name="contractType">Тип контракта</param> /// <param name="contractType">Contract</param>
/// <param name="implementationType">Тип разрешения</param> /// <param name="implementationType">Dependency resolution</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="shared">true - для синглтонов</param> /// <param name="shared">true - for singletone</param>
/// <param name="constructorParameters">Аргументы конструктора</param> /// <param name="constructorParameters">Ctor args</param>
/// <param name="fallback">Обработчик исключения</param> /// <param name="fallback">Error handler</param>
/// <returns>true - в случае успешной регистрации</returns> /// <returns>true - registration successfully completed</returns>
bool TryParameterizedRegister(Type contractType, Type implementationType, string resolveName, bool shared, object[] constructorParameters, Action<Exception> fallback = null); bool TryParameterizedRegister(Type contractType, Type implementationType, string resolveName, bool shared, object[] constructorParameters, Action<Exception> fallback = null);
#endregion #endregion
} }

@ -3,69 +3,65 @@
namespace ZeroLevel.Patterns.DependencyInjection namespace ZeroLevel.Patterns.DependencyInjection
{ {
/// <summary> /// <summary>
/// Интерфейс с методами для реализации хранения параметров /// DI parameters stogare (string key and anytype value)
/// (хранилище ключ-значение, где в качестве ключа используется сущность типа string, а в качестве значения объект любого типа)
/// </summary> /// </summary>
public interface IParameterStorage public interface IParameterStorage
{ {
#region IEverythingStorage #region IEverythingStorage
/// <summary> /// <summary>
/// Сохранение параметра /// Save parameter
/// </summary> /// </summary>
/// <typeparam name="T">Тип параметра</typeparam> /// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Ключ</param> /// <param name="key">Key</param>
/// <param name="value">Значение параметра</param> /// <param name="value">Parameter value</param>
void Save<T>(string key, T value); void Save<T>(string key, T value);
/// <summary> /// <summary>
/// Сохранение или обновление параметра /// Save or update parameter
/// </summary> /// </summary>
/// <typeparam name="T">Тип параметра</typeparam> /// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Ключ</param> /// <param name="key">Key</param>
/// <param name="value">Значение параметра</param> /// <param name="value">Parameter value</param>
void SaveOrUpdate<T>(string key, T value); void SaveOrUpdate<T>(string key, T value);
/// <summary> /// <summary>
/// Безопасное сохранение параметра /// Safe save parameter
/// </summary> /// </summary>
/// <typeparam name="T">Тип параметра</typeparam> /// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Ключ</param> /// <param name="key">Key</param>
/// <param name="value">Значение параметра</param> /// <param name="value">Parameter value</param>
/// <returns>true - в случае успеха</returns>
bool TrySave<T>(string key, T value); bool TrySave<T>(string key, T value);
/// <summary> /// <summary>
/// Удаление параметра /// Remove parameter by key
/// </summary> /// </summary>
/// <typeparam name="T">Тип параметра</typeparam> /// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Ключ</param> /// <param name="key">Key</param>
void Remove<T>(string key); void Remove<T>(string key);
/// <summary> /// <summary>
/// Безопасное удаление параметра /// Safe remove parameter by key
/// </summary> /// </summary>
/// <typeparam name="T">Тип параметра</typeparam> /// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Ключ</param> /// <param name="key">Key</param>
/// <returns>true - в случае успеха</returns>
bool TryRemove<T>(string key); bool TryRemove<T>(string key);
/// <summary> /// <summary>
/// Запрос сохраненного параметра /// Get parameter value by key
/// </summary> /// </summary>
/// <typeparam name="T">Тип параметра</typeparam> /// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Ключ</param> /// <param name="key">Key</param>
/// <returns>Значение параметра</returns> /// <returns>Parameter value</returns>
T Get<T>(string key); T Get<T>(string key);
T GetOrDefault<T>(string key); T GetOrDefault<T>(string key);
T GetOrDefault<T>(string key, T defaultValue); T GetOrDefault<T>(string key, T defaultValue);
/// <summary> /// <summary>
/// Запрос сохраненного параметра /// Get parameter value by key
/// </summary> /// </summary>
/// <param name="type">Тип параметра</param> /// <param name="type">Parameter type</param>
/// <param name="key">Ключ</param> /// <param name="key">Key</param>
/// <returns>Значение параметра</returns> /// <returns>Parameter value</returns>
object Get(Type type, string key); object Get(Type type, string key);
/// <summary> /// <summary>
/// Проверка наличия параметра с указанным именем /// Check for parameter existence by key
/// </summary> /// </summary>
/// <typeparam name="T">Тип параметра</typeparam> /// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Ключ</param> /// <param name="key">Key</param>
/// <returns>Указывает наличие параметра с заданным именем</returns>
bool Contains<T>(string key); bool Contains<T>(string key);
#endregion #endregion
} }

@ -1,91 +0,0 @@
using System;
namespace ZeroLevel.Patterns.DependencyInjection
{
/// <summary>
/// Интерфейс с методами для реализации паттерна пул объектов в контейнере
/// </summary>
public interface IPoolContainer
{
#region Register poolable dependencies
/// <summary>
/// Регистрация пула
/// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam>
/// <param name="initialCount">Начальное количество объектов в пуле</param>
/// <param name="capacity">Максимальное количество объектов в пуле (при -1 пул не ограничен)</param>
void RegisterPool<TContract>(int initialCount, int capacity);
/// <summary>
/// Регистрация разрешения зависимости
/// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam>
void RegisterPoolable<TContract, TImplementation>();
/// <summary>
/// Регистрация разрешения зависимости
/// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param>
void RegisterPoolable<TContract, TImplementation>(string resolveName);
/// <summary>
/// Регистрация разрешения зависимости
/// </summary>
/// <param name="contractType">Тип контракта</param>
/// <param name="implementationType">Тип разрешения</param>
void RegisterPoolable(Type contractType, Type implementationType);
/// <summary>
/// Регистрация разрешения зависимости
/// </summary>
/// <param name="contractType">Тип контракта</param>
/// <param name="implementationType">Тип разрешения</param>
/// <param name="resolveName">Имя разрешения зависимости</param>
void RegisterPoolable(Type contractType, Type implementationType, string resolveName);
/// <summary>
/// Регистрация разрешения зависимости
/// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam>
/// <param name="implementation">Экземпляр</param>
void RegisterPoolable<TContract>(TContract implementation);
/// <summary>
/// Регистрация разрешения зависимости
/// </summary>
/// <param name="contractType">Тип контракта</param>
/// <param name="implementation">Экземпляр</param>
void RegisterPoolable(Type contractType, object implementation);
#endregion
#region Register poolable parametrizied dependencies
/// <summary>
/// Регистрация разрешения зависимости с указанием параметров конструктора
/// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam>
/// <param name="constructorParameters">Аргументы конструктора</param>
void RegisterPoolableParametrizied<TContract, TImplementation>(object[] constructorParameters);
/// <summary>
/// Регистрация разрешения зависимости с указанием параметров конструктора
/// </summary>
/// <typeparam name="TContract">Тип контракта</typeparam>
/// <typeparam name="TImplementation">Тип разрешения</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param>
/// <param name="constructorParameters">Аргументы конструктора</param>
void RegisterPoolableParametrizied<TContract, TImplementation>(string resolveName, object[] constructorParameters);
/// <summary>
/// Регистрация разрешения зависимости с указанием параметров конструктора
/// </summary>
/// <param name="contractType">Тип контракта</param>
/// <param name="implementationType">Тип разрешения</param>
/// <param name="constructorParameters">Аргументы конструктора</param>
void RegisterPoolableParametrizied(Type contractType, Type implementationType, object[] constructorParameters);
/// <summary>
/// Регистрация разрешения зависимости с указанием параметров конструктора
/// </summary>
/// <param name="contractType">Тип контракта</param>
/// <param name="implementationType">Тип разрешения</param>
/// <param name="resolveName">Имя разрешения зависимости</param>
/// <param name="constructorParameters">Аргументы конструктора</param>
void RegisterPoolableParametrizied(Type contractType, Type implementationType, string resolveName, object[] constructorParameters);
#endregion
}
}

@ -3,107 +3,107 @@
namespace ZeroLevel.Patterns.DependencyInjection namespace ZeroLevel.Patterns.DependencyInjection
{ {
/// <summary> /// <summary>
/// Интерфейс с методами разрешений зависимостей /// Dependency resolver
/// </summary> /// </summary>
public interface IResolver public interface IResolver
{ {
#region Activator #region Activator
/// <summary> /// <summary>
/// Создание экземпляра объекта указанного типа /// Creating an instance of an object of the specified type
/// </summary> /// </summary>
/// <typeparam name="T">Тип объекта</typeparam> /// <typeparam name="T">Contract or instance type</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <returns>Экземпляр объекта</returns> /// <returns>Instance</returns>
T CreateInstance<T>(string resolveName = ""); T CreateInstance<T>(string resolveName = "");
/// <summary> /// <summary>
/// Создание экземпляра объекта указанного типа /// Creating an instance of an object of the specified type
/// </summary> /// </summary>
/// <typeparam name="T">Тип объекта</typeparam> /// <typeparam name="T">Contract or instance type</typeparam>
/// <param name="args">Аргументы конструктора</param> /// <param name="args">Ctor agrs</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <returns>Экземпляр объекта</returns> /// <returns>Instance</returns>
T CreateInstance<T>(object[] args, string resolveName = ""); T CreateInstance<T>(object[] args, string resolveName = "");
/// <summary> /// <summary>
/// Создание экземпляра объекта указанного типа /// Creating an instance of an object of the specified type
/// </summary> /// </summary>
/// <param name="type">Тип объекта</param> /// <param name="type">Contract or instance type</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <returns>Экземпляр объекта</returns> /// <returns>Instance</returns>
object CreateInstance(Type type, string resolveName = ""); object CreateInstance(Type type, string resolveName = "");
/// <summary> /// <summary>
/// Создание экземпляра объекта указанного типа /// Creating an instance of an object of the specified type
/// </summary> /// </summary>
/// <param name="type">Тип объекта</param> /// <param name="type">Contract or instance type</param>
/// <param name="args">Аргументы конструктора</param> /// <param name="args">Ctor agrs</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <returns>Экземпляр объекта</returns> /// <returns>Instance</returns>
object CreateInstance(Type type, object[] args, string resolveName = ""); object CreateInstance(Type type, object[] args, string resolveName = "");
#endregion #endregion
#region Resolving #region Resolving
/// <summary> /// <summary>
/// Разрешение зависимости /// Dependency resolve
/// </summary> /// </summary>
/// <typeparam name="T">Тип контракта</typeparam> /// <typeparam name="T">Contract</typeparam>
/// <param name="compose">Указание провести композицию при построении объектов</param> /// <param name="compose">Compose the object when true</param>
/// <returns>Инстанс</returns> /// <returns>Instance</returns>
T Resolve<T>(bool compose = true); T Resolve<T>(bool compose = true);
/// <summary> /// <summary>
/// Разрешение зависимости /// Dependency resolve
/// </summary> /// </summary>
/// <typeparam name="T">Тип контракта</typeparam> /// <typeparam name="T">Contract</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="compose">Указание провести композицию при построении объектов</param> /// <param name="compose">Compose the object when true</param>
/// <returns>Инстанс</returns> /// <returns>Instance</returns>
T Resolve<T>(string resolveName, bool compose = true); T Resolve<T>(string resolveName, bool compose = true);
/// <summary> /// <summary>
/// Разрешение зависимости /// Dependency resolve
/// </summary> /// </summary>
/// <typeparam name="T">Тип контракта</typeparam> /// <typeparam name="T">Contract</typeparam>
/// <param name="args">Аргументы конструктора</param> /// <param name="args">Ctor agrs</param>
/// <param name="compose">Указание провести композицию при построении объектов</param> /// <param name="compose">Compose the object when true</param>
/// <returns>Инстанс</returns> /// <returns>Instance</returns>
T Resolve<T>(object[] args, bool compose = true); T Resolve<T>(object[] args, bool compose = true);
/// <summary> /// <summary>
/// Разрешение зависимости /// Dependency resolve
/// </summary> /// </summary>
/// <typeparam name="T">Тип контракта</typeparam> /// <typeparam name="T">Contract</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="args">Аргументы конструктора</param> /// <param name="args">Ctor agrs</param>
/// <param name="compose">Указание провести композицию при построении объектов</param> /// <param name="compose">Compose the object when true</param>
/// <returns>Инстанс</returns> /// <returns>Instance</returns>
T Resolve<T>(string resolveName, object[] args, bool compose = true); T Resolve<T>(string resolveName, object[] args, bool compose = true);
/// <summary> /// <summary>
/// Разрешение зависимости /// Dependency resolve
/// </summary> /// </summary>
/// <param name="type">Тип контракта</param> /// <param name="type">Contract</param>
/// <param name="compose">Указание провести композицию при построении объектов</param> /// <param name="compose">Compose the object when true</param>
/// <returns>Инстанс</returns> /// <returns>Instance</returns>
object Resolve(Type type, bool compose = true); object Resolve(Type type, bool compose = true);
/// <summary> /// <summary>
/// Разрешение зависимости /// Dependency resolve
/// </summary> /// </summary>
/// <param name="type">Тип контракта</param> /// <param name="type">Contract</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="compose">Указание провести композицию при построении объектов</param> /// <param name="compose">Compose the object when true</param>
/// <returns>Инстанс</returns> /// <returns>Instance</returns>
object Resolve(Type type, string resolveName, bool compose = true); object Resolve(Type type, string resolveName, bool compose = true);
/// <summary> /// <summary>
/// Разрешение зависимости /// Dependency resolve
/// </summary> /// </summary>
/// <param name="type">Тип контракта</param> /// <param name="type">Contract</param>
/// <param name="args">Аргументы конструктора</param> /// <param name="args">Ctor agrs</param>
/// <param name="compose">Указание провести композицию при построении объектов</param> /// <param name="compose">Compose the object when true</param>
/// <returns>Инстанс</returns> /// <returns>Instance</returns>
object Resolve(Type type, object[] args, bool compose = true); object Resolve(Type type, object[] args, bool compose = true);
/// <summary> /// <summary>
/// Разрешение зависимости /// Dependency resolve
/// </summary> /// </summary>
/// <param name="type">Тип контракта</param> /// <param name="type">Contract</param>
/// <param name="resolveName">Имя разрешения зависимости</param> /// <param name="resolveName">Dependency name</param>
/// <param name="args">Аргументы конструктора</param> /// <param name="args">Ctor agrs</param>
/// <param name="compose">Указание провести композицию при построении объектов</param> /// <param name="compose">Compose the object when true</param>
/// <returns>Инстанс</returns> /// <returns>Instance</returns>
object Resolve(Type type, string resolveName, object[] args, bool compose = true); object Resolve(Type type, string resolveName, object[] args, bool compose = true);
#endregion #endregion

@ -6,7 +6,7 @@ using System.Reflection;
namespace ZeroLevel.Patterns.DependencyInjection namespace ZeroLevel.Patterns.DependencyInjection
{ {
/// <summary> /// <summary>
/// Метаданные конструктора /// Constructor metadata
/// </summary> /// </summary>
internal class ConstructorMetadata internal class ConstructorMetadata
{ {
@ -26,16 +26,16 @@ namespace ZeroLevel.Patterns.DependencyInjection
var resolveAttribute = p.GetCustomAttribute<ResolveAttribute>(); var resolveAttribute = p.GetCustomAttribute<ResolveAttribute>();
var kind = (parameterAttribute != null) ? ConstructorParameterKind.Parameter : var kind = (parameterAttribute != null) ? ConstructorParameterKind.Parameter :
(resolveAttribute != null) ? ConstructorParameterKind.Resolve : ConstructorParameterKind.None; (resolveAttribute != null) ? ConstructorParameterKind.Dependency : ConstructorParameterKind.None;
return new ConstructorParameter return new ConstructorParameter
{ {
Type = p.ParameterType, Type = p.ParameterType,
ParameterKind = kind, ParameterKind = kind,
ParameterResolveName = (kind == ConstructorParameterKind.Parameter) ? parameterAttribute?.Name ?? p.Name : 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 : 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) IsNullable = IsNullable(p.ParameterType)
}; };
}).ToList(); }).ToList();
@ -48,11 +48,11 @@ namespace ZeroLevel.Patterns.DependencyInjection
return false; // value-type return false; // value-type
} }
/// <summary> /// <summary>
/// Определение, подходит ли конструктор под указанные аргументы /// Determining whether the constructor is suitable for the specified arguments
/// </summary> /// </summary>
/// <param name="args">Аргументы</param> /// <param name="args">Arguments</param>
/// <param name="parameters">Подготовленные массив аргументов для вызова конструктора</param> /// <param name="parameters">Prepared arguments for constructor call</param>
/// <returns>true - если конструктор можно вызвать с переданными аргументами</returns> /// <returns>true - if the constructor can be called with the arguments passed</returns>
public bool IsMatch(object[] args, out object[] parameters) public bool IsMatch(object[] args, out object[] parameters)
{ {
parameters = null; parameters = null;
@ -67,7 +67,7 @@ namespace ZeroLevel.Patterns.DependencyInjection
case ConstructorParameterKind.Parameter: case ConstructorParameterKind.Parameter:
parameters[i] = _parent.Get(Parameters[i].ParameterResolveType, Parameters[i].ParameterResolveName); parameters[i] = _parent.Get(Parameters[i].ParameterResolveType, Parameters[i].ParameterResolveName);
break; break;
case ConstructorParameterKind.Resolve: case ConstructorParameterKind.Dependency:
parameters[i] = _parent.Resolve(Parameters[i].ParameterResolveType, Parameters[i].ParameterResolveName); parameters[i] = _parent.Resolve(Parameters[i].ParameterResolveType, Parameters[i].ParameterResolveName);
break; break;
default: default:

@ -3,47 +3,47 @@
namespace ZeroLevel.Patterns.DependencyInjection namespace ZeroLevel.Patterns.DependencyInjection
{ {
/// <summary> /// <summary>
/// Тип аргумента конструктора в контексте иньекции зависимостей /// Constructor argument type
/// </summary> /// </summary>
internal enum ConstructorParameterKind internal enum ConstructorParameterKind
{ {
/// <summary> /// <summary>
/// Аргумент задается из переданных значений /// Constant
/// </summary> /// </summary>
None, None,
/// <summary> /// <summary>
/// Аргумент задается из параметров контейнера /// DI parameter
/// </summary> /// </summary>
Parameter, Parameter,
/// <summary> /// <summary>
/// Аргумент задается разрешением зависимости /// Dependency
/// </summary> /// </summary>
Resolve Dependency
} }
/// <summary> /// <summary>
/// Метаданные для описания аргумента конструктора /// Constructor argument metadata
/// </summary> /// </summary>
internal sealed class ConstructorParameter internal sealed class ConstructorParameter
{ {
/// <summary> /// <summary>
/// Тип аргумента в рамках DI /// Argument DI-type
/// </summary> /// </summary>
public ConstructorParameterKind ParameterKind; public ConstructorParameterKind ParameterKind;
/// <summary> /// <summary>
/// Тип для определения аргумента через DI /// Argument contract type
/// </summary> /// </summary>
public Type ParameterResolveType; public Type ParameterResolveType;
/// <summary> /// <summary>
/// Имя для определения аргумента через DI /// Dependency name
/// </summary> /// </summary>
public string ParameterResolveName; public string ParameterResolveName;
/// <summary> /// <summary>
/// Флаг определяющий допустимость записи null в качестве значения аргумента /// Allow null
/// </summary> /// </summary>
public bool IsNullable; public bool IsNullable;
/// <summary> /// <summary>
/// Тип аргумента /// Argument CLR type
/// </summary> /// </summary>
public Type Type; public Type Type;
} }

@ -1,9 +0,0 @@
namespace ZeroLevel.Patterns.DependencyInjection
{
public interface IPoolable<T>
{
T Instance { get; }
void Cleanup();
void Release();
}
}

@ -4,40 +4,40 @@ using System.Collections.Generic;
namespace ZeroLevel.Patterns.DependencyInjection namespace ZeroLevel.Patterns.DependencyInjection
{ {
/// <summary> /// <summary>
/// Метаданные разрешения зависимости /// Dependency resolving metadata
/// </summary> /// </summary>
internal sealed class ResolveTypeInfo internal sealed class ResolveTypeInfo
{ {
/// <summary> /// <summary>
/// Разрешение зависимости по умолчанию /// Default - without dependency name
/// </summary> /// </summary>
public bool IsDefault; public bool IsDefault;
/// <summary> /// <summary>
/// Создается только один экземпляр (в случае true) /// Singletone when true
/// </summary> /// </summary>
public bool IsShared; public bool IsShared;
/// <summary> /// <summary>
/// Тип инстанса (в том числе обобщенный) /// Instance type (may be generic)
/// </summary> /// </summary>
public Type ImplementationType; public Type ImplementationType;
/// <summary> /// <summary>
/// Ключ определения зависимости /// Dependency resolving key
/// </summary> /// </summary>
public string ResolveKey; public string ResolveKey;
/// <summary> /// <summary>
/// Кэш экземпляра /// Instance cache
/// </summary> /// </summary>
public object SharedInstance; public object SharedInstance;
/// <summary> /// <summary>
/// Кэш обобщенных типов /// Generic types cahce
/// </summary> /// </summary>
public Dictionary<Type, Type> GenericCachee; public Dictionary<Type, Type> GenericCachee;
/// <summary> /// <summary>
/// Кэш обобщенных экземпляров /// Generic instances cahce
/// </summary> /// </summary>
public Dictionary<Type, object> GenericInstanceCachee; public Dictionary<Type, object> GenericInstanceCachee;
/// <summary> /// <summary>
/// Параметры конструктора объекта /// Constructor parameters
/// </summary> /// </summary>
public object[] ConstructorParameters; public object[] ConstructorParameters;
} }

@ -6,7 +6,7 @@ namespace ZeroLevel.Services.Drawing
{ {
public static class TextPainter public static class TextPainter
{ {
#region Отрисовка текста вдоль линий #region Drawing text along lines
public static void DrawOnSegment(Graphics gr, Font font, public static void DrawOnSegment(Graphics gr, Font font,
PointF start_point, PointF start_point,
PointF end_point, PointF end_point,

@ -6,7 +6,7 @@ namespace ZeroLevel
public static class ArrayExtensions public static class ArrayExtensions
{ {
/// <summary> /// <summary>
/// Глубокое копирование массива /// Deep copy array
/// </summary> /// </summary>
public static T[] DeepCopy<T>(this T[] array) public static T[] DeepCopy<T>(this T[] array)
where T : ICloneable where T : ICloneable
@ -38,10 +38,8 @@ namespace ZeroLevel
} }
} }
/// <summary> /// <summary>
/// Проверяет вхождение одного массива в другой /// Checks whether one array is in another
/// </summary> /// </summary>
/// <typeparam name="T">Тиа элементов массивов</typeparam>
/// <returns>true - массив содержит указанный подмассив</returns>
public static bool Contains<T>(this T[] array, T[] candidate) public static bool Contains<T>(this T[] array, T[] candidate)
{ {
if (IsEmptyLocate(array, candidate)) if (IsEmptyLocate(array, candidate))

@ -24,7 +24,7 @@ namespace ZeroLevel
} }
/// <summary> /// <summary>
/// Проверяет на одинаковое содержание коллекции строк, в том числе по разному отсортированные /// Checks for the same content of a collection of strings, including sorted in different ways
/// </summary> /// </summary>
public static bool StringEnumerableEquals(this IEnumerable<string> A, IEnumerable<string> B) public static bool StringEnumerableEquals(this IEnumerable<string> A, IEnumerable<string> B)
{ {
@ -34,7 +34,7 @@ namespace ZeroLevel
} }
/// <summary> /// <summary>
/// Проверяет на одинаковое содержание коллекций, в том числе по разному отсортированных /// Checks for the same content of collections, including sorted in different ways
/// </summary> /// </summary>
public static bool NoOrderingEquals<T>(this IEnumerable<T> A, IEnumerable<T> B) public static bool NoOrderingEquals<T>(this IEnumerable<T> A, IEnumerable<T> B)
{ {
@ -51,7 +51,7 @@ namespace ZeroLevel
} }
/// <summary> /// <summary>
/// Проверяет на одинаковое содержание коллекций /// Checks for the same content collections
/// </summary> /// </summary>
public static bool OrderingEquals<T>(this IEnumerable<T> A, IEnumerable<T> B) public static bool OrderingEquals<T>(this IEnumerable<T> A, IEnumerable<T> B)
{ {
@ -85,7 +85,7 @@ namespace ZeroLevel
return true; return true;
} }
/// <summary> /// <summary>
/// Расчет хеша для коллекции /// Calculate hash for collection
/// </summary> /// </summary>
public static int GetEnumHashCode<T>(this IEnumerable<T> A) public static int GetEnumHashCode<T>(this IEnumerable<T> A)
{ {

@ -5,10 +5,8 @@ namespace ZeroLevel
public static class DateTimeExtensions public static class DateTimeExtensions
{ {
/// <summary> /// <summary>
/// Огругляет дату до указанного масштаба /// Rounds the date to the specified scale.
/// /// Example: sqlserver - Datetime values are rounded to increments of .000, .003, or .007 seconds
/// Необходимость: округление дат при сохранении в модель, которая будет использоваться для SqlServer,
/// т.к. sqlserver не может точность - Datetime values are rounded to increments of .000, .003, or .007 seconds
/// </summary> /// </summary>
public static DateTime Truncate(this DateTime dateTime, TimeSpan timeSpan) public static DateTime Truncate(this DateTime dateTime, TimeSpan timeSpan)
{ {

@ -4,7 +4,7 @@ using System.Runtime.Serialization;
namespace ZeroLevel.Services.Extensions namespace ZeroLevel.Services.Extensions
{ {
/// <summary> /// <summary>
/// Обобщенные возможности из ФП /// FP
/// </summary> /// </summary>
public static class FPCommon public static class FPCommon
{ {

@ -2,9 +2,6 @@
namespace ZeroLevel namespace ZeroLevel
{ {
/// <summary>
/// Сборник монад
/// </summary>
public static class Monades public static class Monades
{ {
#region With #region With

@ -42,12 +42,12 @@ namespace ZeroLevel.Services.FileSystem
} }
/// <summary> /// <summary>
/// Задает права доступа к каталогу для учетной записи /// Sets the directory permissions for the account
/// </summary> /// </summary>
/// <param name="folderPath">Путь к каталогу</param> /// <param name="folderPath">Directory path</param>
/// <param name="account">Аккаунт</param> /// <param name="account">Account</param>
/// <param name="right">Права доступа</param> /// <param name="right">Access rights</param>
/// <param name="controlType">Тип доступа</param> /// <param name="controlType">Access type</param>
public static void SetupFolderPermission(string folderPath, string account, public static void SetupFolderPermission(string folderPath, string account,
FileSystemRights right, AccessControlType controlType) 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_path_characters = new string(Path.GetInvalidPathChars());
private static string _invalid_filename_characters = new string(Path.GetInvalidFileNameChars()); private static string _invalid_filename_characters = new string(Path.GetInvalidFileNameChars());
/// <summary> /// <summary>
/// Удаляет из переданного пути недопустимые символы /// Removes invalid characters from the passed path
/// </summary> /// </summary>
public static string PathCorrection(string path) public static string PathCorrection(string path)
{ {
@ -82,7 +82,7 @@ namespace ZeroLevel.Services.FileSystem
return new string(result, 0, index); return new string(result, 0, index);
} }
/// <summary> /// <summary>
/// Удаляет из переданного имени файла недопустимые символы /// Removes invalid characters from the passed file name
/// </summary> /// </summary>
/// <param name="path"></param> /// <param name="path"></param>
/// <returns></returns> /// <returns></returns>
@ -105,7 +105,7 @@ namespace ZeroLevel.Services.FileSystem
#endregion #endregion
/// <summary> /// <summary>
/// Выполняет проверку на доступность файла для обработки /// Performs a file accessibility check for processing
/// </summary> /// </summary>
public static bool IsFileLocked(FileInfo file) public static bool IsFileLocked(FileInfo file)
{ {

@ -227,20 +227,20 @@ namespace ZeroLevel.Services.FileSystem
} while (_disposed == false); } while (_disposed == false);
} }
/// <summary> /// <summary>
/// Сохранение текста в архив /// Save text to archive
/// </summary> /// </summary>
/// <param name="text">Текст</param> /// <param name="text">Text</param>
/// <param name="subfolder_name">Имя файла в архиве (по умолчанию HH_mm_ss_fff_counter.{ext})</param> /// <param name="subfolder_name">Archive file name (HH_mm_ss_fff_counter.{ext} by default)</param>
/// <returns></returns> /// <returns></returns>
public void StoreText(string text, string subfolder_name = null, string file_name = null) public void StoreText(string text, string subfolder_name = null, string file_name = null)
{ {
Apply(new StoreText(text, CreateArchiveFilePath(subfolder_name, file_name))); Apply(new StoreText(text, CreateArchiveFilePath(subfolder_name, file_name)));
} }
/// <summary> /// <summary>
/// Сохранение указанного файла в архив /// Saving the specified file to the archive
/// </summary> /// </summary>
/// <param name="file_path">Путь к файлу</param> /// <param name="file_path">File path</param>
/// <param name="subfolder_name">Имя файла в архиве (по умолчанию оригинальное имя файла)</param> /// <param name="subfolder_name">Archive file name (original file name by default)</param>
/// <returns></returns> /// <returns></returns>
public void Store(string file_path, string subfolder_name = null, string file_name = null) public void Store(string file_path, string subfolder_name = null, string file_name = null)
{ {
@ -259,20 +259,20 @@ namespace ZeroLevel.Services.FileSystem
} }
} }
/// <summary> /// <summary>
/// Сохранение данных из потока в архив /// Saving data from stream to archive
/// </summary> /// </summary>
/// <param name="stream">Поток с данными для чтения</param> /// <param name="stream">Data stream for reading</param>
/// <param name="subfolder_name">Имя файла в архиве (по умолчанию HH_mm_ss_fff_counter.{ext})</param> /// <param name="subfolder_name">Archive file name (HH_mm_ss_fff_counter.{ext} by default)</param>
/// <returns></returns> /// <returns></returns>
public void Store(Stream stream, string subfolder_name = null, string file_name = null) public void Store(Stream stream, string subfolder_name = null, string file_name = null)
{ {
Apply(new StoreStream(stream, CreateArchiveFilePath(subfolder_name, file_name))); Apply(new StoreStream(stream, CreateArchiveFilePath(subfolder_name, file_name)));
} }
/// <summary> /// <summary>
/// Сохранение данных в бинарном виде в архив /// Saving data in binary form in the archive
/// </summary> /// </summary>
/// <param name="data">Данные</param> /// <param name="data">Data</param>
/// <param name="subfolder_name">Имя файла в архиве (по умолчанию HH_mm_ss_fff_counter.{ext})</param> /// <param name="subfolder_name">Archive file name (HH_mm_ss_fff_counter.{ext} by default)</param>
/// <returns></returns> /// <returns></returns>
public void StoreData(byte[] data, string subfolder_name = null, string file_name = null) 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) if (Directory.Exists(path) == false)
{ {
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
FSUtils.SetupFolderPermission(path, FSUtils.SetupFolderPermission(path,$"{Environment.UserDomainName}\\{Environment.UserName}",
string.Format("{0}\\{1}", Environment.UserDomainName, Environment.UserName),
FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify, FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify,
AccessControlType.Allow); AccessControlType.Allow);
} }
@ -398,31 +397,31 @@ namespace ZeroLevel.Services.FileSystem
} }
} }
/// <summary> /// <summary>
/// Сохранение текста в архив /// Save text to archive
/// </summary> /// </summary>
/// <param name="text">Текст</param> /// <param name="text">Text</param>
/// <param name="name">Имя файла в архиве (по умолчанию HH_mm_ss_fff_counter.{ext})</param> /// <param name="name">Archive file name (HH_mm_ss_fff_counter.{ext} by default)</param>
/// <returns></returns> /// <returns></returns>
public void StoreText(string text, string name = null) public void StoreText(string text, string name = null)
{ {
Apply(new StoreText(text, CreateArchiveFilePath(name))); Apply(new StoreText(text, CreateArchiveFilePath(name)));
} }
/// <summary> /// <summary>
/// Сохранение указанного файла в архив /// Saving the specified file to the archive
/// </summary> /// </summary>
/// <param name="file_path">Путь к файлу</param> /// <param name="file_path">File path</param>
/// <param name="name">Имя файла в архиве (по умолчанию оригинальное имя файла)</param> /// <param name="subfolder_name">Archive file name (original file name by default)</param>
/// <returns></returns> /// <returns></returns>
public void Store(string file_path, string name = null) public void Store(string file_path, string name = null)
{ {
Apply(new StoreFile(file_path, CreateArchiveFilePath(name))); Apply(new StoreFile(file_path, CreateArchiveFilePath(name)));
} }
/// <summary> /// <summary>
/// охранение указанного файла в архив, синхронно /// Sync saving the specified file to the archive
/// </summary> /// </summary>
/// <param name="file_path"></param> /// <param name="file_path">File path</param>
/// <param name="immediate"></param> /// <param name="subfolder_name">Archive file name (original file name by default)</param>
/// <param name="name"></param> /// <returns></returns>
public void Store(string file_path, bool immediate, string name = null) public void Store(string file_path, bool immediate, string name = null)
{ {
if (immediate) if (immediate)
@ -435,10 +434,10 @@ namespace ZeroLevel.Services.FileSystem
} }
} }
/// <summary> /// <summary>
/// Сохранение данных из потока в архив /// Saving data from stream to archive
/// </summary> /// </summary>
/// <param name="stream">Поток с данными для чтения</param> /// <param name="stream">Data stream for reading</param>
/// <param name="name">Имя файла в архиве (по умолчанию HH_mm_ss_fff_counter.{ext})</param> /// <param name="name">Archive file name (HH_mm_ss_fff_counter.{ext} by default)</param>
/// <returns></returns> /// <returns></returns>
public void Store(Stream stream, string name = null) public void Store(Stream stream, string name = null)
{ {
@ -447,8 +446,8 @@ namespace ZeroLevel.Services.FileSystem
/// <summary> /// <summary>
/// Сохранение данных в бинарном виде в архив /// Сохранение данных в бинарном виде в архив
/// </summary> /// </summary>
/// <param name="data">Данные</param> /// <param name="data">Data</param>
/// <param name="name">Имя файла в архиве (по умолчанию HH_mm_ss_fff_counter.{ext})</param> /// <param name="name">Archive file name (HH_mm_ss_fff_counter.{ext} by default)</param>
/// <returns></returns> /// <returns></returns>
public void StoreData(byte[] data, string name = null) public void StoreData(byte[] data, string name = null)
{ {
@ -475,7 +474,7 @@ namespace ZeroLevel.Services.FileSystem
{ {
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
FSUtils.SetupFolderPermission(path, FSUtils.SetupFolderPermission(path,
string.Format("{0}\\{1}", Environment.UserDomainName, Environment.UserName), $"{Environment.UserDomainName}\\{Environment.UserName}",
FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify, FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify,
AccessControlType.Allow); AccessControlType.Allow);
} }

@ -72,7 +72,7 @@ namespace ZeroLevel.Services.FileSystem
} }
catch (Exception ex) 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; continue;
} }
Log.Debug($"[PeriodicFileSystemWatcher] Handle file {file}"); Log.Debug($"[PeriodicFileSystemWatcher] Handle file {file}");
@ -87,12 +87,12 @@ namespace ZeroLevel.Services.FileSystem
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.SystemError(ex, "Сбой при обработке входного каталога '{0}'", _sourceFolder); Log.SystemError(ex, $"[PeriodicFileSystemWatcher] Failed to process input directory '{_sourceFolder}'");
} }
} }
/// <summary> /// <summary>
/// Перемещение файла во временный каталог /// Moving a file to a temporary directory
/// </summary> /// </summary>
public string MoveToTemporary(string from) public string MoveToTemporary(string from)
{ {
@ -110,8 +110,7 @@ namespace ZeroLevel.Services.FileSystem
return tempFile; return tempFile;
} }
/// <summary> /// <summary>
/// Разрешение коллизий в именах файлов во временном каталоге /// Resolving collisions in filenames in the temporary directory
/// (требуется если в источнике могут появляться файлы в разное время с одинаковыми именами)
/// </summary> /// </summary>
private static string TrySolveCollision(string file) private static string TrySolveCollision(string file)
{ {
@ -141,7 +140,7 @@ namespace ZeroLevel.Services.FileSystem
throw new ArgumentException("folder"); throw new ArgumentException("folder");
} }
/// <summary> /// <summary>
/// Получение списка файлов из входного каталога /// Getting a list of files from the input directory
/// </summary> /// </summary>
public string[] GetFilesFromSource() public string[] GetFilesFromSource()
{ {
@ -150,7 +149,7 @@ namespace ZeroLevel.Services.FileSystem
return files; return files;
} }
/// <summary> /// <summary>
/// Сравнение названий файлов /// File Name Comparison
/// </summary> /// </summary>
private static int FileNameSortCompare(string x, string y) private static int FileNameSortCompare(string x, string y)
{ {

@ -3,7 +3,7 @@
namespace ZeroLevel.Services.Impersonation namespace ZeroLevel.Services.Impersonation
{ {
/// <summary> /// <summary>
/// Интерфейс для классов исполняющих произвольный код от прав пользователя или процесса /// Interface for classes executing code from user or process rights
/// </summary> /// </summary>
public interface IImpersonationExecutor public interface IImpersonationExecutor
{ {

@ -7,7 +7,7 @@ using System.Security.Principal;
namespace ZeroLevel.Services.Impersonation namespace ZeroLevel.Services.Impersonation
{ {
/// <summary> /// <summary>
/// Класс реализует перевод исполнения программы на права указанного пользователя /// The class implements the translation of the program execution to the rights of the specified user.
/// </summary> /// </summary>
[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)] [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")] [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
@ -17,20 +17,20 @@ namespace ZeroLevel.Services.Impersonation
#region Private methods #region Private methods
/// <summary> /// <summary>
/// Назначение текущему процессу прав от указанного процесса, путем копирования его токена /// Assigning rights to the current process from the specified process, by copying its token
/// </summary> /// </summary>
/// <param name="hProcess">Указатель на процесс</param> /// <param name="hProcess">Process pointer</param>
private void ImpersonateByProcess(IntPtr hProcess) private void ImpersonateByProcess(IntPtr hProcess)
{ {
MySafeTokenHandle token; MySafeTokenHandle token;
if (!ImpersonationNativeMethods.OpenProcessToken(hProcess, ImpersonationNativeMethods.TokenDesiredAccess.TOKEN_DUPLICATE, out 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); ImpersonateToken(token);
} }
/// <summary> /// <summary>
/// Метод назначает текущему процессу дубликат переданного токена /// The method assigns a duplicate token to the current process.
/// </summary> /// </summary>
/// <param name="token">Токен</param> /// <param name="token">Token</param>
private void ImpersonateToken(MySafeTokenHandle token) private void ImpersonateToken(MySafeTokenHandle token)
{ {
MySafeTokenHandle tokenDuplicate; MySafeTokenHandle tokenDuplicate;
@ -50,19 +50,19 @@ namespace ZeroLevel.Services.Impersonation
} }
} }
else 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 #endregion
#region Public methods #region Public methods
/// <summary> /// <summary>
/// Вход от имени указанного пользователя /// Login as a specified user
/// </summary> /// </summary>
/// <param name="userName">Имя пользователя</param> /// <param name="userName">User name</param>
/// <param name="domain">Домен</param> /// <param name="domain">User domain</param>
/// <param name="password">Пароль</param> /// <param name="password">User password</param>
/// <returns>false - если не удалось выполнить вход по указанным данным</returns> /// <returns>false - if failed to log in with the specified data</returns>
public void ImpersonateByUser(String userName, String domain, String password) public void ImpersonateByUser(String userName, String domain, String password)
{ {
MySafeTokenHandle token; MySafeTokenHandle token;
@ -111,9 +111,9 @@ namespace ZeroLevel.Services.Impersonation
} }
} }
/// <summary> /// <summary>
/// Копирование прав указанного процесса /// Copying the rights of the specified process
/// </summary> /// </summary>
/// <param name="ProcessID">Идентификатор процесса</param> /// <param name="ProcessID">Process id</param>
public void ImpersonateByProcess(int ProcessID) public void ImpersonateByProcess(int ProcessID)
{ {
Process[] myProcesses = Process.GetProcesses(); Process[] myProcesses = Process.GetProcesses();
@ -129,7 +129,7 @@ namespace ZeroLevel.Services.Impersonation
#endregion #endregion
/// <summary> /// <summary>
/// При освобождении рессурсов вернем предыдущего пользователя /// When releasing resources, we will return the previous user right
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {

@ -10,7 +10,7 @@ namespace ZeroLevel.Services.Impersonation
{ {
#region P/Invoke enums #region P/Invoke enums
/// <summary> /// <summary>
/// Провайдер авторизации /// Authorization provider
/// </summary> /// </summary>
public enum LogonProvider : int public enum LogonProvider : int
{ {
@ -23,7 +23,7 @@ namespace ZeroLevel.Services.Impersonation
LOGON32_PROVIDER_DEFAULT = 0, LOGON32_PROVIDER_DEFAULT = 0,
} }
/// <summary> /// <summary>
/// Способ авторизации /// Authorization method
/// </summary> /// </summary>
public enum LogonType : int public enum LogonType : int
{ {
@ -74,7 +74,7 @@ namespace ZeroLevel.Services.Impersonation
LOGON32_LOGON_NEW_CREDENTIALS = 9, LOGON32_LOGON_NEW_CREDENTIALS = 9,
} }
/// <summary> /// <summary>
/// Желаемый уровень доступа к токену /// Desired access level to token
/// </summary> /// </summary>
public struct TokenDesiredAccess public struct TokenDesiredAccess
{ {
@ -82,7 +82,7 @@ namespace ZeroLevel.Services.Impersonation
public static uint STANDARD_RIGHTS_READ = 0x00020000; public static uint STANDARD_RIGHTS_READ = 0x00020000;
public static uint TOKEN_ASSIGN_PRIMARY = 0x0001; public static uint TOKEN_ASSIGN_PRIMARY = 0x0001;
/// <summary> /// <summary>
/// Позволяет создать копию /// Allows to create a copy
/// </summary> /// </summary>
public static uint TOKEN_DUPLICATE = 0x0002; public static uint TOKEN_DUPLICATE = 0x0002;
public static uint TOKEN_IMPERSONATE = 0x0004; public static uint TOKEN_IMPERSONATE = 0x0004;
@ -99,7 +99,7 @@ namespace ZeroLevel.Services.Impersonation
TOKEN_ADJUST_SESSIONID); TOKEN_ADJUST_SESSIONID);
} }
/// <summary> /// <summary>
/// Тип безопасности применяется при операции дублирования токена(в текущей задаче) /// The security type is used during the token duplication operation (in the current task)
/// </summary> /// </summary>
public enum SecurityImpersonationLevel : int public enum SecurityImpersonationLevel : int
{ {
@ -132,14 +132,14 @@ namespace ZeroLevel.Services.Impersonation
#region P/Invoke #region P/Invoke
/// <summary> /// <summary>
/// Авторизация от имени указанного пользователя /// Authorization on behalf of the specified user
/// </summary> /// </summary>
/// <param name="lpszUserName">Имя пользователя</param> /// <param name="lpszUserName">Username</param>
/// <param name="lpszDomain">Домен в котором зарегистрирован пользователь</param> /// <param name="lpszDomain">Domain</param>
/// <param name="lpszPassword">Пароль</param> /// <param name="lpszPassword">Password</param>
/// <param name="dwLogonType">Тип авторизации</param> /// <param name="dwLogonType">Authorization Type</param>
/// <param name="dwLogonProvider">Провайдер (всегда 0)</param> /// <param name="dwLogonProvider">Provider (always 0)</param>
/// <param name="phToken">Токен - результат входа</param> /// <param name="phToken">Token - login result</param>
/// <returns></returns> /// <returns></returns>
[DllImport("advapi32.dll")] [DllImport("advapi32.dll")]
internal static extern int LogonUserA(String lpszUserName, internal static extern int LogonUserA(String lpszUserName,
@ -149,9 +149,9 @@ namespace ZeroLevel.Services.Impersonation
int dwLogonProvider, int dwLogonProvider,
out MySafeTokenHandle phToken); out MySafeTokenHandle phToken);
/// <summary> /// <summary>
/// Создание дубликата токена /// Creating a duplicate token
/// </summary> /// </summary>
/// <param name="hToken">Исходный токен</param> /// <param name="hToken">Original token</param>
/// <param name="impersonationLevel"></param> /// <param name="impersonationLevel"></param>
/// <param name="hNewToken"></param> /// <param name="hNewToken"></param>
/// <returns></returns> /// <returns></returns>
@ -164,11 +164,11 @@ namespace ZeroLevel.Services.Impersonation
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal static extern bool CloseHandle(IntPtr handle); internal static extern bool CloseHandle(IntPtr handle);
/// <summary> /// <summary>
/// Попытка получения токена работающего процесса /// Attempt to get a token running process
/// </summary> /// </summary>
/// <param name="ProcessHandle">Указатель на процесс</param> /// <param name="ProcessHandle">Process pointer</param>
/// <param name="DesiredAccess"></param> /// <param name="DesiredAccess"></param>
/// <param name="TokenHandle">Токен - результат</param> /// <param name="TokenHandle">Token - result</param>
/// <returns></returns> /// <returns></returns>
[DllImport("advapi32.dll", SetLastError = true)] [DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]

@ -5,7 +5,7 @@ using System.Security.Permissions;
namespace ZeroLevel.Services.Impersonation namespace ZeroLevel.Services.Impersonation
{ {
/// <summary> /// <summary>
/// Реализация безопасного указателя /// Implementing a safe pointer
/// </summary> /// </summary>
[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)] [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)] [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]

@ -3,7 +3,7 @@
namespace ZeroLevel.Services.Impersonation namespace ZeroLevel.Services.Impersonation
{ {
/// <summary> /// <summary>
/// Реализует исполнение произвольного кода от прав указанного процесса /// Implements the execution of an code from the rights of the specified process
/// </summary> /// </summary>
public class ProcessImpersonationExecutor public class ProcessImpersonationExecutor
: IImpersonationExecutor : IImpersonationExecutor
@ -21,11 +21,8 @@ namespace ZeroLevel.Services.Impersonation
_pid = pid; _pid = pid;
} }
/// <summary> /// <summary>
/// Исполнение кода /// Code execution
/// </summary> /// </summary>
/// <typeparam name="T">Тип передаваемого аргумента</typeparam>
/// <param name="action">Делегат</param>
/// <param name="arg">Аргумент</param>
public void ExecuteCode<T>(Action<T> action, T arg) public void ExecuteCode<T>(Action<T> action, T arg)
{ {
using (Impersonation imp = new Impersonation()) using (Impersonation imp = new Impersonation())
@ -40,16 +37,14 @@ namespace ZeroLevel.Services.Impersonation
} }
else 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); action(arg);
} }
} }
/// <summary> /// <summary>
/// Исполнение кода /// Code execution
/// </summary> /// </summary>
/// <typeparam name="T">Тип передаваемого аргумента</typeparam>
/// <param name="action">Делегат</param>
public void ExecuteCode(Action action) public void ExecuteCode(Action action)
{ {
using (Impersonation imp = new Impersonation()) using (Impersonation imp = new Impersonation())
@ -64,7 +59,7 @@ namespace ZeroLevel.Services.Impersonation
} }
else 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(); action();
} }

@ -3,7 +3,7 @@
namespace ZeroLevel.Services.Impersonation namespace ZeroLevel.Services.Impersonation
{ {
/// <summary> /// <summary>
/// Класс исполняющий произвольный код с правами указанного пользователя /// Class executing code with the rights of the specified user
/// </summary> /// </summary>
public class UserImpersonationExecutor public class UserImpersonationExecutor
: IImpersonationExecutor : IImpersonationExecutor
@ -22,11 +22,8 @@ namespace ZeroLevel.Services.Impersonation
} }
/// <summary> /// <summary>
/// Исполнение кода /// Code execution
/// </summary> /// </summary>
/// <typeparam name="T">Тип передаваемого аргумента</typeparam>
/// <param name="action">Делегат</param>
/// <param name="arg">Аргумент</param>
public void ExecuteCode<T>(Action<T> action, T arg) public void ExecuteCode<T>(Action<T> action, T arg)
{ {
using (Impersonation imp = new Impersonation()) using (Impersonation imp = new Impersonation())
@ -36,10 +33,8 @@ namespace ZeroLevel.Services.Impersonation
} }
} }
/// <summary> /// <summary>
/// Исполнение кода /// Code execution
/// </summary> /// </summary>
/// <typeparam name="T">Тип передаваемого аргумента</typeparam>
/// <param name="action">Делегат</param>
public void ExecuteCode(Action action) public void ExecuteCode(Action action)
{ {
using (Impersonation imp = new Impersonation()) using (Impersonation imp = new Impersonation())

@ -8,31 +8,31 @@ using System.Text;
namespace ZeroLevel.Services.Invokation namespace ZeroLevel.Services.Invokation
{ {
/// <summary> /// <summary>
/// Обертка для вызова методов /// Method call wrapper
/// </summary> /// </summary>
public class InvokeWrapper : IInvokeWrapper public class InvokeWrapper : IInvokeWrapper
{ {
/// <summary> /// <summary>
/// Кэш делегатов /// Cahce
/// </summary> /// </summary>
protected readonly Dictionary<string, Invoker> _invokeCachee = new Dictionary<string, Invoker>(); protected readonly Dictionary<string, Invoker> _invokeCachee = new Dictionary<string, Invoker>();
#region Static helpers #region Static helpers
/// <summary> /// <summary>
/// Создает скомпилированное выражение для быстрого вызова метода, возвращает идентификатор выражения и делегат для вызова /// Creates a compiled expression for a quick method call, returns the identifier of the expression and a delegate for the call.
/// </summary> /// </summary>
/// <param name="method">Оборачиваемый метод</param> /// <param name="method">Wrapped method</param>
/// <returns>Кортеж с идентификатором выражения и делегатом</returns> /// <returns>Expression ID and Delegate Tuple</returns>
protected static Tuple<string, Invoker> CreateCompiledExpression(MethodInfo method) protected static Tuple<string, Invoker> CreateCompiledExpression(MethodInfo method)
{ {
var targetArg = Expression.Parameter(typeof(object)); // Цель на которой происходит вызов var targetArg = Expression.Parameter(typeof(object));
var argsArg = Expression.Parameter(typeof(object[])); // Аргументы метода var argsArg = Expression.Parameter(typeof(object[]));
var parameters = method.GetParameters(); var parameters = method.GetParameters();
Expression body = Expression.Call( Expression body = Expression.Call(
method.IsStatic method.IsStatic
? null ? null
: Expression.Convert(targetArg, method.DeclaringType), // тип в котором объявлен метод : Expression.Convert(targetArg, method.DeclaringType), // the type in which the method is declared
method, method,
parameters.Select((p, i) => parameters.Select((p, i) =>
Expression.Convert(Expression.ArrayIndex(argsArg, Expression.Constant(i)), p.ParameterType))); Expression.Convert(Expression.ArrayIndex(argsArg, Expression.Constant(i)), p.ParameterType)));
@ -46,10 +46,10 @@ namespace ZeroLevel.Services.Invokation
} }
/// <summary> /// <summary>
/// Оборачивает вызов делегата /// Wraps Delegate Call
/// </summary> /// </summary>
/// <param name="handler">Оборачиваемый делегат</param> /// <param name="handler">Wrapped delegate</param>
/// <returns>Кортеж с идентификатором выражения и делегатом</returns> /// <returns>Expression ID and Delegate Tuple</returns>
protected static Tuple<string, Invoker> CreateCompiledExpression(Delegate handler) protected static Tuple<string, Invoker> CreateCompiledExpression(Delegate handler)
{ {
return CreateCompiledExpression(handler.GetMethodInfo()); return CreateCompiledExpression(handler.GetMethodInfo());
@ -60,10 +60,10 @@ namespace ZeroLevel.Services.Invokation
#region Helpers #region Helpers
/// <summary> /// <summary>
/// Идентификатр однозначно определяющий метод на уровне типа (но не на глобальном уровне) /// ID uniquely identifying method at the type level (but not at the global level)
/// </summary> /// </summary>
/// <param name="name">Имя метода</param> /// <param name="name">Method name</param>
/// <param name="argsTypes">Типы аргументов метода</param> /// <param name="argsTypes">Method Argument Types</param>
/// <returns></returns> /// <returns></returns>
internal static string CreateMethodIdentity(string name, params Type[] argsTypes) internal static string CreateMethodIdentity(string name, params Type[] argsTypes)
{ {
@ -190,10 +190,10 @@ namespace ZeroLevel.Services.Invokation
#region Configure by MethodInfo #region Configure by MethodInfo
/// <summary> /// <summary>
/// Вносит в кэш вызов указанного метода /// Cache the specified method
/// </summary> /// </summary>
/// <param name="method">Метод</param> /// <param name="method">Method</param>
/// <returns>Идентификатор для вызова</returns> /// <returns>Call ID</returns>
public string Configure(MethodInfo method) public string Configure(MethodInfo method)
{ {
var invoke = CreateCompiledExpression(method); var invoke = CreateCompiledExpression(method);
@ -202,10 +202,10 @@ namespace ZeroLevel.Services.Invokation
} }
/// <summary> /// <summary>
/// Вносит в кэш вызов указанного делегата /// Cache the specified delegate
/// </summary> /// </summary>
/// <param name="handler">Делегат</param> /// <param name="handler">Delegate</param>
/// <returns>Идентификатор вызова</returns> /// <returns>Call ID</returns>
public string Configure(Delegate handler) public string Configure(Delegate handler)
{ {
var invoke = CreateCompiledExpression(handler); var invoke = CreateCompiledExpression(handler);
@ -230,7 +230,7 @@ namespace ZeroLevel.Services.Invokation
#region Configuration #region Configuration
/// <summary> /// <summary>
/// Наполнение кэша из списка методов с идентификаторами /// Filling the cache from the list of methods with identifiers
/// </summary> /// </summary>
protected void Configure(IEnumerable<Tuple<string, Invoker>> list) protected void Configure(IEnumerable<Tuple<string, Invoker>> list)
{ {
@ -241,7 +241,7 @@ namespace ZeroLevel.Services.Invokation
} }
/// <summary> /// <summary>
/// Добавление вызова в кэш /// Adding a call to the cache
/// </summary> /// </summary>
protected void Configure(Tuple<string, Invoker> invoke) protected void Configure(Tuple<string, Invoker> invoke)
{ {
@ -253,11 +253,11 @@ namespace ZeroLevel.Services.Invokation
#region Invoking #region Invoking
/// <summary> /// <summary>
/// Вызов статического метода по идентификатору, в случае отсутствия метода в кеше будет брошено исключение KeyNotFoundException /// Calling a static method by identifier, if there is no method in the cache, a KeyNotFoundException exception will be thrown
/// </summary> /// </summary>
/// <param name="identity">Идентификатор метода</param> /// <param name="identity">Call ID</param>
/// <param name="args">Аргументы метода</param> /// <param name="args">Method Arguments</param>
/// <returns>Результат выполнения</returns> /// <returns>Execution result</returns>
public object InvokeStatic(string identity, object[] args) public object InvokeStatic(string identity, object[] args)
{ {
if (_invokeCachee.ContainsKey(identity)) if (_invokeCachee.ContainsKey(identity))
@ -269,12 +269,12 @@ namespace ZeroLevel.Services.Invokation
} }
/// <summary> /// <summary>
/// Вызов метода по идентификатору, в случае отсутствия метода в кеше будет брошено исключение KeyNotFoundException /// Calling a method by identifier; if there is no method in the cache, KeyNotFoundException will be thrown.
/// </summary> /// </summary>
/// <param name="target">Инстанс на котором вызывается метод</param> /// <param name="target">The instance on which the method is called</param>
/// <param name="identity">Идентификатор метода</param> /// <param name="identity">Call ID</param>
/// <param name="args">Аргументы метода</param> /// <param name="args">Method Arguments</param>
/// <returns>Результат выполнения</returns> /// <returns>Execution result</returns>
public object Invoke(object target, string identity, object[] args) public object Invoke(object target, string identity, object[] args)
{ {
if (_invokeCachee.ContainsKey(identity)) if (_invokeCachee.ContainsKey(identity))
@ -282,7 +282,7 @@ namespace ZeroLevel.Services.Invokation
return _invokeCachee[identity](target, args); 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) public object Invoke(object target, string identity)
@ -292,15 +292,15 @@ namespace ZeroLevel.Services.Invokation
return _invokeCachee[identity](target, null); 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}'");
} }
/// <summary> /// <summary>
/// Выполнение статического закэшированного метода /// Execution of a static cached method
/// </summary> /// </summary>
/// <param name="methodName">Имя метода</param> /// <param name="methodName">Method name</param>
/// <param name="args">Аргументы метода</param> /// <param name="args">Method Arguments</param>
/// /// <returns>Результат выполнения</returns> /// /// <returns>Execution result</returns>
public object Invoke(string methodName, object[] args) public object Invoke(string methodName, object[] args)
{ {
return InvokeStatic(CreateMethodIdentity(methodName, args.Select(a => a.GetType()).ToArray()), args); return InvokeStatic(CreateMethodIdentity(methodName, args.Select(a => a.GetType()).ToArray()), args);
@ -311,21 +311,21 @@ namespace ZeroLevel.Services.Invokation
#region Helpers #region Helpers
/// <summary> /// <summary>
/// Запрос идентификатора для метода /// Request call id for method
/// </summary> /// </summary>
/// <param name="methodName">Имя метода</param> /// <param name="methodName">Method name</param>
/// <param name="argsTypes">Список типов аргументов метода</param> /// <param name="argsTypes">Method argument type list</param>
/// <returns>Идентификатор</returns> /// <returns>Call ID</returns>
public string GetInvokerIdentity(string methodName, params Type[] argsTypes) public string GetInvokerIdentity(string methodName, params Type[] argsTypes)
{ {
return CreateMethodIdentity(methodName, argsTypes); return CreateMethodIdentity(methodName, argsTypes);
} }
/// <summary> /// <summary>
/// Запрос делегата оборачивающего метод /// Request for delegate to wrap method
/// </summary> /// </summary>
/// <param name="identity">Идентификатор метода</param> /// <param name="identity">Call ID</param>
/// <returns>Делегат</returns> /// <returns>Delegate</returns>
public Invoker GetInvoker(string identity) public Invoker GetInvoker(string identity)
{ {
if (_invokeCachee.ContainsKey(identity)) if (_invokeCachee.ContainsKey(identity))
@ -337,11 +337,11 @@ namespace ZeroLevel.Services.Invokation
} }
/// <summary> /// <summary>
/// Запрос делегата оборачивающего метод /// Request for delegate to wrap method
/// </summary> /// </summary>
/// <param name="methodName">Имя метода</param> /// <param name="methodName">Method name</param>
/// <param name="argsTypes">Список типов аргументов метода</param> /// <param name="argsTypes">Method argument type list</param>
/// <returns>Делегат</returns> /// <returns>Delegate</returns>
public Invoker GetInvoker(string methodName, params Type[] argsTypes) public Invoker GetInvoker(string methodName, params Type[] argsTypes)
{ {
return GetInvoker(CreateMethodIdentity(methodName, argsTypes)); return GetInvoker(CreateMethodIdentity(methodName, argsTypes));

@ -1,10 +1,10 @@
namespace ZeroLevel.Services.Invokation namespace ZeroLevel.Services.Invokation
{ {
/// <summary> /// <summary>
/// Делегат описывающий вызов метода /// Delegate describing the method call
/// </summary> /// </summary>
/// <param name="target">Цель на которой вызывается метод</param> /// <param name="target">The target on which the method is called</param>
/// <param name="args">Аргументы метода</param> /// <param name="args">Method Arguments</param>
/// <returns>Результат</returns> /// <returns>Result</returns>
public delegate object Invoker(object target, params object[] args); public delegate object Invoker(object target, params object[] args);
} }

@ -5,39 +5,39 @@ namespace ZeroLevel.Services.Logging
public interface ILog public interface ILog
{ {
/// <summary> /// <summary>
/// Вывод сообщения как есть, без добавления уровня логирования и даты /// Message output as is, without adding a logging level and date
/// </summary> /// </summary>
void Raw(string line, params object[] args); void Raw(string line, params object[] args);
/// <summary> /// <summary>
/// Сообщение /// Message
/// </summary> /// </summary>
void Info(string line, params object[] args); void Info(string line, params object[] args);
/// <summary> /// <summary>
/// Предупреждение /// Warning
/// </summary> /// </summary>
void Warning(string line, params object[] args); void Warning(string line, params object[] args);
/// <summary> /// <summary>
/// Ошибка /// Error
/// </summary> /// </summary>
void Error(string line, params object[] args); void Error(string line, params object[] args);
/// <summary> /// <summary>
/// Ошибка /// Error
/// </summary> /// </summary>
void Error(Exception ex, string line, params object[] args); void Error(Exception ex, string line, params object[] args);
/// <summary> /// <summary>
/// Фатальный сбой /// Fatal crash
/// </summary> /// </summary>
void Fatal(string line, params object[] args); void Fatal(string line, params object[] args);
/// <summary> /// <summary>
/// Фатальный сбой /// Fatal crash
/// </summary> /// </summary>
void Fatal(Exception ex, string line, params object[] args); void Fatal(Exception ex, string line, params object[] args);
/// <summary> /// <summary>
/// Отладочная информация /// Debug info
/// </summary> /// </summary>
void Debug(string line, params object[] args); void Debug(string line, params object[] args);
/// <summary> /// <summary>
/// Низкоуровневая отладочная информация /// Low Level Debug info
/// </summary> /// </summary>
void Verbose(string line, params object[] args); void Verbose(string line, params object[] args);
} }

@ -3,22 +3,19 @@
namespace ZeroLevel.Services.Logging namespace ZeroLevel.Services.Logging
{ {
/// <summary> /// <summary>
/// Очередь сообщений для вывода в лог /// Message queue for logging
/// </summary> /// </summary>
internal interface ILogMessageBuffer : IDisposable internal interface ILogMessageBuffer : IDisposable
{ {
/// <summary> /// <summary>
/// Количество сообщений в очереди /// Number of messages in the queue
/// </summary> /// </summary>
long Count { get; } long Count { get; }
/// <summary> /// <summary>
/// Запись сообщения в очередь /// Write message to the queue
/// </summary> /// </summary>
void Push(LogLevel level, string message); void Push(LogLevel level, string message);
/// <summary>
/// Запрос сообщения из очереди для вывода в лог, подразумевается блокирующая работа метода,
/// пока очередь пустая, метод ожидает появления сообщения не возвращая результат.
/// </summary>
Tuple<LogLevel, string> Take(); Tuple<LogLevel, string> Take();
} }
} }

@ -50,15 +50,15 @@ namespace ZeroLevel.Services.Logging.Implementation
private readonly EncryptedFileLogOptions _options; private readonly EncryptedFileLogOptions _options;
private int _todayCountLogFiles = 0; private int _todayCountLogFiles = 0;
/// <summary> /// <summary>
/// Текущий лог-файл /// Current log file
/// </summary> /// </summary>
private string _currentLogFile; private string _currentLogFile;
/// <summary> /// <summary>
/// Поток для вывода в файл /// Stream to output to file
/// </summary> /// </summary>
private Stream _writer; private Stream _writer;
/// <summary> /// <summary>
/// Лок на пересоздание файла /// Lock on re-create file
/// </summary> /// </summary>
private readonly object _fileRecreating = new object(); private readonly object _fileRecreating = new object();
@ -85,7 +85,7 @@ namespace ZeroLevel.Services.Logging.Implementation
var dir = Directory.CreateDirectory(_options.Folder); var dir = Directory.CreateDirectory(_options.Folder);
if (dir.Exists == false) 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); _obfuscator = new FastObfuscator(options.Key);
@ -97,7 +97,7 @@ namespace ZeroLevel.Services.Logging.Implementation
#region Utils #region Utils
/// <summary> /// <summary>
/// Проверка имени лог-файла (изменяется при смене даты на следующий день) /// Checking the name of the log file (changes when the date changes to the next day)
/// </summary> /// </summary>
private void RecreateLogFile() private void RecreateLogFile()
{ {
@ -122,7 +122,7 @@ namespace ZeroLevel.Services.Logging.Implementation
} }
} }
/// <summary> /// <summary>
/// Закрытие текущего лога /// Closing the current log
/// </summary> /// </summary>
private void CloseCurrentWriter() private void CloseCurrentWriter()
{ {
@ -165,9 +165,6 @@ namespace ZeroLevel.Services.Logging.Implementation
#region IDisposable #region IDisposable
private bool _disposed = false; private bool _disposed = false;
/// <summary>
/// Освобождение рессурсов
/// </summary>
public void Dispose() public void Dispose()
{ {
Sheduller.Remove(_taskRename); Sheduller.Remove(_taskRename);

@ -26,15 +26,15 @@ namespace ZeroLevel.Services.Logging.Implementation
internal long LimitFileSize { get; private set; } internal long LimitFileSize { get; private set; }
internal Encoding TextEncoding { get; private set; } internal Encoding TextEncoding { get; private set; }
/// <summary> /// <summary>
/// Удалять файлы старее чем (период устаревания) /// Delete files older than (aging period)
/// </summary> /// </summary>
internal TimeSpan RemoveOlderThen { get; private set; } internal TimeSpan RemoveOlderThen { get; private set; }
/// <summary> /// <summary>
/// Удалять устаревшие файлы /// Delete outdate files
/// </summary> /// </summary>
internal bool RemoveOldFiles { get; private set; } internal bool RemoveOldFiles { get; private set; }
/// <summary> /// <summary>
/// Архивировать файлы /// Archive files
/// </summary> /// </summary>
internal bool ZipOldFiles { get; private set; } internal bool ZipOldFiles { get; private set; }
@ -48,7 +48,7 @@ namespace ZeroLevel.Services.Logging.Implementation
} }
/// <summary> /// <summary>
/// Включить автоматическое архивирование /// Enable automatic archiving
/// </summary> /// </summary>
public TextFileLoggerOptions EnableAutoArchiving() public TextFileLoggerOptions EnableAutoArchiving()
{ {
@ -56,9 +56,9 @@ namespace ZeroLevel.Services.Logging.Implementation
return this; return this;
} }
/// <summary> /// <summary>
/// Включить автоматическое удаление устаревших файлов ///Enable automatic deletion of outdate files.
/// </summary> /// </summary>
/// <param name="age">Возраст файла лога по достижении которого требуется удаление</param> /// <param name="age">The age of the log file at which removal is required</param>
public TextFileLoggerOptions EnableAutoCleaning(TimeSpan age) public TextFileLoggerOptions EnableAutoCleaning(TimeSpan age)
{ {
this.RemoveOldFiles = true; this.RemoveOldFiles = true;
@ -98,21 +98,21 @@ namespace ZeroLevel.Services.Logging.Implementation
var options = new TextFileLoggerOptions(). var options = new TextFileLoggerOptions().
SetFolderPath(config.First(logPrefix)); SetFolderPath(config.First(logPrefix));
config.DoWithFirst<long>(string.Format("{0}.backlog", logPrefix), backlog => config.DoWithFirst<long>($"{logPrefix}.backlog", backlog =>
{ {
if (backlog > 0) if (backlog > 0)
{ {
Log.Backlog(backlog); Log.Backlog(backlog);
} }
}); });
config.DoWithFirst<bool>(string.Format("{0}.archive", logPrefix), enable => config.DoWithFirst<bool>($"{logPrefix}.archive", enable =>
{ {
if (enable) if (enable)
{ {
options.EnableAutoArchiving(); options.EnableAutoArchiving();
} }
}); });
config.DoWithFirst<int>(string.Format("{0}.sizeinkb", logPrefix), size => config.DoWithFirst<int>($"{logPrefix}.sizeinkb", size =>
{ {
if (size >= 1) if (size >= 1)
{ {
@ -120,7 +120,7 @@ namespace ZeroLevel.Services.Logging.Implementation
} }
}); });
config.DoWithFirst<int>(string.Format("{0}.cleanolderdays", logPrefix), days => config.DoWithFirst<int>($"{logPrefix}.cleanolderdays", days =>
{ {
if (days > 0) if (days > 0)
{ {
@ -140,15 +140,15 @@ namespace ZeroLevel.Services.Logging.Implementation
private int _todayCountLogFiles = 0; private int _todayCountLogFiles = 0;
/// <summary> /// <summary>
/// Текущий лог-файл /// Current log file
/// </summary> /// </summary>
private string _currentLogFile; private string _currentLogFile;
/// <summary> /// <summary>
/// Поток для вывода в файл /// Stream to output to file
/// </summary> /// </summary>
private TextWriter _writer; private TextWriter _writer;
/// <summary> /// <summary>
/// Лок на пересоздание файла /// Lock on re-create file
/// </summary> /// </summary>
private readonly object _fileRecreating = new object(); private readonly object _fileRecreating = new object();
@ -160,9 +160,8 @@ namespace ZeroLevel.Services.Logging.Implementation
#region Ctors #region Ctors
/// <summary> /// <summary>
/// Конструктор с указанием каталога для записи лог-файлов, кодировка задается по умолчанию как Unicode /// Constructor indicating the directory for recording log files, the encoding is set to Unicode by default.
/// </summary> /// </summary>
/// <param name="options"></param>
public TextFileLogger(TextFileLoggerOptions options) public TextFileLogger(TextFileLoggerOptions options)
{ {
_options = options.Commit(); _options = options.Commit();
@ -171,12 +170,11 @@ namespace ZeroLevel.Services.Logging.Implementation
var dir = Directory.CreateDirectory(_options.Folder); var dir = Directory.CreateDirectory(_options.Folder);
if (dir.Exists == false) 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(); RecreateLogFile();
// Задачи обслуживания // Maintenance tasks
// Пересоздание лог-файла при достижении размера больше указанного
if (_options.LimitFileSize > 0) if (_options.LimitFileSize > 0)
{ {
_taskKeys.Add(Sheduller.RemindEvery(TimeSpan.FromSeconds(20), CheckRecreateFileLogByOversize)); _taskKeys.Add(Sheduller.RemindEvery(TimeSpan.FromSeconds(20), CheckRecreateFileLogByOversize));
@ -212,7 +210,7 @@ namespace ZeroLevel.Services.Logging.Implementation
} }
/// <summary> /// <summary>
/// Закрытие текущего лога /// Closing the current log
/// </summary> /// </summary>
private void CloseCurrentWriter() private void CloseCurrentWriter()
{ {
@ -264,7 +262,7 @@ namespace ZeroLevel.Services.Logging.Implementation
fi = null; fi = null;
} }
/// <summary> /// <summary>
/// Проверка имени лог-файла (изменяется при смене даты на следующий день) /// Checking the name of the log file (changes when the date changes to the next day)
/// </summary> /// </summary>
private void RecreateLogFile() private void RecreateLogFile()
{ {
@ -296,7 +294,7 @@ namespace ZeroLevel.Services.Logging.Implementation
{ {
if (null != filePath && File.Exists(filePath) && _options.ZipOldFiles) 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)) using (var zipStream = new GZipStream(stream, CompressionLevel.Optimal, false))
{ {
@ -344,9 +342,6 @@ namespace ZeroLevel.Services.Logging.Implementation
#region IDisposable #region IDisposable
private bool _disposed = false; private bool _disposed = false;
/// <summary>
/// Освобождение рессурсов
/// </summary>
public void Dispose() public void Dispose()
{ {
foreach (var tk in _taskKeys) foreach (var tk in _taskKeys)
@ -366,18 +361,13 @@ namespace ZeroLevel.Services.Logging.Implementation
{ {
#region Fields #region Fields
/// <summary> /// <summary>
/// Поток для вывода в файл /// Stream to output to file
/// </summary> /// </summary>
private TextWriter _writer; private TextWriter _writer;
public static readonly Encoding DEFAULT_ENCODING = Encoding.UTF8; public static readonly Encoding DEFAULT_ENCODING = Encoding.UTF8;
#endregion #endregion
#region Ctors #region Ctors
/// <summary>
/// Конструктор с указанием каталога для записи лог-файлов, кодировка задается по умолчанию как Unicode
/// </summary>
/// <param name="options"></param>
public FileLogger(string path) public FileLogger(string path)
{ {
CreateLogFile(PreparePath(path)); CreateLogFile(PreparePath(path));
@ -391,7 +381,7 @@ namespace ZeroLevel.Services.Logging.Implementation
{ {
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
FSUtils.SetupFolderPermission(path, FSUtils.SetupFolderPermission(path,
string.Format("{0}\\{1}", Environment.UserDomainName, Environment.UserName), $"{Environment.UserDomainName}\\{Environment.UserName}",
FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify, FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify,
AccessControlType.Allow); AccessControlType.Allow);
} }
@ -409,7 +399,7 @@ namespace ZeroLevel.Services.Logging.Implementation
} }
/// <summary> /// <summary>
/// Закрытие текущего лога /// Closing the current log
/// </summary> /// </summary>
private void CloseCurrentWriter() private void CloseCurrentWriter()
{ {
@ -464,9 +454,6 @@ namespace ZeroLevel.Services.Logging.Implementation
#region IDisposable #region IDisposable
private bool _disposed = false; private bool _disposed = false;
/// <summary>
/// Освобождение рессурсов
/// </summary>
public void Dispose() public void Dispose()
{ {
if (false == _disposed) if (false == _disposed)

@ -36,56 +36,56 @@ namespace ZeroLevel
_router.Write(LogLevel.Raw, FormatMessage(line, args)); _router.Write(LogLevel.Raw, FormatMessage(line, args));
} }
/// <summary> /// <summary>
/// Сообщение /// Info message
/// </summary> /// </summary>
public static void Info(string line, params object[] args) public static void Info(string line, params object[] args)
{ {
_router.Write(LogLevel.Info, FormatMessage(line, args)); _router.Write(LogLevel.Info, FormatMessage(line, args));
} }
/// <summary> /// <summary>
/// Предупреждение /// Warning message
/// </summary> /// </summary>
public static void Warning(string line, params object[] args) public static void Warning(string line, params object[] args)
{ {
_router.Write(LogLevel.Warning, FormatMessage(line, args)); _router.Write(LogLevel.Warning, FormatMessage(line, args));
} }
/// <summary> /// <summary>
/// Ошибка /// Error message
/// </summary> /// </summary>
public static void Error(string line, params object[] args) public static void Error(string line, params object[] args)
{ {
_router.Write(LogLevel.Error, FormatMessage(line, args)); _router.Write(LogLevel.Error, FormatMessage(line, args));
} }
/// <summary> /// <summary>
/// Ошибка /// Error message
/// </summary> /// </summary>
public static void Error(Exception ex, string line, params object[] args) public static void Error(Exception ex, string line, params object[] args)
{ {
_router.Write(LogLevel.Error, FormatMessage(line, args) + "\r\n" + ex.ToString()); _router.Write(LogLevel.Error, FormatMessage(line, args) + "\r\n" + ex.ToString());
} }
/// <summary> /// <summary>
/// Фатальный сбой /// Fatal crash
/// </summary> /// </summary>
public static void Fatal(string line, params object[] args) public static void Fatal(string line, params object[] args)
{ {
_router.Write(LogLevel.Fatal, FormatMessage(line, args)); _router.Write(LogLevel.Fatal, FormatMessage(line, args));
} }
/// <summary> /// <summary>
/// Фатальный сбой /// Fatal message (mean stop app after crash)
/// </summary> /// </summary>
public static void Fatal(Exception ex, string line, params object[] args) public static void Fatal(Exception ex, string line, params object[] args)
{ {
_router.Write(LogLevel.Fatal, FormatMessage(line, args) + "\r\n" + ex.ToString()); _router.Write(LogLevel.Fatal, FormatMessage(line, args) + "\r\n" + ex.ToString());
} }
/// <summary> /// <summary>
/// Отладочная информация /// Debug message
/// </summary> /// </summary>
public static void Debug(string line, params object[] args) public static void Debug(string line, params object[] args)
{ {
_router.Write(LogLevel.Debug, FormatMessage(line, args)); _router.Write(LogLevel.Debug, FormatMessage(line, args));
} }
/// <summary> /// <summary>
/// Низкоуровневая отладолчная информация /// Low-level debug message
/// </summary> /// </summary>
public static void Verbose(string line, params object[] args) public static void Verbose(string line, params object[] args)
{ {
@ -94,47 +94,33 @@ namespace ZeroLevel
/// <summary> /// <summary>
/// Сообщение /// System message
/// </summary> /// </summary>
public static void SystemInfo(string line, params object[] args) public static void SystemInfo(string line, params object[] args)
{ {
_router.Write(LogLevel.SystemInfo, FormatMessage(line, args)); _router.Write(LogLevel.SystemInfo, FormatMessage(line, args));
} }
/// <summary> /// <summary>
/// Предупреждение /// System warning
/// </summary> /// </summary>
public static void SystemWarning(string line, params object[] args) public static void SystemWarning(string line, params object[] args)
{ {
_router.Write(LogLevel.SystemWarning, FormatMessage(line, args)); _router.Write(LogLevel.SystemWarning, FormatMessage(line, args));
} }
/// <summary> /// <summary>
/// Ошибка /// System error
/// </summary> /// </summary>
public static void SystemError(string line, params object[] args) public static void SystemError(string line, params object[] args)
{ {
_router.Write(LogLevel.SystemError, FormatMessage(line, args)); _router.Write(LogLevel.SystemError, FormatMessage(line, args));
} }
/// <summary> /// <summary>
/// Ошибка /// System error
/// </summary> /// </summary>
public static void SystemError(Exception ex, string line, params object[] args) public static void SystemError(Exception ex, string line, params object[] args)
{ {
_router.Write(LogLevel.SystemError, FormatMessage(line, args) + "\r\n" + ex.ToString()); _router.Write(LogLevel.SystemError, FormatMessage(line, args) + "\r\n" + ex.ToString());
} }
/// <summary>
/// Фатальный сбой
/// </summary>
public static void SystemFatal(string line, params object[] args)
{
_router.Write(LogLevel.SystemFatal, FormatMessage(line, args));
}
/// <summary>
/// Фатальный сбой
/// </summary>
public static void SystemFatal(Exception ex, string line, params object[] args)
{
_router.Write(LogLevel.SystemFatal, FormatMessage(line, args) + "\r\n" + ex.ToString());
}
#endregion #endregion
#region Register loggers #region Register loggers
@ -217,7 +203,7 @@ namespace ZeroLevel
} }
} }
/// <summary> /// <summary>
/// Установка максимального количества сообщений в очереди /// Set mam count log-messages in queue
/// </summary> /// </summary>
public static void Backlog(long backlog) public static void Backlog(long backlog)
{ {

@ -3,63 +3,62 @@
namespace ZeroLevel.Services.Logging namespace ZeroLevel.Services.Logging
{ {
/// <summary> /// <summary>
/// Перечисление, содержит возможные типы сообщений, для записи в лог /// Enum contains possible types of messages to write to the log
/// </summary> /// </summary>
[Flags] [Flags]
public enum LogLevel : int public enum LogLevel : int
{ {
None = 0, None = 0,
/// <summary> /// <summary>
/// Сообщение /// Message
/// </summary> /// </summary>
Info = 1 << 0, Info = 1 << 0,
/// <summary> /// <summary>
/// Предупреждение о возможной неполадке /// Warning
/// </summary> /// </summary>
Warning = 1 << 1, Warning = 1 << 1,
/// <summary> /// <summary>
/// Ошибка в выполнении (некритичная) /// Error
/// </summary> /// </summary>
Error = 1 << 2, Error = 1 << 2,
/// <summary> /// <summary>
/// Ошибка приводящая к аварийному завершению программы /// Fatal
/// </summary> /// </summary>
Fatal = 1 << 3, Fatal = 1 << 3,
/// <summary> /// <summary>
/// Отладочная информация /// Debug
/// </summary> /// </summary>
Debug = 1 << 4, Debug = 1 << 4,
/// <summary> /// <summary>
/// Низкоуровневое логирование /// LowLevel Debug
/// </summary> /// </summary>
Verbose = 1 << 5, Verbose = 1 << 5,
/// <summary> /// <summary>
/// Стандартный уровень логирования, сообщения, предупреждения, ошибки и падения /// Info | Warning | Error | Fatal
/// </summary> /// </summary>
Standart = Info | Warning | Error | Fatal, Standart = Info | Warning | Error | Fatal,
/// <summary> /// <summary>
/// Вывод сообщения как есть, без даты и уровня логирования /// Message output as is, without date and logging level
/// </summary> /// </summary>
Raw = 1 << 6, Raw = 1 << 6,
/// <summary> /// <summary>
/// Запиcь проблем, предупреждения, ошибки, сбои /// Error | Fatal | Warning
/// </summary> /// </summary>
Problem = Error | Fatal | Warning, Problem = Error | Fatal | Warning,
/// <summary> /// <summary>
/// Запись всех стандартных уровней, не включая отладочные /// Info | Problem | Raw
/// </summary> /// </summary>
All = Info | Problem | Raw, All = Info | Problem | Raw,
/// <summary> /// <summary>
/// Все сообщения, включая отладочные и низкоуровневые /// All | Verbose | Debug
/// </summary> /// </summary>
FullDebug = All | Verbose | Debug, FullDebug = All | Verbose | Debug,
SystemInfo = 1 << 6, SystemInfo = 1 << 6,
SystemWarning = 1 << 7, SystemWarning = 1 << 7,
SystemError = 1 << 8, SystemError = 1 << 8,
SystemFatal = 1 << 9,
System = SystemInfo | SystemError | SystemWarning | SystemFatal, System = SystemInfo | SystemError | SystemWarning,
FullStandart = Standart | System FullStandart = Standart | System
} }

@ -16,8 +16,7 @@ namespace ZeroLevel.Services.Logging
{ LogLevel.SystemInfo, "SYSINF"}, { LogLevel.SystemInfo, "SYSINF"},
{ LogLevel.SystemError, "SYSERR"}, { LogLevel.SystemError, "SYSERR"},
{ LogLevel.SystemWarning, "SYSWRN"}, { LogLevel.SystemWarning, "SYSWRN"}
{ LogLevel.SystemFatal, "SYSFLT"}
}; };
private static readonly Dictionary<LogLevel, string> _full = new Dictionary<LogLevel, string> private static readonly Dictionary<LogLevel, string> _full = new Dictionary<LogLevel, string>
{ {
@ -31,8 +30,7 @@ namespace ZeroLevel.Services.Logging
{ LogLevel.SystemInfo, " system info"}, { LogLevel.SystemInfo, " system info"},
{ LogLevel.SystemError, " system error"}, { LogLevel.SystemError, " system error"},
{ LogLevel.SystemWarning, " systm warning"}, { LogLevel.SystemWarning, " systm warning"}
{ LogLevel.SystemFatal, " system fatal"}
}; };
public static string CompactName(LogLevel level) { return _compact[level]; } public static string CompactName(LogLevel level) { return _compact[level]; }

@ -1,304 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZeroLevel.Services.Collections;
namespace ZeroLevel.Services.Trees
{
/// <summary>
/// Выполняет преобразование набора элементов в дерево (в набор ветвей)
/// </summary>
/// <typeparam name="T">Тип элемента</typeparam>
/// <typeparam name="TKey">Тип связующих компонентов элемента</typeparam>
public class ItemFieldToTreeConverter<T, TKey>
{
#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<T, T, bool> comparer, Func<TKey, TKey, bool> 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<Node> _nodes = new List<Node>();
private readonly Func<TKey, TKey, bool> _key_comparer;
private readonly Func<T, T, bool> _comparer;
public IEnumerable<Node> Nodes
{
get
{
return _nodes;
}
}
public NodeBranch(Node first, Func<T, T, bool> comparer, Func<TKey, TKey, bool> key_comparer)
{
_nodes.Add(first);
_key_comparer = key_comparer;
_comparer = comparer;
}
public NodeBranch(IEnumerable<Node> nodes, Func<T, T, bool> comparer, Func<TKey, TKey, bool> key_comparer)
{
_nodes.AddRange(nodes);
_key_comparer = key_comparer;
_comparer = comparer;
}
public List<T> 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;
}
/// <summary>
/// Проверка возможности объединения с другой ветвью, если текущая является ее началом или продолжением
/// </summary>
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<T, TKey> _inKeyExtractor;
private readonly Func<T, TKey> _outKeyExtractor;
private readonly Func<T, T, bool> _comparer;
private readonly Func<TKey, TKey, bool> _key_comparer;
/// <summary>
/// Конструктор
/// </summary>
/// <param name="inKeyExtractor">Экстрактор входной связи элемента</param>
/// <param name="outKeyExtractor">Экстрактор исходящей связи элемента</param>
public ItemFieldToTreeConverter(Func<T, TKey> inKeyExtractor,
Func<T, TKey> outKeyExtractor,
Func<T, T, bool> comparer = null,
Func<TKey, TKey, bool> 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<TKey, TKey, bool>((k1, k2) =>
{
if (k1 == null && k2 == null) return true;
if (k1 == null) return false;
if (k2 == null) return false;
return k1.Equals(k2);
});
}
/// <summary>
/// Преобразование набора элементов к набору ветвей
/// </summary>
public IEnumerable<List<T>> Convert(IEnumerable<T> entries)
{
if (entries == null || entries.Any() == false)
{
return Enumerable.Empty<List<T>>();
}
var iterator = new SparseIterator<T>(entries);
var result = new List<NodeBranch>();
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<List<T>>();
}
int index;
var cachee = new Dictionary<int, Node>();
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<NodeBranch>();
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;
}
}
}

@ -86,7 +86,6 @@
<Compile Include="Services\Collections\EverythingStorage.cs" /> <Compile Include="Services\Collections\EverythingStorage.cs" />
<Compile Include="Services\Collections\IEverythingStorage.cs" /> <Compile Include="Services\Collections\IEverythingStorage.cs" />
<Compile Include="Services\Collections\RoundRobinCollection.cs" /> <Compile Include="Services\Collections\RoundRobinCollection.cs" />
<Compile Include="Services\Collections\SparseIterator.cs" />
<Compile Include="Services\DependencyInjection\Container.cs" /> <Compile Include="Services\DependencyInjection\Container.cs" />
<Compile Include="Services\DependencyInjection\ContainerFactory.cs" /> <Compile Include="Services\DependencyInjection\ContainerFactory.cs" />
<Compile Include="Services\DependencyInjection\Contracts\ICompositionProvider.cs" /> <Compile Include="Services\DependencyInjection\Contracts\ICompositionProvider.cs" />
@ -95,12 +94,10 @@
<Compile Include="Services\DependencyInjection\Contracts\IContainerInstanceRegister.cs" /> <Compile Include="Services\DependencyInjection\Contracts\IContainerInstanceRegister.cs" />
<Compile Include="Services\DependencyInjection\Contracts\IContainerRegister.cs" /> <Compile Include="Services\DependencyInjection\Contracts\IContainerRegister.cs" />
<Compile Include="Services\DependencyInjection\Contracts\IParameterStorage.cs" /> <Compile Include="Services\DependencyInjection\Contracts\IParameterStorage.cs" />
<Compile Include="Services\DependencyInjection\Contracts\IPoolContainer.cs" />
<Compile Include="Services\DependencyInjection\Contracts\IResolver.cs" /> <Compile Include="Services\DependencyInjection\Contracts\IResolver.cs" />
<Compile Include="Services\DependencyInjection\Injector.cs" /> <Compile Include="Services\DependencyInjection\Injector.cs" />
<Compile Include="Services\DependencyInjection\Internal\ConstructorMetadata.cs" /> <Compile Include="Services\DependencyInjection\Internal\ConstructorMetadata.cs" />
<Compile Include="Services\DependencyInjection\Internal\ConstructorParameter.cs" /> <Compile Include="Services\DependencyInjection\Internal\ConstructorParameter.cs" />
<Compile Include="Services\DependencyInjection\Internal\IPoolable.cs" />
<Compile Include="Services\DependencyInjection\Internal\ResolveTypeInfo.cs" /> <Compile Include="Services\DependencyInjection\Internal\ResolveTypeInfo.cs" />
<Compile Include="Services\DependencyInjection\ParameterAttribute.cs" /> <Compile Include="Services\DependencyInjection\ParameterAttribute.cs" />
<Compile Include="Services\DependencyInjection\ResolveAttribute.cs" /> <Compile Include="Services\DependencyInjection\ResolveAttribute.cs" />
@ -137,7 +134,7 @@
<Compile Include="Services\DOM\DSL\Tokens\TTextToken.cs" /> <Compile Include="Services\DOM\DSL\Tokens\TTextToken.cs" />
<Compile Include="Services\DOM\DSL\Tokens\TToken.cs" /> <Compile Include="Services\DOM\DSL\Tokens\TToken.cs" />
<Compile Include="Services\DOM\Model\Agency.cs" /> <Compile Include="Services\DOM\Model\Agency.cs" />
<Compile Include="Services\DOM\Model\AsideContent.cs" /> <Compile Include="Services\DOM\Model\AttachContent.cs" />
<Compile Include="Services\DOM\Model\Assotiation.cs" /> <Compile Include="Services\DOM\Model\Assotiation.cs" />
<Compile Include="Services\DOM\Model\AssotiationRelation.cs" /> <Compile Include="Services\DOM\Model\AssotiationRelation.cs" />
<Compile Include="Services\DOM\Model\Category.cs" /> <Compile Include="Services\DOM\Model\Category.cs" />
@ -365,7 +362,6 @@
<Compile Include="Services\Trees\Contracts\ITree.cs" /> <Compile Include="Services\Trees\Contracts\ITree.cs" />
<Compile Include="Services\Trees\Contracts\ITreeNode.cs" /> <Compile Include="Services\Trees\Contracts\ITreeNode.cs" />
<Compile Include="Services\Trees\Generic.cs" /> <Compile Include="Services\Trees\Generic.cs" />
<Compile Include="Services\Trees\ItemFieldToTreeConverter.cs" />
<Compile Include="Services\Trees\Tree.cs" /> <Compile Include="Services\Trees\Tree.cs" />
<Compile Include="Services\Trees\TreeNode.cs" /> <Compile Include="Services\Trees\TreeNode.cs" />
<Compile Include="Services\Trees\TreesVisitor.cs" /> <Compile Include="Services\Trees\TreesVisitor.cs" />

@ -1 +1 @@
c7012002005514f37ffc568f2998758c453405e9 3af5ac7a6b742028005a8a0757e8f6fbb4fd20fa

Loading…
Cancel
Save

Powered by TurnKey Linux.