-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEventingServiceCollectionExtensions.cs
More file actions
77 lines (66 loc) · 2.64 KB
/
Copy pathEventingServiceCollectionExtensions.cs
File metadata and controls
77 lines (66 loc) · 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
using System.Reflection;
using Domain.Eventing;
using Microsoft.Extensions.DependencyInjection;
namespace Application.Eventing;
public static class EventingServiceCollectionExtensions
{
public static void AddEventing(this IServiceCollection services, params Assembly[] assemblies)
{
// Get all handler types once
var handlerTypes = GetEventHandlerTypes(assemblies);
// One singleton registry, populated via factory
services.AddSingleton<HandlerRegistry>(_ => BuildRegistry(handlerTypes));
// Dispatcher uses the same registry and current scope's services
services.AddScoped<IEventDispatcher, EventDispatcher>();
services.AddScoped<IAsyncEventDispatcher, AsyncEventDispatcher>();
// Register all handler types found by scanning
foreach (var type in handlerTypes)
{
services.AddScoped(type);
}
}
private static HandlerRegistry BuildRegistry(IEnumerable<Type> handlerTypes)
{
var registry = new HandlerRegistry();
handlerTypes
.SelectMany(type => type.GetInterfaces()
.Where(i => i.IsGenericType &&
(i.GetGenericTypeDefinition() == typeof(IEventHandler<>) ||
i.GetGenericTypeDefinition() == typeof(IAsyncEventHandler<>)))
.Select(i => new { Interface = i, HandlerType = type }))
.ToList()
.ForEach(item =>
{
var isAsync = item.Interface.GetGenericTypeDefinition() == typeof(IAsyncEventHandler<>);
registry.Register(item.Interface.GetGenericArguments()[0], item.HandlerType, isAsync);
});
return registry;
}
private static List<Type> GetEventHandlerTypes(Assembly[] assemblies)
{
return assemblies.Distinct()
.SelectMany(GetTypesFromAssembly)
.Where(t => t is { IsAbstract: false, IsInterface: false })
.Where(IsEventHandlerType)
.ToList();
}
private static Type[] GetTypesFromAssembly(Assembly assembly)
{
try
{
return assembly.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
// Use only the types that could be loaded successfully
return ex.Types.Where(t => t != null).ToArray()!;
}
}
private static bool IsEventHandlerType(Type type)
{
return type.GetInterfaces()
.Any(i => i.IsGenericType &&
(i.GetGenericTypeDefinition() == typeof(IEventHandler<>) ||
i.GetGenericTypeDefinition() == typeof(IAsyncEventHandler<>)));
}
}