Skip to content

Commit

Permalink
Expose IExcelFunctionsProcessor
Browse files Browse the repository at this point in the history
  • Loading branch information
altso committed Apr 18, 2023
1 parent 5cb3d11 commit ceb6c5e
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using ExcelDna.Registration;
using Moq;
using Xunit;

Expand All @@ -13,7 +15,11 @@ public async Task StartAsync_should_register_functions()
// ARRANGE
var excelFunctionsProvider = new Mock<IExcelFunctionsProvider>();
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);
Expand All @@ -27,12 +33,19 @@ public void StopAsync_is_noop()
{
// ARRANGE
var excelFunctionsProvider = new Mock<IExcelFunctionsProvider>();
ExcelFunctionsRegistrar excelFunctionsRegistrar = new(excelFunctionsProvider.Object, new NoopExcelFunctionsProcessor());
ExcelFunctionsRegistrar excelFunctionsRegistrar =
new(excelFunctionsProvider.Object, new[] { new TestProcessor() });

// ACT
Task stopTask = excelFunctionsRegistrar.StopAsync(CancellationToken.None);

// ASSERT
Assert.Equal(Task.CompletedTask, stopTask);
}

private class TestProcessor : IExcelFunctionsProcessor
{
public IEnumerable<ExcelFunctionRegistration> Process(IEnumerable<ExcelFunctionRegistration> registrations) =>
registrations;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
Expand All @@ -22,7 +23,8 @@ public void AddExcelFunctions_should_add_functions_type()

// ASSERT
var provider = services.BuildServiceProvider();
IEnumerable<IExcelFunctionsDeclaration> declarations = provider.GetRequiredService<IEnumerable<IExcelFunctionsDeclaration>>();
IEnumerable<IExcelFunctionsDeclaration> declarations =
provider.GetRequiredService<IEnumerable<IExcelFunctionsDeclaration>>();
Assert.Collection(declarations,
a => Assert.Equal(typeof(TestFunctionsA), a.ExcelFunctionsType),
b => Assert.Equal(typeof(TestFunctionsB), b.ExcelFunctionsType));
Expand All @@ -47,6 +49,7 @@ public void AddExcelRibbon_should_add_loader()
}

[Fact]
[Obsolete]
public void AddExcelFunctionsProcessor_should_add_processor()
{
// ARRANGE
Expand All @@ -63,6 +66,23 @@ public void AddExcelFunctionsProcessor_should_add_processor()
Assert.Single(processor.Process(Enumerable.Empty<ExcelFunctionRegistration>()));
}

[Fact]
public void AddExcelFunctionsProcessor_should_add_multiple_processors()
{
// ARRANGE
var services = new ServiceCollection();
services.AddTransient<TestDependency>();

// ACT
services.AddExcelFunctionsProcessor<TestProcessorA>();
services.AddExcelFunctionsProcessor<TestProcessorB>();

// ASSERT
ServiceProvider serviceProvider = services.BuildServiceProvider();
IEnumerable<IExcelFunctionsProcessor> processors = serviceProvider.GetRequiredService<IEnumerable<IExcelFunctionsProcessor>>();
Assert.Collection(processors, a => Assert.IsType<TestProcessorA>(a), b => Assert.IsType<TestProcessorB>(b));
}

private class TestFunctionsA
{
}
Expand All @@ -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<ExcelFunctionRegistration> Process(IEnumerable<ExcelFunctionRegistration> registrations) =>
registrations.Concat(new[] { _dependency.Registration });
}

private class TestProcessorB : IExcelFunctionsProcessor
{
public IEnumerable<ExcelFunctionRegistration> Process(IEnumerable<ExcelFunctionRegistration> registrations) =>
throw new NotImplementedException();
}
}
12 changes: 7 additions & 5 deletions Source/ExcelRna.Extensions.Hosting/ExcelFunctionsRegistrar.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ExcelDna.Registration;
Expand All @@ -10,20 +11,21 @@ namespace ExcelRna.Extensions.Hosting;
internal class ExcelFunctionsRegistrar : IHostedService
{
private readonly IExcelFunctionsProvider _excelFunctionsProvider;
private readonly IExcelFunctionsProcessor _excelFunctionsProcessor;
private readonly IEnumerable<IExcelFunctionsProcessor> _excelFunctionsProcessors;

public ExcelFunctionsRegistrar(IExcelFunctionsProvider excelFunctionsProvider, IExcelFunctionsProcessor excelFunctionsProcessor)
public ExcelFunctionsRegistrar(IExcelFunctionsProvider excelFunctionsProvider, IEnumerable<IExcelFunctionsProcessor> excelFunctionsProcessors)
{
_excelFunctionsProvider = excelFunctionsProvider;
_excelFunctionsProcessor = excelFunctionsProcessor;
_excelFunctionsProcessors = excelFunctionsProcessors;
}

internal Action<IEnumerable<ExcelFunctionRegistration>> RegisterFunctions { get; set; } = functions => functions.RegisterFunctions();

public Task StartAsync(CancellationToken cancellationToken)
{
IEnumerable<ExcelFunctionRegistration> functions = _excelFunctionsProcessor
.Process(_excelFunctionsProvider.GetExcelFunctions());
var functions = _excelFunctionsProcessors.Aggregate(
_excelFunctionsProvider.GetExcelFunctions(),
(current, excelFunctionsProcessor) => excelFunctionsProcessor.Process(current));
RegisterFunctions(functions);
return Task.CompletedTask;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,11 @@

namespace ExcelRna.Extensions.Hosting;

internal interface IExcelFunctionsProcessor
public interface IExcelFunctionsProcessor
{
IEnumerable<ExcelFunctionRegistration> Process(IEnumerable<ExcelFunctionRegistration> registrations);
}

internal class NoopExcelFunctionsProcessor : IExcelFunctionsProcessor
{
public IEnumerable<ExcelFunctionRegistration> Process(IEnumerable<ExcelFunctionRegistration> registrations) => registrations;
}

internal class ExcelFunctionsProcessor : IExcelFunctionsProcessor
{
private readonly Func<IEnumerable<ExcelFunctionRegistration>, IEnumerable<ExcelFunctionRegistration>> _process;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ public static IServiceCollection AddExcelFunctions<T>(this IServiceCollection se
services.AddHostedService<ExcelFunctionsRegistrar>();

services.AddSingleton<T>();
services.TryAddEnumerable(ServiceDescriptor.Singleton<IExcelFunctionsDeclaration, ExcelFunctionsDeclaration<T>>());
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IExcelFunctionsDeclaration, ExcelFunctionsDeclaration<T>>());

return services;
}
Expand All @@ -28,13 +29,22 @@ public static IServiceCollection AddExcelRibbon<T>(this IServiceCollection servi
return services;
}

[Obsolete("Please use AddExcelFunctionsProcessor<TProcessor>()")]
public static IServiceCollection AddExcelFunctionsProcessor(this IServiceCollection services, Func<IEnumerable<ExcelFunctionRegistration>, IEnumerable<ExcelFunctionRegistration>> process)
{
return services.AddSingleton<IExcelFunctionsProcessor>(new ExcelFunctionsProcessor(process));
}

[Obsolete("Please use AddExcelFunctionsProcessor<TProcessor>()")]
public static IServiceCollection AddExcelFunctionsProcessor(this IServiceCollection services, Func<IEnumerable<ExcelFunctionRegistration>, IServiceProvider, IEnumerable<ExcelFunctionRegistration>> process)
{
return services.AddSingleton<IExcelFunctionsProcessor>(provider => new ExcelFunctionsProcessor(functions => process(functions, provider)));
}

public static IServiceCollection AddExcelFunctionsProcessor<TProcessor>(this IServiceCollection services)
where TProcessor : class, IExcelFunctionsProcessor
{
services.TryAddEnumerable(ServiceDescriptor.Singleton<IExcelFunctionsProcessor, TProcessor>());
return services;
}
}

0 comments on commit ceb6c5e

Please sign in to comment.