Merge pull request #11199 from umbraco/register-notification-extension
v9: Added Extension method to register all custom Notifications
This commit is contained in:
104
src/Umbraco.Core/Extensions/UmbracoBuilderExtensions.cs
Normal file
104
src/Umbraco.Core/Extensions/UmbracoBuilderExtensions.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
|
||||
namespace Umbraco.Cms.Core.Extensions
|
||||
{
|
||||
public static class UmbracoBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers all <see cref="INotificationHandler{TNotification}"/> within an assembly
|
||||
/// </summary>
|
||||
/// <param name="self"><see cref="IUmbracoBuilder"/></param>
|
||||
/// <typeparam name="T">Type contained within the targeted assembly</typeparam>
|
||||
/// <returns></returns>
|
||||
public static IUmbracoBuilder AddNotificationsFromAssembly<T>(this IUmbracoBuilder self)
|
||||
{
|
||||
AddNotificationHandlers<T>(self);
|
||||
AddAsyncNotificationHandlers<T>(self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
private static void AddNotificationHandlers<T>(IUmbracoBuilder self)
|
||||
{
|
||||
var notificationHandlers = GetNotificationHandlers<T>();
|
||||
foreach (var notificationHandler in notificationHandlers)
|
||||
{
|
||||
var handlerImplementations = GetNotificationHandlerImplementations<T>(notificationHandler);
|
||||
foreach (var implementation in handlerImplementations)
|
||||
{
|
||||
RegisterNotificationHandler(self, implementation, notificationHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Type> GetNotificationHandlers<T>() =>
|
||||
typeof(T).Assembly.GetTypes()
|
||||
.Where(x => x.IsAssignableToGenericType(typeof(INotificationHandler<>)))
|
||||
.ToList();
|
||||
|
||||
private static List<Type> GetNotificationHandlerImplementations<T>(Type handlerType) =>
|
||||
handlerType
|
||||
.GetInterfaces()
|
||||
.Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(INotificationHandler<>))
|
||||
.ToList();
|
||||
|
||||
private static void AddAsyncNotificationHandlers<T>(IUmbracoBuilder self)
|
||||
{
|
||||
var notificationHandlers = GetAsyncNotificationHandlers<T>();
|
||||
foreach (var notificationHandler in notificationHandlers)
|
||||
{
|
||||
var handlerImplementations = GetAsyncNotificationHandlerImplementations<T>(notificationHandler);
|
||||
foreach (var handler in handlerImplementations)
|
||||
{
|
||||
RegisterNotificationHandler(self, handler, notificationHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Type> GetAsyncNotificationHandlers<T>() =>
|
||||
typeof(T).Assembly.GetTypes()
|
||||
.Where(x => x.IsAssignableToGenericType(typeof(INotificationAsyncHandler<>)))
|
||||
.ToList();
|
||||
|
||||
private static List<Type> GetAsyncNotificationHandlerImplementations<T>(Type handlerType) =>
|
||||
handlerType
|
||||
.GetInterfaces()
|
||||
.Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(INotificationAsyncHandler<>))
|
||||
.ToList();
|
||||
|
||||
private static void RegisterNotificationHandler(IUmbracoBuilder self, Type notificationHandlerType, Type implementingHandlerType)
|
||||
{
|
||||
var descriptor = new UniqueServiceDescriptor(notificationHandlerType, implementingHandlerType, ServiceLifetime.Transient);
|
||||
if (!self.Services.Contains(descriptor))
|
||||
{
|
||||
self.Services.Add(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsAssignableToGenericType(this Type givenType, Type genericType)
|
||||
{
|
||||
var interfaceTypes = givenType.GetInterfaces();
|
||||
|
||||
foreach (var it in interfaceTypes)
|
||||
{
|
||||
if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var baseType = givenType.BaseType;
|
||||
return baseType != null && IsAssignableToGenericType(baseType, genericType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AutoFixture;
|
||||
using AutoFixture.NUnit3;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Cms.Core.Composing;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Extensions;
|
||||
using Umbraco.Cms.Core.Hosting;
|
||||
using Umbraco.Cms.Core.Logging;
|
||||
using Umbraco.Cms.Core.Notifications;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Extensions
|
||||
{
|
||||
[TestFixture]
|
||||
public class UmbracoBuilderExtensionsTests
|
||||
{
|
||||
[Test, Customization]
|
||||
public void AddNotificationsFromAssembly_Should_AddNotificationHandler_To_ServicesCollection(IUmbracoBuilder sut)
|
||||
{
|
||||
sut.AddNotificationsFromAssembly<CustomizationAttribute>();
|
||||
|
||||
var expectedHandlerType = typeof(INotificationHandler<ContentPublishedNotification>);
|
||||
var handler = sut.Services.SingleOrDefault(x => x.ServiceType == expectedHandlerType);
|
||||
Assert.NotNull(handler);
|
||||
Assert.That(handler.ImplementationType, Is.EqualTo(typeof(StubNotificationHandler)));
|
||||
}
|
||||
|
||||
[Test, Customization]
|
||||
public void AddNotificationsFromAssembly_Should_AddAsyncNotificationHandler_To_ServicesCollection(IUmbracoBuilder sut)
|
||||
{
|
||||
sut.AddNotificationsFromAssembly<CustomizationAttribute>();
|
||||
|
||||
var expectedHandlerType = typeof(INotificationAsyncHandler<ContentPublishedNotification>);
|
||||
var handler = sut.Services.SingleOrDefault(x => x.ServiceType == expectedHandlerType);
|
||||
Assert.NotNull(handler);
|
||||
Assert.That(handler.ImplementationType, Is.EqualTo(typeof(StubNotificationHandler)));
|
||||
}
|
||||
|
||||
private class CustomizationAttribute : AutoDataAttribute
|
||||
{
|
||||
public CustomizationAttribute() : base(() => {
|
||||
var fixture = new Fixture();
|
||||
|
||||
var stub = new UmbracoBuildStub();
|
||||
fixture.Inject((IUmbracoBuilder)stub);
|
||||
|
||||
return fixture;
|
||||
}){}
|
||||
}
|
||||
|
||||
private class UmbracoBuildStub : IUmbracoBuilder
|
||||
{
|
||||
public IServiceCollection Services { get; }
|
||||
public IConfiguration Config { get; }
|
||||
public TypeLoader TypeLoader { get; }
|
||||
public ILoggerFactory BuilderLoggerFactory { get; }
|
||||
public IHostingEnvironment BuilderHostingEnvironment { get; }
|
||||
public IProfiler Profiler { get; }
|
||||
public AppCaches AppCaches { get; }
|
||||
public TBuilder WithCollectionBuilder<TBuilder>() where TBuilder : ICollectionBuilder, new() => default;
|
||||
|
||||
public UmbracoBuildStub() => Services = new ServiceCollection();
|
||||
|
||||
public void Build() {}
|
||||
}
|
||||
|
||||
private class StubNotificationHandler
|
||||
: INotificationHandler<ContentPublishedNotification>
|
||||
, INotificationAsyncHandler<ContentPublishedNotification>
|
||||
{
|
||||
public void Handle(ContentPublishedNotification notification) { }
|
||||
|
||||
public Task HandleAsync(ContentPublishedNotification notification, CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user