// // StringConverterRepository.cs // // Copyright (c) František Boháček. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.DependencyInjection; using NosSmooth.Packets.Converters.Special; using NosSmooth.Packets.Errors; using NosSmooth.Packets.Extensions; using NosSmooth.PacketSerializer.Abstractions; using Remora.Results; namespace NosSmooth.Packets.Converters; /// /// Repository for . /// public class StringConverterRepository : IStringConverterRepository { private readonly IServiceProvider _serviceProvider; private readonly ConcurrentDictionary _typeConverters; private IReadOnlyList? _converterFactories; /// /// Initializes a new instance of the class. /// /// The dependency injection service provider. public StringConverterRepository(IServiceProvider serviceProvider) { _typeConverters = new ConcurrentDictionary(); _converterFactories = null; _serviceProvider = serviceProvider; } private IReadOnlyList ConverterFactories { get { if (_converterFactories is null) { _converterFactories = _serviceProvider .GetServices() .ToArray(); } return _converterFactories; } } /// /// Gets the type converter for the given type. /// /// The type to find converter for. /// The type converter or an error. public Result GetTypeConverter(Type type) { var typeConverter = _typeConverters.GetOrAddResult ( type, (getType) => { foreach (var converterFactory in ConverterFactories) { if (converterFactory.ShouldHandle(getType)) { var result = converterFactory.CreateTypeSerializer(getType); if (!result.IsSuccess) { return Result.FromError(result); } return Result.FromSuccess(result.Entity); } } var converterType = typeof(IStringConverter<>).MakeGenericType(type); return Result.FromSuccess ((IStringConverter?)_serviceProvider.GetService(converterType)); } ); if (!typeConverter.IsSuccess) { return Result.FromError(typeConverter); } if (typeConverter.Entity is null) { return new TypeConverterNotFoundError(type); } return Result.FromSuccess(typeConverter.Entity); } /// /// Gets the type converter for the given type. /// /// The type to find converter for. /// The type converter or an error. public Result> GetTypeConverter() => GetTypeConverter(typeof(TParseType)).Cast, IStringConverter>(); }