From a152cc643e5a45e3691d9d7420ed40e5d3a13985 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Sun, 1 Jan 2023 18:57:17 +0100 Subject: [PATCH] feat(shared): add in-process-shared NosSmooth binding, packet repository and files --- .../Extensions/ServiceCollectionExtensions.cs | 98 ++++++++++++++ .../NosSmooth.Extensions.SharedBinding.csproj | 18 +++ .../SharedManager.cs | 120 ++++++++++++++++++ .../SharedOptions.cs | 33 +++++ 4 files changed, 269 insertions(+) create mode 100644 NosSmooth.Extensions.SharedBinding/Extensions/ServiceCollectionExtensions.cs create mode 100644 NosSmooth.Extensions.SharedBinding/NosSmooth.Extensions.SharedBinding.csproj create mode 100644 NosSmooth.Extensions.SharedBinding/SharedManager.cs create mode 100644 NosSmooth.Extensions.SharedBinding/SharedOptions.cs diff --git a/NosSmooth.Extensions.SharedBinding/Extensions/ServiceCollectionExtensions.cs b/NosSmooth.Extensions.SharedBinding/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..b015dfd --- /dev/null +++ b/NosSmooth.Extensions.SharedBinding/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,98 @@ +// +// 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 Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using NosSmooth.Data.NOSFiles; +using NosSmooth.LocalBinding; +using NosSmooth.PacketSerializer.Packets; + +namespace NosSmooth.Extensions.SharedBinding.Extensions; + +/// +/// Extension methods for . +/// +public static class ServiceCollectionExtensions +{ + /// + /// Replaces + /// with shared equivalent. That allows for multiple programs injected inside NosTale. + /// + /// The collection. + /// The same collection. + public static IServiceCollection ShareBinding(this IServiceCollection serviceCollection) + { + var original = serviceCollection + .Last(x => x.ServiceType == typeof(NosBindingManager)); + + return serviceCollection + .Configure(o => o.BindingDescriptor = original) + .Replace + (ServiceDescriptor.Singleton(p => SharedManager.Instance.GetNosBindingManager(p))); + } + + /// + /// Replaces + /// with shared equivalent. That allows for multiple programs injected inside NosTale. + /// + /// The collection. + /// The same collection. + public static IServiceCollection ShareFileManager(this IServiceCollection serviceCollection) + { + var original = serviceCollection + .Last(x => x.ServiceType == typeof(NostaleDataFilesManager)); + + return serviceCollection + .Configure(o => o.FileDescriptor = original) + .Replace + (ServiceDescriptor.Singleton(p => SharedManager.Instance.GetFilesManager(p))); + } + + /// + /// Replaces + /// with shared equivalent. That allows for multiple programs injected inside NosTale. + /// + /// The collection. + /// The same collection. + public static IServiceCollection SharePacketRepository(this IServiceCollection serviceCollection) + { + var original = serviceCollection + .Last(x => x.ServiceType == typeof(IPacketTypesRepository)); + + return serviceCollection + .Configure(o => o.PacketRepositoryDescriptor = original) + .Replace + ( + ServiceDescriptor.Singleton(p => SharedManager.Instance.GetPacketRepository(p)) + ); + } + + /// + /// Replaces , and + /// with their shared equvivalents. That allows for multiple programs injected inside NosTale. + /// + /// The collection. + /// The same collection. + public static IServiceCollection ShareNosSmooth(this IServiceCollection serviceCollection) + { + if (serviceCollection.Any(x => x.ServiceType == typeof(NosBindingManager))) + { + serviceCollection.ShareBinding(); + } + + if (serviceCollection.Any(x => x.ServiceType == typeof(NostaleDataFilesManager))) + { + serviceCollection.ShareFileManager(); + } + + if (serviceCollection.Any(x => x.ServiceType == typeof(IPacketTypesRepository))) + { + serviceCollection.SharePacketRepository(); + } + + return serviceCollection; + } +} \ No newline at end of file diff --git a/NosSmooth.Extensions.SharedBinding/NosSmooth.Extensions.SharedBinding.csproj b/NosSmooth.Extensions.SharedBinding/NosSmooth.Extensions.SharedBinding.csproj new file mode 100644 index 0000000..13a1295 --- /dev/null +++ b/NosSmooth.Extensions.SharedBinding/NosSmooth.Extensions.SharedBinding.csproj @@ -0,0 +1,18 @@ + + + + net7.0 + enable + enable + + + + + + + + + + + + diff --git a/NosSmooth.Extensions.SharedBinding/SharedManager.cs b/NosSmooth.Extensions.SharedBinding/SharedManager.cs new file mode 100644 index 0000000..2eeb862 --- /dev/null +++ b/NosSmooth.Extensions.SharedBinding/SharedManager.cs @@ -0,0 +1,120 @@ +// +// SharedManager.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 Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using NosSmooth.Data.NOSFiles; +using NosSmooth.LocalBinding; +using NosSmooth.PacketSerializer.Packets; + +namespace NosSmooth.Extensions.SharedBinding; + +/// +/// Manager for sharing , +/// and +/// . +/// +public class SharedManager +{ + private static SharedManager? _instance; + private NosBindingManager? _bindingManager; + private NostaleDataFilesManager? _filesManager; + private IPacketTypesRepository? _packetRepository; + + /// + /// A singleton instance. + /// One per process. + /// + public static SharedManager Instance + { + get + { + if (_instance is null) + { + _instance = new SharedManager(); + } + + return _instance; + } + } + + /// + /// Gets the shared nos binding manager. + /// + /// The service provider. + /// The shared manager. + public NosBindingManager GetNosBindingManager(IServiceProvider services) + { + if (_bindingManager is null) + { + _bindingManager = GetFromDescriptor(services, o => o.BindingDescriptor); + } + + return _bindingManager; + + } + + /// + /// Gets the shared file manager. + /// + /// The service provider. + /// The shared manager. + public NostaleDataFilesManager GetFilesManager(IServiceProvider services) + { + if (_filesManager is null) + { + _filesManager = GetFromDescriptor(services, o => o.FileDescriptor); + } + + return _filesManager; + + } + + /// + /// Gets the shared packet type repository. + /// + /// The service provider. + /// The shared repository. + public IPacketTypesRepository GetPacketRepository(IServiceProvider services) + { + if (_packetRepository is null) + { + _packetRepository = GetFromDescriptor(services, o => o.PacketRepositoryDescriptor); + } + + return _packetRepository; + + } + + private T GetFromDescriptor(IServiceProvider services, Func getDescriptor) + { + var options = services.GetRequiredService>(); + var descriptor = getDescriptor(options.Value); + + if (descriptor is null) + { + throw new InvalidOperationException + ($"Could not find {typeof(T)} in the service provider when trying to make a shared instance."); + } + + if (descriptor.ImplementationInstance is not null) + { + return (T)descriptor.ImplementationInstance; + } + + if (descriptor.ImplementationFactory is not null) + { + return (T)descriptor.ImplementationFactory(services); + } + + if (descriptor.ImplementationType is not null) + { + return (T)ActivatorUtilities.CreateInstance(services, descriptor.ImplementationType); + } + + return ActivatorUtilities.CreateInstance(services); + } +} \ No newline at end of file diff --git a/NosSmooth.Extensions.SharedBinding/SharedOptions.cs b/NosSmooth.Extensions.SharedBinding/SharedOptions.cs new file mode 100644 index 0000000..184d55b --- /dev/null +++ b/NosSmooth.Extensions.SharedBinding/SharedOptions.cs @@ -0,0 +1,33 @@ +// +// SharedOptions.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 Microsoft.Extensions.DependencyInjection; +using NosSmooth.Data.NOSFiles; +using NosSmooth.LocalBinding; +using NosSmooth.PacketSerializer.Packets; + +namespace NosSmooth.Extensions.SharedBinding; + +/// +/// Options for . +/// +internal class SharedOptions +{ + /// + /// Gets or sets the original descriptor of . + /// + public ServiceDescriptor? BindingDescriptor { get; set; } + + /// + /// Gets or sets the original descriptor of . + /// + public ServiceDescriptor? FileDescriptor { get; set; } + + /// + /// Gets or sets the original descriptor of . + /// + public ServiceDescriptor? PacketRepositoryDescriptor { get; set; } +} \ No newline at end of file -- 2.49.0