128 lines
4.5 KiB
C#
128 lines
4.5 KiB
C#
namespace BotPages.Core.Abstractions;
|
||
|
||
/// <summary>
|
||
/// Реализация <see cref="IMessengerAdapterFactory"/>, позволяющая регистрировать и разрешать несколько адаптеров.
|
||
/// </summary>
|
||
public sealed class MultiAdapterFactory : IMessengerAdapterFactory
|
||
{
|
||
private readonly List<IMessengerAdapterSetup> _allAdapters = new();
|
||
private readonly Dictionary<string, IMessengerAdapterSetup> _adaptersById = new(StringComparer.OrdinalIgnoreCase);
|
||
private readonly Dictionary<string, List<IMessengerAdapterSetup>> _adaptersByType = new(StringComparer.OrdinalIgnoreCase);
|
||
|
||
/// <summary>
|
||
/// Список всех зарегистрированных адаптеров.
|
||
/// </summary>
|
||
public IReadOnlyList<IMessengerAdapterSetup> AllAdapters => _allAdapters;
|
||
|
||
/// <summary>
|
||
/// Зарегистрировать адаптер с уникальным идентификатором.
|
||
/// </summary>
|
||
public IMessengerAdapterFactory Register(string adapterId, IMessengerAdapterSetup adapter)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(adapterId))
|
||
throw new ArgumentException("Adapter ID cannot be null or empty", nameof(adapterId));
|
||
|
||
if (_adaptersById.ContainsKey(adapterId))
|
||
throw new ArgumentException($"Adapter with ID '{adapterId}' is already registered", nameof(adapterId));
|
||
|
||
// Устанавливаем идентификатор в адаптер
|
||
adapter.SetAdapterId(adapterId);
|
||
|
||
_allAdapters.Add(adapter);
|
||
_adaptersById[adapterId] = adapter;
|
||
|
||
// Группируем по типу
|
||
var adapterType = adapter.Type;
|
||
if (!_adaptersByType.TryGetValue(adapterType, out var typeList))
|
||
{
|
||
typeList = new List<IMessengerAdapterSetup>();
|
||
_adaptersByType[adapterType] = typeList;
|
||
}
|
||
typeList.Add(adapter);
|
||
|
||
return this;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Зарегистрировать адаптер с автоматически сгенерированным ID.
|
||
/// </summary>
|
||
public IMessengerAdapterFactory Register(IMessengerAdapterSetup adapter)
|
||
{
|
||
var adapterId = GenerateAdapterId(adapter);
|
||
return Register(adapterId, adapter);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Получить адаптер по ID.
|
||
/// </summary>
|
||
public IMessengerAdapter Resolve(string adapterId)
|
||
{
|
||
if (_adaptersById.TryGetValue(adapterId, out var adapter))
|
||
{
|
||
return adapter;
|
||
}
|
||
|
||
throw new InvalidOperationException($"No adapter registered with ID '{adapterId}'");
|
||
}
|
||
|
||
/// <summary>
|
||
/// Попытаться получить адаптер по ID.
|
||
/// </summary>
|
||
public bool TryResolve(string adapterId, out IMessengerAdapter? adapter)
|
||
{
|
||
var result = _adaptersById.TryGetValue(adapterId, out var adapterSetup);
|
||
adapter = adapterSetup;
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Получить все адаптеры определенного типа.
|
||
/// </summary>
|
||
public IReadOnlyList<IMessengerAdapter> GetAdaptersByType(string adapterType)
|
||
{
|
||
if (_adaptersByType.TryGetValue(adapterType, out var adapters))
|
||
{
|
||
return adapters.AsReadOnly();
|
||
}
|
||
|
||
return Array.Empty<IMessengerAdapter>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Проверить, зарегистрирован ли адаптер с указанным ID.
|
||
/// </summary>
|
||
public bool Contains(string adapterId) => _adaptersById.ContainsKey(adapterId);
|
||
|
||
/// <summary>
|
||
/// Удалить адаптер по ID.
|
||
/// </summary>
|
||
public bool Remove(string adapterId)
|
||
{
|
||
if (_adaptersById.TryGetValue(adapterId, out var adapter))
|
||
{
|
||
_allAdapters.Remove(adapter);
|
||
_adaptersById.Remove(adapterId);
|
||
|
||
var adapterType = adapter.Type;
|
||
if (_adaptersByType.TryGetValue(adapterType, out var typeList))
|
||
{
|
||
typeList.Remove(adapter);
|
||
if (typeList.Count == 0)
|
||
{
|
||
_adaptersByType.Remove(adapterType);
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
private static string GenerateAdapterId(IMessengerAdapter adapter)
|
||
{
|
||
var adapterType = adapter.Type;
|
||
var guid = Guid.NewGuid().ToString("N").Substring(0, 8);
|
||
return $"{adapterType}_{guid}".ToLowerInvariant();
|
||
}
|
||
} |