diff --git a/Source/ExcelRna.Extensions.Hosting.Tests/ExcelFunctionsRegistrarTests.cs b/Source/ExcelRna.Extensions.Hosting.Tests/ExcelFunctionsRegistrarTests.cs index 3c372b9..816bf91 100644 --- a/Source/ExcelRna.Extensions.Hosting.Tests/ExcelFunctionsRegistrarTests.cs +++ b/Source/ExcelRna.Extensions.Hosting.Tests/ExcelFunctionsRegistrarTests.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using ExcelDna.Registration; using Moq; using Xunit; @@ -13,7 +15,11 @@ public async Task StartAsync_should_register_functions() // ARRANGE var excelFunctionsProvider = new Mock(); bool registered = false; - ExcelFunctionsRegistrar excelFunctionsRegistrar = new(excelFunctionsProvider.Object, new NoopExcelFunctionsProcessor()) { RegisterFunctions = _ => { registered = true; } }; + ExcelFunctionsRegistrar excelFunctionsRegistrar = + new(excelFunctionsProvider.Object, new[] { new TestProcessor() }) + { + RegisterFunctions = _ => { registered = true; } + }; // ACT await excelFunctionsRegistrar.StartAsync(CancellationToken.None); @@ -27,7 +33,8 @@ public void StopAsync_is_noop() { // ARRANGE var excelFunctionsProvider = new Mock(); - ExcelFunctionsRegistrar excelFunctionsRegistrar = new(excelFunctionsProvider.Object, new NoopExcelFunctionsProcessor()); + ExcelFunctionsRegistrar excelFunctionsRegistrar = + new(excelFunctionsProvider.Object, new[] { new TestProcessor() }); // ACT Task stopTask = excelFunctionsRegistrar.StopAsync(CancellationToken.None); @@ -35,4 +42,10 @@ public void StopAsync_is_noop() // ASSERT Assert.Equal(Task.CompletedTask, stopTask); } + + private class TestProcessor : IExcelFunctionsProcessor + { + public IEnumerable Process(IEnumerable registrations) => + registrations; + } } diff --git a/Source/ExcelRna.Extensions.Hosting.Tests/NoopFunctionsProcessorTests.cs b/Source/ExcelRna.Extensions.Hosting.Tests/NoopFunctionsProcessorTests.cs deleted file mode 100644 index 7b3a758..0000000 --- a/Source/ExcelRna.Extensions.Hosting.Tests/NoopFunctionsProcessorTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; -using ExcelDna.Registration; -using Xunit; - -namespace ExcelRna.Extensions.Hosting.Tests; - -public class NoopFunctionsProcessorTests -{ - [Fact] - public void Process_should_return_the_same_object() - { - // ARRANGE - NoopExcelFunctionsProcessor noopExcelFunctionsProcessor = new(); - var functions = new ExcelFunctionRegistration[42]; - - // ACT - IEnumerable processedFunctions = noopExcelFunctionsProcessor.Process(functions); - - // ASSERT - Assert.Same(processedFunctions, functions); - } -} diff --git a/Source/ExcelRna.Extensions.Hosting.Tests/ServiceCollectionExtensionsTests.cs b/Source/ExcelRna.Extensions.Hosting.Tests/ServiceCollectionExtensionsTests.cs index 560513d..fe06728 100644 --- a/Source/ExcelRna.Extensions.Hosting.Tests/ServiceCollectionExtensionsTests.cs +++ b/Source/ExcelRna.Extensions.Hosting.Tests/ServiceCollectionExtensionsTests.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; @@ -22,7 +23,8 @@ public void AddExcelFunctions_should_add_functions_type() // ASSERT var provider = services.BuildServiceProvider(); - IEnumerable declarations = provider.GetRequiredService>(); + IEnumerable declarations = + provider.GetRequiredService>(); Assert.Collection(declarations, a => Assert.Equal(typeof(TestFunctionsA), a.ExcelFunctionsType), b => Assert.Equal(typeof(TestFunctionsB), b.ExcelFunctionsType)); @@ -47,6 +49,7 @@ public void AddExcelRibbon_should_add_loader() } [Fact] + [Obsolete] public void AddExcelFunctionsProcessor_should_add_processor() { // ARRANGE @@ -63,6 +66,23 @@ public void AddExcelFunctionsProcessor_should_add_processor() Assert.Single(processor.Process(Enumerable.Empty())); } + [Fact] + public void AddExcelFunctionsProcessor_should_add_multiple_processors() + { + // ARRANGE + var services = new ServiceCollection(); + services.AddTransient(); + + // ACT + services.AddExcelFunctionsProcessor(); + services.AddExcelFunctionsProcessor(); + + // ASSERT + ServiceProvider serviceProvider = services.BuildServiceProvider(); + IEnumerable processors = serviceProvider.GetRequiredService>(); + Assert.Collection(processors, a => Assert.IsType(a), b => Assert.IsType(b)); + } + private class TestFunctionsA { } @@ -83,4 +103,20 @@ private class TestDependency { public ExcelFunctionRegistration Registration { get; } = new(Expression.Lambda(Expression.Constant(null))); } + + private class TestProcessorA : IExcelFunctionsProcessor + { + private readonly TestDependency _dependency; + + public TestProcessorA(TestDependency dependency) => _dependency = dependency; + + public IEnumerable Process(IEnumerable registrations) => + registrations.Concat(new[] { _dependency.Registration }); + } + + private class TestProcessorB : IExcelFunctionsProcessor + { + public IEnumerable Process(IEnumerable registrations) => + throw new NotImplementedException(); + } } diff --git a/Source/ExcelRna.Extensions.Hosting/ExcelFunctionsRegistrar.cs b/Source/ExcelRna.Extensions.Hosting/ExcelFunctionsRegistrar.cs index 997c4f4..538e903 100644 --- a/Source/ExcelRna.Extensions.Hosting/ExcelFunctionsRegistrar.cs +++ b/Source/ExcelRna.Extensions.Hosting/ExcelFunctionsRegistrar.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using ExcelDna.Registration; @@ -10,20 +11,21 @@ namespace ExcelRna.Extensions.Hosting; internal class ExcelFunctionsRegistrar : IHostedService { private readonly IExcelFunctionsProvider _excelFunctionsProvider; - private readonly IExcelFunctionsProcessor _excelFunctionsProcessor; + private readonly IEnumerable _excelFunctionsProcessors; - public ExcelFunctionsRegistrar(IExcelFunctionsProvider excelFunctionsProvider, IExcelFunctionsProcessor excelFunctionsProcessor) + public ExcelFunctionsRegistrar(IExcelFunctionsProvider excelFunctionsProvider, IEnumerable excelFunctionsProcessors) { _excelFunctionsProvider = excelFunctionsProvider; - _excelFunctionsProcessor = excelFunctionsProcessor; + _excelFunctionsProcessors = excelFunctionsProcessors; } internal Action> RegisterFunctions { get; set; } = functions => functions.RegisterFunctions(); public Task StartAsync(CancellationToken cancellationToken) { - IEnumerable functions = _excelFunctionsProcessor - .Process(_excelFunctionsProvider.GetExcelFunctions()); + var functions = _excelFunctionsProcessors.Aggregate( + _excelFunctionsProvider.GetExcelFunctions(), + (current, excelFunctionsProcessor) => excelFunctionsProcessor.Process(current)); RegisterFunctions(functions); return Task.CompletedTask; } diff --git a/Source/ExcelRna.Extensions.Hosting/IExcelFunctionsProcessor.cs b/Source/ExcelRna.Extensions.Hosting/IExcelFunctionsProcessor.cs index 2205147..cf2e4f5 100644 --- a/Source/ExcelRna.Extensions.Hosting/IExcelFunctionsProcessor.cs +++ b/Source/ExcelRna.Extensions.Hosting/IExcelFunctionsProcessor.cs @@ -4,16 +4,11 @@ namespace ExcelRna.Extensions.Hosting; -internal interface IExcelFunctionsProcessor +public interface IExcelFunctionsProcessor { IEnumerable Process(IEnumerable registrations); } -internal class NoopExcelFunctionsProcessor : IExcelFunctionsProcessor -{ - public IEnumerable Process(IEnumerable registrations) => registrations; -} - internal class ExcelFunctionsProcessor : IExcelFunctionsProcessor { private readonly Func, IEnumerable> _process; diff --git a/Source/ExcelRna.Extensions.Hosting/ServiceCollectionExtensions.cs b/Source/ExcelRna.Extensions.Hosting/ServiceCollectionExtensions.cs index 7dcb4a6..132f54d 100644 --- a/Source/ExcelRna.Extensions.Hosting/ServiceCollectionExtensions.cs +++ b/Source/ExcelRna.Extensions.Hosting/ServiceCollectionExtensions.cs @@ -15,7 +15,8 @@ public static IServiceCollection AddExcelFunctions(this IServiceCollection se services.AddHostedService(); services.AddSingleton(); - services.TryAddEnumerable(ServiceDescriptor.Singleton>()); + services.TryAddEnumerable( + ServiceDescriptor.Singleton>()); return services; } @@ -28,13 +29,22 @@ public static IServiceCollection AddExcelRibbon(this IServiceCollection servi return services; } + [Obsolete("Please use AddExcelFunctionsProcessor()")] public static IServiceCollection AddExcelFunctionsProcessor(this IServiceCollection services, Func, IEnumerable> process) { return services.AddSingleton(new ExcelFunctionsProcessor(process)); } + [Obsolete("Please use AddExcelFunctionsProcessor()")] public static IServiceCollection AddExcelFunctionsProcessor(this IServiceCollection services, Func, IServiceProvider, IEnumerable> process) { return services.AddSingleton(provider => new ExcelFunctionsProcessor(functions => process(functions, provider))); } + + public static IServiceCollection AddExcelFunctionsProcessor(this IServiceCollection services) + where TProcessor : class, IExcelFunctionsProcessor + { + services.TryAddEnumerable(ServiceDescriptor.Singleton()); + return services; + } }