Skip to content

Commit

Permalink
Merge pull request #247 from SixLabors/js/insert-provider
Browse files Browse the repository at this point in the history
Add InsertProvider extensions and tests
  • Loading branch information
JimBobSquarePants authored Apr 5, 2022
2 parents 8892d76 + 198e8f4 commit b922f29
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,45 @@ public static IImageSharpBuilder AddProvider<TProvider>(this IImageSharpBuilder
return builder;
}

/// <summary>
/// Inserts the given <see cref="IImageProvider"/> at the give index into to the provider collection within the service collection.
/// </summary>
/// <typeparam name="TProvider">The type of class implementing <see cref="IImageProvider"/>to add.</typeparam>
/// <param name="builder">The core builder.</param>
/// <param name="index">The zero-based index at which the provider should be inserted.</param>
/// <returns>The <see cref="IImageSharpBuilder"/>.</returns>
public static IImageSharpBuilder InsertProvider<TProvider>(this IImageSharpBuilder builder, int index)
where TProvider : class, IImageProvider
{
var descriptors = builder.Services.Where(x => x.ServiceType == typeof(IImageProvider)).ToList();
builder.ClearProviders();

descriptors.Insert(index, ServiceDescriptor.Singleton<IImageProvider, TProvider>());

builder.Services.TryAddEnumerable(descriptors);
return builder;
}

/// <summary>
/// Inserts the given <see cref="IImageProvider"/> at the give index into the provider collection within the service collection.
/// </summary>
/// <typeparam name="TProvider">The type of class implementing <see cref="IImageProvider"/>to add.</typeparam>
/// <param name="builder">The core builder.</param>
/// <param name="index">The zero-based index at which the provider should be inserted.</param>
/// <param name="implementationFactory">The factory method for returning a <see cref="IImageProvider"/>.</param>
/// <returns>The <see cref="IImageSharpBuilder"/>.</returns>
public static IImageSharpBuilder InsertProvider<TProvider>(this IImageSharpBuilder builder, int index, Func<IServiceProvider, TProvider> implementationFactory)
where TProvider : class, IImageProvider
{
var descriptors = builder.Services.Where(x => x.ServiceType == typeof(IImageProvider)).ToList();
builder.ClearProviders();

descriptors.Insert(index, ServiceDescriptor.Singleton<IImageProvider>(implementationFactory));

builder.Services.TryAddEnumerable(descriptors);
return builder;
}

/// <summary>
/// Removes the given <see cref="IImageProvider"/> from the provider collection within the service collection.
/// </summary>
Expand All @@ -166,7 +205,6 @@ public static IImageSharpBuilder RemoveProvider<TProvider>(this IImageSharpBuild
{
ServiceDescriptor descriptor = builder.Services.FirstOrDefault(x =>
x.ServiceType == typeof(IImageProvider)
&& x.Lifetime == ServiceLifetime.Singleton
&& (x.ImplementationType == typeof(TProvider)
|| (x.ImplementationFactory?.GetMethodInfo().ReturnType == typeof(TProvider))));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.

using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using SixLabors.ImageSharp.Web.Caching;
Expand Down Expand Up @@ -40,6 +42,8 @@ private static bool IsServiceImplementationFactory<TService, TImplementation>(Se
(descriptor.ImplementationFactory?.GetMethodInfo().ReturnType == typeof(TImplementation) ||
descriptor.ImplementationFactory?.Invoke(null)?.GetType() == typeof(TImplementation)); // OK to invoke the factory in tests

private static IReadOnlyList<ServiceDescriptor> GetCollection<T>(IServiceCollection serviceDescriptors) => serviceDescriptors.Where(x => x.ServiceType == typeof(T)).ToList();

[Fact]
public void DefaultServicesAreRegistered()
{
Expand Down Expand Up @@ -174,6 +178,24 @@ public void CanAddRemoveImageProviders()
Assert.DoesNotContain(services, IsService<IImageProvider, MockImageProvider>);
}

[Fact]
public void CanInsertRemoveImageProviders()
{
var services = new ServiceCollection();
IImageSharpBuilder builder = services.AddImageSharp();

builder.InsertProvider<MockImageProvider>(0);
Assert.Single(services, IsService<IImageProvider, MockImageProvider>);
Assert.Single(services, IsServiceImplementationType<IImageProvider, MockImageProvider>);

IReadOnlyList<ServiceDescriptor> providers = GetCollection<IImageProvider>(services);
Assert.Equal(2, providers.Count);
Assert.True(IsService<IImageProvider, MockImageProvider>(providers[0]));

builder.RemoveProvider<MockImageProvider>();
Assert.DoesNotContain(services, IsService<IImageProvider, MockImageProvider>);
}

[Fact]
public void CanAddRemoveFactoryImageProviders()
{
Expand All @@ -188,6 +210,25 @@ public void CanAddRemoveFactoryImageProviders()
Assert.DoesNotContain(services, IsService<IImageProvider, MockImageProvider>);
}

[Fact]
public void CanInsertRemoveFactoryImageProviders()
{
var services = new ServiceCollection();
IImageSharpBuilder builder = services.AddImageSharp();

builder.InsertProvider(0, _ => new MockImageProvider());
Assert.Single(services, IsService<IImageProvider, MockImageProvider>);
Assert.Single(services, IsServiceImplementationFactory<IImageProvider, MockImageProvider>);

IReadOnlyList<ServiceDescriptor> providers = GetCollection<IImageProvider>(services);
Assert.Equal(2, providers.Count);
Assert.True(IsService<IImageProvider, MockImageProvider>(providers[0]));
Assert.True(IsServiceImplementationFactory<IImageProvider, MockImageProvider>(providers[0]));

builder.RemoveProvider<MockImageProvider>();
Assert.DoesNotContain(services, IsService<IImageProvider, MockImageProvider>);
}

[Fact]
public void CanAddRemoveAllImageProviders()
{
Expand Down

0 comments on commit b922f29

Please sign in to comment.