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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -7,6 +7,7 @@ using System.Linq;
using System.Security;
using System.Text;
using System.Threading;
using ZeroLevel;
using ZeroLevel.DocumentObjectModel;
using ZeroLevel.DocumentObjectModel.Flow;
using ZeroLevel.Services.FileSystem;
@ -56,7 +57,7 @@ namespace DOM.DSL.Services
}
else
{
// Добавляются элементы разных типов, в этом случае все элементы приводим к string
// Added elements of different types. All elements casts to string
var list = new List<string>();
foreach (var i in _list) list.Add(i.ToString());
_elementType = typeof(string);
@ -170,7 +171,7 @@ namespace DOM.DSL.Services
else if (_current is Category) SelectProperty((Category)_current, propertyName, propertyIndex);
else if (_current is Header) SelectProperty((Header)_current, propertyName, propertyIndex);
else if (_current is Tag) SelectProperty((Tag)_current, propertyName, propertyIndex);
else if (_current is AsideContent) SelectProperty((AsideContent)_current, propertyName, propertyIndex);
else if (_current is AttachContent) SelectProperty((AttachContent)_current, propertyName, propertyIndex);
else if (_current is Assotiation) SelectProperty((Assotiation)_current, propertyName, propertyIndex);
else if (_current is List<Header>) SelectProperty((List<Header>)_current, propertyName, propertyIndex);
else if (_current is Identifier) SelectProperty((Identifier)_current, propertyName, propertyIndex);
@ -255,8 +256,9 @@ namespace DOM.DSL.Services
{
return (T)Convert.ChangeType(_current, type);
}
catch
catch (Exception ex)
{
Log.SystemWarning($"[DOM.TContainer] Fault cast current value from type '{_current?.GetType()?.FullName ?? string.Empty}' to type '{type.FullName}'. {ex.ToString()}");
return default(T);
}
}
@ -273,8 +275,9 @@ namespace DOM.DSL.Services
{
return Convert.ChangeType(_current, type);
}
catch
catch(Exception ex)
{
Log.SystemWarning($"[DOM.TContainer] Fault cast current value from type '{_current?.GetType()?.FullName ?? string.Empty}' to type '{type.FullName}'. {ex.ToString()}");
return TypeHelpers.CreateDefaultState(type);
}
}
@ -1144,7 +1147,7 @@ namespace DOM.DSL.Services
}
}
private void SelectProperty(AsideContent aside, string property, string propertyIndex)
private void SelectProperty(AttachContent aside, string property, string propertyIndex)
{
switch (property.Trim().ToLowerInvariant())
{
@ -2596,7 +2599,7 @@ namespace DOM.DSL.Services
else if (_current is Category) return ((Category)_current).Title ?? string.Empty;
else if (_current is Header) return ((Header)_current).Value ?? string.Empty;
else if (_current is Tag) return ((Tag)_current).Name ?? string.Empty;
else if (_current is AsideContent) return ((AsideContent)_current).Caption ?? string.Empty;
else if (_current is AttachContent) return ((AttachContent)_current).Caption ?? string.Empty;
else if (_current is Assotiation) return ((Assotiation)_current).Title ?? string.Empty;
else if (_current is List<Header>) return string.Join("; ", ((List<Header>)_current).Select(h => h.Name));
else if (_current is Identifier) return string.Empty;

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

@ -28,7 +28,7 @@ namespace DOM.DSL
}
catch (Exception ex)
{
Log.SystemError(ex, "Fault parse template '{0}' to token list", template);
Log.SystemError(ex, $"Fault parse template '{template}' to token list");
}
}
return Enumerable.Empty<TToken>();
@ -69,7 +69,7 @@ namespace DOM.DSL
}
catch (Exception ex)
{
Log.Debug("Fault transform document '{0} by token list'. {1}", document.Id, ex);
Log.Debug($"Fault transform document '{document.Id} by token list'. {ex.ToString()}");
if (ignore_fault == false)
{
throw ex;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -192,12 +192,12 @@ namespace DOM.Services
reader.LeaveHeaders(doc.DescriptiveMetadata.Headers);
reader.LeaveDescriptioveBlock(doc.DescriptiveMetadata);
reader.EnterAsides(doc.Aside);
for (int i = 0; i < doc.Aside.Count; i++)
reader.EnterAsides(doc.Attachments);
for (int i = 0; i < doc.Attachments.Count; i++)
{
reader.ReadAside(doc.Aside[i], i);
reader.ReadAside(doc.Attachments[i], i);
}
reader.LeaveAsides(doc.Aside);
reader.LeaveAsides(doc.Attachments);
reader.EnterAssotiations(doc.Assotiations);
for (int i = 0; i < doc.Assotiations.Count; i++)

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

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

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

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

@ -3,69 +3,65 @@
namespace ZeroLevel.Patterns.DependencyInjection
{
/// <summary>
/// Интерфейс с методами для реализации хранения параметров
/// (хранилище ключ-значение, где в качестве ключа используется сущность типа string, а в качестве значения объект любого типа)
/// DI parameters stogare (string key and anytype value)
/// </summary>
public interface IParameterStorage
{
#region IEverythingStorage
/// <summary>
/// Сохранение параметра
/// Save parameter
/// </summary>
/// <typeparam name="T">Тип параметра</typeparam>
/// <param name="key">Ключ</param>
/// <param name="value">Значение параметра</param>
/// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Key</param>
/// <param name="value">Parameter value</param>
void Save<T>(string key, T value);
/// <summary>
/// Сохранение или обновление параметра
/// Save or update parameter
/// </summary>
/// <typeparam name="T">Тип параметра</typeparam>
/// <param name="key">Ключ</param>
/// <param name="value">Значение параметра</param>
/// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Key</param>
/// <param name="value">Parameter value</param>
void SaveOrUpdate<T>(string key, T value);
/// <summary>
/// Безопасное сохранение параметра
/// Safe save parameter
/// </summary>
/// <typeparam name="T">Тип параметра</typeparam>
/// <param name="key">Ключ</param>
/// <param name="value">Значение параметра</param>
/// <returns>true - в случае успеха</returns>
/// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Key</param>
/// <param name="value">Parameter value</param>
bool TrySave<T>(string key, T value);
/// <summary>
/// Удаление параметра
/// Remove parameter by key
/// </summary>
/// <typeparam name="T">Тип параметра</typeparam>
/// <param name="key">Ключ</param>
/// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Key</param>
void Remove<T>(string key);
/// <summary>
/// Безопасное удаление параметра
/// Safe remove parameter by key
/// </summary>
/// <typeparam name="T">Тип параметра</typeparam>
/// <param name="key">Ключ</param>
/// <returns>true - в случае успеха</returns>
/// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Key</param>
bool TryRemove<T>(string key);
/// <summary>
/// Запрос сохраненного параметра
/// Get parameter value by key
/// </summary>
/// <typeparam name="T">Тип параметра</typeparam>
/// <param name="key">Ключ</param>
/// <returns>Значение параметра</returns>
/// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Key</param>
/// <returns>Parameter value</returns>
T Get<T>(string key);
T GetOrDefault<T>(string key);
T GetOrDefault<T>(string key, T defaultValue);
/// <summary>
/// Запрос сохраненного параметра
/// Get parameter value by key
/// </summary>
/// <param name="type">Тип параметра</param>
/// <param name="key">Ключ</param>
/// <returns>Значение параметра</returns>
/// <param name="type">Parameter type</param>
/// <param name="key">Key</param>
/// <returns>Parameter value</returns>
object Get(Type type, string key);
/// <summary>
/// Проверка наличия параметра с указанным именем
/// Check for parameter existence by key
/// </summary>
/// <typeparam name="T">Тип параметра</typeparam>
/// <param name="key">Ключ</param>
/// <returns>Указывает наличие параметра с заданным именем</returns>
/// <typeparam name="T">Parameter type</typeparam>
/// <param name="key">Key</param>
bool Contains<T>(string key);
#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
{
/// <summary>
/// Интерфейс с методами разрешений зависимостей
/// Dependency resolver
/// </summary>
public interface IResolver
{
#region Activator
/// <summary>
/// Создание экземпляра объекта указанного типа
/// Creating an instance of an object of the specified type
/// </summary>
/// <typeparam name="T">Тип объекта</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param>
/// <returns>Экземпляр объекта</returns>
/// <typeparam name="T">Contract or instance type</typeparam>
/// <param name="resolveName">Dependency name</param>
/// <returns>Instance</returns>
T CreateInstance<T>(string resolveName = "");
/// <summary>
/// Создание экземпляра объекта указанного типа
/// Creating an instance of an object of the specified type
/// </summary>
/// <typeparam name="T">Тип объекта</typeparam>
/// <param name="args">Аргументы конструктора</param>
/// <param name="resolveName">Имя разрешения зависимости</param>
/// <returns>Экземпляр объекта</returns>
/// <typeparam name="T">Contract or instance type</typeparam>
/// <param name="args">Ctor agrs</param>
/// <param name="resolveName">Dependency name</param>
/// <returns>Instance</returns>
T CreateInstance<T>(object[] args, string resolveName = "");
/// <summary>
/// Создание экземпляра объекта указанного типа
/// Creating an instance of an object of the specified type
/// </summary>
/// <param name="type">Тип объекта</param>
/// <param name="resolveName">Имя разрешения зависимости</param>
/// <returns>Экземпляр объекта</returns>
/// <param name="type">Contract or instance type</param>
/// <param name="resolveName">Dependency name</param>
/// <returns>Instance</returns>
object CreateInstance(Type type, string resolveName = "");
/// <summary>
/// Создание экземпляра объекта указанного типа
/// Creating an instance of an object of the specified type
/// </summary>
/// <param name="type">Тип объекта</param>
/// <param name="args">Аргументы конструктора</param>
/// <param name="resolveName">Имя разрешения зависимости</param>
/// <returns>Экземпляр объекта</returns>
/// <param name="type">Contract or instance type</param>
/// <param name="args">Ctor agrs</param>
/// <param name="resolveName">Dependency name</param>
/// <returns>Instance</returns>
object CreateInstance(Type type, object[] args, string resolveName = "");
#endregion
#region Resolving
/// <summary>
/// Разрешение зависимости
/// Dependency resolve
/// </summary>
/// <typeparam name="T">Тип контракта</typeparam>
/// <param name="compose">Указание провести композицию при построении объектов</param>
/// <returns>Инстанс</returns>
/// <typeparam name="T">Contract</typeparam>
/// <param name="compose">Compose the object when true</param>
/// <returns>Instance</returns>
T Resolve<T>(bool compose = true);
/// <summary>
/// Разрешение зависимости
/// Dependency resolve
/// </summary>
/// <typeparam name="T">Тип контракта</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param>
/// <param name="compose">Указание провести композицию при построении объектов</param>
/// <returns>Инстанс</returns>
/// <typeparam name="T">Contract</typeparam>
/// <param name="resolveName">Dependency name</param>
/// <param name="compose">Compose the object when true</param>
/// <returns>Instance</returns>
T Resolve<T>(string resolveName, bool compose = true);
/// <summary>
/// Разрешение зависимости
/// Dependency resolve
/// </summary>
/// <typeparam name="T">Тип контракта</typeparam>
/// <param name="args">Аргументы конструктора</param>
/// <param name="compose">Указание провести композицию при построении объектов</param>
/// <returns>Инстанс</returns>
/// <typeparam name="T">Contract</typeparam>
/// <param name="args">Ctor agrs</param>
/// <param name="compose">Compose the object when true</param>
/// <returns>Instance</returns>
T Resolve<T>(object[] args, bool compose = true);
/// <summary>
/// Разрешение зависимости
/// Dependency resolve
/// </summary>
/// <typeparam name="T">Тип контракта</typeparam>
/// <param name="resolveName">Имя разрешения зависимости</param>
/// <param name="args">Аргументы конструктора</param>
/// <param name="compose">Указание провести композицию при построении объектов</param>
/// <returns>Инстанс</returns>
/// <typeparam name="T">Contract</typeparam>
/// <param name="resolveName">Dependency name</param>
/// <param name="args">Ctor agrs</param>
/// <param name="compose">Compose the object when true</param>
/// <returns>Instance</returns>
T Resolve<T>(string resolveName, object[] args, bool compose = true);
/// <summary>
/// Разрешение зависимости
/// Dependency resolve
/// </summary>
/// <param name="type">Тип контракта</param>
/// <param name="compose">Указание провести композицию при построении объектов</param>
/// <returns>Инстанс</returns>
/// <param name="type">Contract</param>
/// <param name="compose">Compose the object when true</param>
/// <returns>Instance</returns>
object Resolve(Type type, bool compose = true);
/// <summary>
/// Разрешение зависимости
/// Dependency resolve
/// </summary>
/// <param name="type">Тип контракта</param>
/// <param name="resolveName">Имя разрешения зависимости</param>
/// <param name="compose">Указание провести композицию при построении объектов</param>
/// <returns>Инстанс</returns>
/// <param name="type">Contract</param>
/// <param name="resolveName">Dependency name</param>
/// <param name="compose">Compose the object when true</param>
/// <returns>Instance</returns>
object Resolve(Type type, string resolveName, bool compose = true);
/// <summary>
/// Разрешение зависимости
/// Dependency resolve
/// </summary>
/// <param name="type">Тип контракта</param>
/// <param name="args">Аргументы конструктора</param>
/// <param name="compose">Указание провести композицию при построении объектов</param>
/// <returns>Инстанс</returns>
/// <param name="type">Contract</param>
/// <param name="args">Ctor agrs</param>
/// <param name="compose">Compose the object when true</param>
/// <returns>Instance</returns>
object Resolve(Type type, object[] args, bool compose = true);
/// <summary>
/// Разрешение зависимости
/// Dependency resolve
/// </summary>
/// <param name="type">Тип контракта</param>
/// <param name="resolveName">Имя разрешения зависимости</param>
/// <param name="args">Аргументы конструктора</param>
/// <param name="compose">Указание провести композицию при построении объектов</param>
/// <returns>Инстанс</returns>
/// <param name="type">Contract</param>
/// <param name="resolveName">Dependency name</param>
/// <param name="args">Ctor agrs</param>
/// <param name="compose">Compose the object when true</param>
/// <returns>Instance</returns>
object Resolve(Type type, string resolveName, object[] args, bool compose = true);
#endregion

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

@ -3,47 +3,47 @@
namespace ZeroLevel.Patterns.DependencyInjection
{
/// <summary>
/// Тип аргумента конструктора в контексте иньекции зависимостей
/// Constructor argument type
/// </summary>
internal enum ConstructorParameterKind
{
/// <summary>
/// Аргумент задается из переданных значений
/// Constant
/// </summary>
None,
/// <summary>
/// Аргумент задается из параметров контейнера
/// DI parameter
/// </summary>
Parameter,
/// <summary>
/// Аргумент задается разрешением зависимости
/// Dependency
/// </summary>
Resolve
Dependency
}
/// <summary>
/// Метаданные для описания аргумента конструктора
/// Constructor argument metadata
/// </summary>
internal sealed class ConstructorParameter
{
/// <summary>
/// Тип аргумента в рамках DI
/// Argument DI-type
/// </summary>
public ConstructorParameterKind ParameterKind;
/// <summary>
/// Тип для определения аргумента через DI
/// Argument contract type
/// </summary>
public Type ParameterResolveType;
/// <summary>
/// Имя для определения аргумента через DI
/// Dependency name
/// </summary>
public string ParameterResolveName;
/// <summary>
/// Флаг определяющий допустимость записи null в качестве значения аргумента
/// Allow null
/// </summary>
public bool IsNullable;
/// <summary>
/// Тип аргумента
/// Argument CLR type
/// </summary>
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
{
/// <summary>
/// Метаданные разрешения зависимости
/// Dependency resolving metadata
/// </summary>
internal sealed class ResolveTypeInfo
{
/// <summary>
/// Разрешение зависимости по умолчанию
/// Default - without dependency name
/// </summary>
public bool IsDefault;
/// <summary>
/// Создается только один экземпляр (в случае true)
/// Singletone when true
/// </summary>
public bool IsShared;
/// <summary>
/// Тип инстанса (в том числе обобщенный)
/// Instance type (may be generic)
/// </summary>
public Type ImplementationType;
/// <summary>
/// Ключ определения зависимости
/// Dependency resolving key
/// </summary>
public string ResolveKey;
/// <summary>
/// Кэш экземпляра
/// Instance cache
/// </summary>
public object SharedInstance;
/// <summary>
/// Кэш обобщенных типов
/// Generic types cahce
/// </summary>
public Dictionary<Type, Type> GenericCachee;
/// <summary>
/// Кэш обобщенных экземпляров
/// Generic instances cahce
/// </summary>
public Dictionary<Type, object> GenericInstanceCachee;
/// <summary>
/// Параметры конструктора объекта
/// Constructor parameters
/// </summary>
public object[] ConstructorParameters;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -3,7 +3,7 @@
namespace ZeroLevel.Services.Impersonation
{
/// <summary>
/// Реализует исполнение произвольного кода от прав указанного процесса
/// Implements the execution of an code from the rights of the specified process
/// </summary>
public class ProcessImpersonationExecutor
: IImpersonationExecutor
@ -21,11 +21,8 @@ namespace ZeroLevel.Services.Impersonation
_pid = pid;
}
/// <summary>
/// Исполнение кода
/// Code execution
/// </summary>
/// <typeparam name="T">Тип передаваемого аргумента</typeparam>
/// <param name="action">Делегат</param>
/// <param name="arg">Аргумент</param>
public void ExecuteCode<T>(Action<T> action, T arg)
{
using (Impersonation imp = new Impersonation())
@ -40,16 +37,14 @@ namespace ZeroLevel.Services.Impersonation
}
else
{
throw new Exception("Нет данных для идентификации процесса. Для копирования прав процесса требуется указать его имя или идентификатор.");
throw new Exception("No data to identify the process. To copy the rights of a process, you must specify its name or identifier");
}
action(arg);
}
}
/// <summary>
/// Исполнение кода
/// Code execution
/// </summary>
/// <typeparam name="T">Тип передаваемого аргумента</typeparam>
/// <param name="action">Делегат</param>
public void ExecuteCode(Action action)
{
using (Impersonation imp = new Impersonation())
@ -64,7 +59,7 @@ namespace ZeroLevel.Services.Impersonation
}
else
{
throw new Exception("Нет данных для идентификации процесса. Для копирования прав процесса требуется указать его имя или идентификатор.");
throw new Exception("No data to identify the process. To copy the rights of a process, you must specify its name or identifier");
}
action();
}

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

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

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

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

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

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

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

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

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

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

@ -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\IEverythingStorage.cs" />
<Compile Include="Services\Collections\RoundRobinCollection.cs" />
<Compile Include="Services\Collections\SparseIterator.cs" />
<Compile Include="Services\DependencyInjection\Container.cs" />
<Compile Include="Services\DependencyInjection\ContainerFactory.cs" />
<Compile Include="Services\DependencyInjection\Contracts\ICompositionProvider.cs" />
@ -95,12 +94,10 @@
<Compile Include="Services\DependencyInjection\Contracts\IContainerInstanceRegister.cs" />
<Compile Include="Services\DependencyInjection\Contracts\IContainerRegister.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\Injector.cs" />
<Compile Include="Services\DependencyInjection\Internal\ConstructorMetadata.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\ParameterAttribute.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\TToken.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\AssotiationRelation.cs" />
<Compile Include="Services\DOM\Model\Category.cs" />
@ -365,7 +362,6 @@
<Compile Include="Services\Trees\Contracts\ITree.cs" />
<Compile Include="Services\Trees\Contracts\ITreeNode.cs" />
<Compile Include="Services\Trees\Generic.cs" />
<Compile Include="Services\Trees\ItemFieldToTreeConverter.cs" />
<Compile Include="Services\Trees\Tree.cs" />
<Compile Include="Services\Trees\TreeNode.cs" />
<Compile Include="Services\Trees\TreesVisitor.cs" />

@ -1 +1 @@
c7012002005514f37ffc568f2998758c453405e9
3af5ac7a6b742028005a8a0757e8f6fbb4fd20fa

Loading…
Cancel
Save

Powered by TurnKey Linux.