// // ServiceCollectionExtensions.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.Linq; using System.Reflection; using Microsoft.Extensions.DependencyInjection; using NosSmooth.Packets.Converters; using NosSmooth.Packets.Converters.Basic; using NosSmooth.Packets.Converters.Common; using NosSmooth.Packets.Converters.Packets; using NosSmooth.Packets.Converters.Special; using NosSmooth.Packets.Packets; using NosSmooth.PacketSerializer.Abstractions; namespace NosSmooth.Packets.Extensions; /// /// Extensions for . /// public static class ServiceCollectionExtensions { /// /// Add packet serialization classes. /// /// /// All generic implementations of IStringConverter the class /// implements will be registered. /// /// The service collection. /// The collection. public static IServiceCollection AddPacketSerialization(this IServiceCollection serviceCollection) { return serviceCollection .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() .AddGeneratedSerializers(typeof(IPacket).Assembly) .AddBasicConverters(); } /// /// Adds all generated serializers from the given assembly. /// /// The service collection. /// The assembly. /// The collection. public static IServiceCollection AddGeneratedSerializers(this IServiceCollection serviceCollection, Assembly assembly) { var types = assembly.GetExportedTypes() .Where(x => x.Namespace?.Contains("Generated") ?? false) .Where(x => x.GetInterfaces().Any( i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IStringConverter<>) )); foreach (var type in types) { serviceCollection.AddStringConverter(type); } return serviceCollection; } /// /// Adds basic converters for int, uint, short, ushort, long, ulong, char, string /// and special converters for lists and enums. /// /// The service collection. /// The collection. public static IServiceCollection AddBasicConverters(this IServiceCollection serviceCollection) { return serviceCollection .AddStringConverterFactory() .AddStringConverterFactory() .AddStringConverterFactory() .AddStringConverter() .AddStringConverter() .AddStringConverter() .AddStringConverter() .AddStringConverter() .AddStringConverter() .AddStringConverter() .AddStringConverter() .AddStringConverter() .AddStringConverter() .AddStringConverter() .AddStringConverter(); } /// /// Add generic type converter. /// /// /// All generic implementations of IStringConverter the class /// implements will be registered. /// /// The service collection. /// The type of the converter. /// The collection. public static IServiceCollection AddStringConverter(this IServiceCollection serviceCollection) where TConverter : IStringConverter => serviceCollection.AddStringConverter(typeof(TConverter)); /// /// Add generic type converter. /// /// /// All generic implementations of IStringConverter the class /// implements will be registered. /// /// The service collection. /// The type of the converter. /// The collection. public static IServiceCollection AddStringConverter(this IServiceCollection serviceCollection, Type converterType) { if (!converterType.GetInterfaces().Any( i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IStringConverter<>) )) { throw new ArgumentException( $"{nameof(converterType)} should implement IStringConverter.", nameof(converterType)); } var handlerTypeInterfaces = converterType.GetInterfaces(); var handlerInterfaces = handlerTypeInterfaces.Where ( r => r.IsGenericType && r.GetGenericTypeDefinition() == typeof(IStringConverter<>) ); foreach (var handlerInterface in handlerInterfaces) { serviceCollection.AddSingleton(handlerInterface, converterType); } return serviceCollection; } /// /// Add the specified converter as a special converter. /// /// The service collection. /// The type to add as a special converter. /// The collection. public static IServiceCollection AddStringConverterFactory(this IServiceCollection serviceCollection) where TConverterFactory : class, IStringConverterFactory { return serviceCollection.AddSingleton(); } }