diff --git a/SecuritySystem/SecuritySystemContracts/DI/DependencyManager.cs b/SecuritySystem/SecuritySystemContracts/DI/DependencyManager.cs new file mode 100644 index 0000000..6691ee4 --- /dev/null +++ b/SecuritySystem/SecuritySystemContracts/DI/DependencyManager.cs @@ -0,0 +1,72 @@ +using Microsoft.Extensions.Logging; + +namespace SecuritySystemContracts.DI +{ + /// + /// Менеджер для работы с зависимостями + /// + public class DependencyManager + { + private readonly IDependencyContainer _dependencyManager; + private static DependencyManager? _manager; + private static readonly object _locjObject = new(); + private DependencyManager() + { + _dependencyManager = new ServiceDependencyContainer(); + } + public static DependencyManager Instance + { + get + { + if (_manager == null) + { + lock (_locjObject) + { + _manager = new DependencyManager(); + } + } + return _manager; + } + } + /// + /// Иницализация библиотек, в которых идут установки зависомстей + /// + public static void InitDependency() + { + var ext = ServiceProviderLoader.GetImplementationExtensions(); + if (ext == null) + { + throw new ArgumentNullException("Отсутствуют компоненты для загрузки зависимостей по модулям"); + } + // регистрируем зависимости + ext.RegisterServices(); + } + /// + /// Регистрация логгера + /// + /// + public void AddLogging(Action configure) => _dependencyManager.AddLogging(configure); + /// + /// Добавление зависимости + /// + /// + /// + public void RegisterType(bool isSingle = false) + where U : class, T + where T : class => _dependencyManager.RegisterType(isSingle); + /// + /// Добавление зависимости + /// + /// + /// + public void RegisterType(bool isSingle = false) + where T : class => _dependencyManager.RegisterType(isSingle); + /// + /// Получение класса со всеми зависмостями + /// + /// + /// + public T Resolve() => _dependencyManager.Resolve(); + } + +} diff --git a/SecuritySystem/SecuritySystemContracts/DI/IDependencyContainer.cs b/SecuritySystem/SecuritySystemContracts/DI/IDependencyContainer.cs new file mode 100644 index 0000000..eb761f0 --- /dev/null +++ b/SecuritySystem/SecuritySystemContracts/DI/IDependencyContainer.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Logging; + +namespace SecuritySystemContracts.DI +{ + /// + /// Интерфейс установки зависмости между элементами + /// + public interface IDependencyContainer + { + /// + /// Регистрация логгера + /// + /// + void AddLogging(Action configure); + /// + /// Добавление зависимости + /// + /// + /// + /// + void RegisterType(bool isSingle) where U : class, T where T : + class; + /// + /// Добавление зависимости + /// + /// + /// + void RegisterType(bool isSingle) where T : class; + /// + /// Получение класса со всеми зависмостями + /// + /// + /// + T Resolve(); + } +} diff --git a/SecuritySystem/SecuritySystemContracts/DI/IImplementationExtension.cs b/SecuritySystem/SecuritySystemContracts/DI/IImplementationExtension.cs new file mode 100644 index 0000000..177bebf --- /dev/null +++ b/SecuritySystem/SecuritySystemContracts/DI/IImplementationExtension.cs @@ -0,0 +1,14 @@ +namespace SecuritySystemContracts.DI +{ + /// + /// Интерфейс для регистрации зависимостей в модулях + /// + public interface IImplementationExtension + { + public int Priority { get; } + /// + /// Регистрация сервисов + /// + public void RegisterServices(); + } +} diff --git a/SecuritySystem/SecuritySystemContracts/DI/ServiceDependencyContainer.cs b/SecuritySystem/SecuritySystemContracts/DI/ServiceDependencyContainer.cs new file mode 100644 index 0000000..7ec4665 --- /dev/null +++ b/SecuritySystem/SecuritySystemContracts/DI/ServiceDependencyContainer.cs @@ -0,0 +1,56 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace SecuritySystemContracts.DI +{ + public class ServiceDependencyContainer : IDependencyContainer + { + private ServiceProvider? _serviceProvider; + private readonly ServiceCollection _serviceCollection; + + public ServiceDependencyContainer() + { + _serviceCollection = new ServiceCollection(); + } + + public void AddLogging(Action configure) + { + _serviceCollection.AddLogging(configure); + } + + public void RegisterType(bool isSingle) where T : class where U : class, T + { + if (isSingle) + { + _serviceCollection.AddSingleton(); + } + else + { + _serviceCollection.AddTransient(); + } + _serviceProvider = null; + } + + public T Resolve() + { + if (_serviceProvider == null) + { + _serviceProvider = _serviceCollection.BuildServiceProvider(); + } + return _serviceProvider.GetService()!; + } + + void IDependencyContainer.RegisterType(bool isSingle) where T : class + { + if (isSingle) + { + _serviceCollection.AddSingleton(); + } + else + { + _serviceCollection.AddTransient(); + } + _serviceProvider = null; + } + } +} diff --git a/SecuritySystem/SecuritySystemContracts/DI/ServiceProviderLoader.cs b/SecuritySystem/SecuritySystemContracts/DI/ServiceProviderLoader.cs new file mode 100644 index 0000000..b128076 --- /dev/null +++ b/SecuritySystem/SecuritySystemContracts/DI/ServiceProviderLoader.cs @@ -0,0 +1,53 @@ +using System.Reflection; + +namespace SecuritySystemContracts.DI +{ + /// + /// Загрузчик данных + /// + public static partial class ServiceProviderLoader + { + /// + /// Загрузка всех классов-реализаций IImplementationExtension + /// + /// + public static IImplementationExtension? GetImplementationExtensions() + { + IImplementationExtension? source = null; + var files = Directory.GetFiles(TryGetImplementationExtensionsFolder(), "*.dll", SearchOption.AllDirectories); + foreach (var file in files.Distinct()) + { + Assembly asm = Assembly.LoadFrom(file); + foreach (var t in asm.GetExportedTypes()) + { + if (t.IsClass && typeof(IImplementationExtension).IsAssignableFrom(t)) + { + if (source == null) + { + source = (IImplementationExtension)Activator.CreateInstance(t)!; + } + else + { + var newSource = (IImplementationExtension)Activator.CreateInstance(t)!; + if (newSource.Priority > source.Priority) + { + source = newSource; + } + } + } + } + } + return source; + } + private static string TryGetImplementationExtensionsFolder() + { + var directory = new DirectoryInfo(Directory.GetCurrentDirectory()); + while (directory != null && !directory.GetDirectories("ImplementationExtensions", SearchOption.AllDirectories).Any(x => x.Name == "ImplementationExtensions")) + { + directory = directory.Parent; + } + return $"{directory?.FullName}\\ImplementationExtensions"; + } + } + +} diff --git a/SecuritySystem/SecuritySystemContracts/SecuritySystemContracts.csproj b/SecuritySystem/SecuritySystemContracts/SecuritySystemContracts.csproj index 2554988..c3a3957 100644 --- a/SecuritySystem/SecuritySystemContracts/SecuritySystemContracts.csproj +++ b/SecuritySystem/SecuritySystemContracts/SecuritySystemContracts.csproj @@ -7,6 +7,10 @@ AnyCPU;x64;x86 + + + +