// // 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.PacketSerializer.Abstractions; using NosSmooth.PacketSerializer.Converters.Special; using NosSmooth.PacketSerializer.Errors; using NosSmooth.PacketSerializer.Extensions; using Remora.Results; namespace NosSmooth.PacketSerializer.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) => { var converterType = typeof(IStringConverter<>).MakeGenericType(type); var serviceConverter = (IStringConverter?)_serviceProvider.GetService(converterType); if (serviceConverter is not null) { // prefer specific converter to generated one. return Result.FromSuccess(serviceConverter); } 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); } } return Result.FromSuccess(null); } ); 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>(); }