fix: registration
This commit is contained in:
@@ -7,11 +7,53 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
|
|||||||
|
|
||||||
namespace InServiceQue.Sample;
|
namespace InServiceQue.Sample;
|
||||||
|
|
||||||
|
public class InServiceQueBuilder
|
||||||
|
{
|
||||||
|
private IServiceCollection _services;
|
||||||
|
private ITypeRegistry _typeRegistry;
|
||||||
|
private HostedServiceRegistrator _hostedServiceRegistrator;
|
||||||
|
public InServiceQueBuilder(IServiceCollection services)
|
||||||
|
{
|
||||||
|
_services = services;
|
||||||
|
StartBuilding();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartBuilding()
|
||||||
|
{
|
||||||
|
_typeRegistry = new QueueTypeRegistry();
|
||||||
|
_services.AddSingleton<ITypeRegistry>(_typeRegistry);
|
||||||
|
_hostedServiceRegistrator = new HostedServiceRegistrator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddQueue<T, THandler>()
|
||||||
|
where T : IQueueTask
|
||||||
|
where THandler : IQueueHandler<T>
|
||||||
|
{
|
||||||
|
_typeRegistry.RegisterTaskType(typeof(T).Name, typeof(THandler).GetInterfaces()
|
||||||
|
.First(x => x.IsGenericType
|
||||||
|
&& x.GetGenericTypeDefinition() == typeof(IQueueHandler<>)));
|
||||||
|
|
||||||
|
var taskType = typeof(T);
|
||||||
|
var queueHandlerType = typeof(THandler);
|
||||||
|
//can't resolve then
|
||||||
|
_services.AddScoped(typeof(IQueueHandler<>).MakeGenericType(taskType), queueHandlerType);
|
||||||
|
|
||||||
|
var hostedServiceType = typeof(QueueService<>).MakeGenericType(taskType);
|
||||||
|
_hostedServiceRegistrator.RegisterHostedService(_services, hostedServiceType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class DIExtensions
|
public static class DIExtensions
|
||||||
{
|
{
|
||||||
|
public static void AddInServiceQue(this IServiceCollection services, Action<InServiceQueBuilder> buildAction)
|
||||||
|
|
||||||
|
{
|
||||||
|
var builder = new InServiceQueBuilder(services);
|
||||||
|
buildAction(builder);
|
||||||
|
}
|
||||||
|
|
||||||
public static IServiceCollection RegisterInternals(this IServiceCollection services)
|
public static IServiceCollection RegisterInternals(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddSingleton<ITypeRegistry, QueueTypeRegistry>();
|
|
||||||
services.AddTransient<ITaskRepository, TaskRepositoryInMemory>();
|
services.AddTransient<ITaskRepository, TaskRepositoryInMemory>();
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
@@ -19,34 +61,30 @@ public static class DIExtensions
|
|||||||
public static IServiceCollection RegisterQueues(this IServiceCollection services)
|
public static IServiceCollection RegisterQueues(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
using var sp = services.BuildServiceProvider();
|
using var sp = services.BuildServiceProvider();
|
||||||
|
var queueHandlerType = typeof(IQueueHandler<>);
|
||||||
// find all types in the assembly that implement IQueueHandler<T>
|
// find all types in the assembly that implement IQueueHandler<T>
|
||||||
var queueTypes = Assembly.GetExecutingAssembly().GetTypes()
|
var queueTypes = Assembly.GetExecutingAssembly().GetTypes()
|
||||||
.Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces()
|
.Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces()
|
||||||
.Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IQueueHandler<>)));
|
.Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == queueHandlerType));
|
||||||
var hostedServiceRegistrator = new HostedServiceRegistrator();
|
var hostedServiceRegistrator = new HostedServiceRegistrator();
|
||||||
|
|
||||||
// register each query type with its corresponding interface
|
// register each query type with its corresponding interface
|
||||||
foreach (var queueType in queueTypes)
|
foreach (var queueType in queueTypes)
|
||||||
{
|
{
|
||||||
// get the T from IQueueHandler<T>
|
// get the T from IQueueHandler<T>
|
||||||
var type = queueType.GetInterfaces()
|
var taskType = queueType.GetInterfaces()
|
||||||
.Single(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IQueueHandler<>));
|
.Single(i => i.IsGenericType && i.GetGenericTypeDefinition() == queueHandlerType);
|
||||||
|
|
||||||
// register the query type as a scoped service with its corresponding interface
|
// register the query type as a scoped service with its corresponding interface
|
||||||
services.AddScoped(queueType);
|
services.AddScoped(queueType);
|
||||||
|
|
||||||
var typeRegistry = sp.GetRequiredService<ITypeRegistry>();
|
var typeRegistry = sp.GetRequiredService<ITypeRegistry>();
|
||||||
typeRegistry.RegisterTaskType(type.GenericTypeArguments.First().Name, type);
|
typeRegistry.RegisterTaskType(taskType.GenericTypeArguments.First().Name, taskType);
|
||||||
|
|
||||||
services.AddScoped(typeof(IQueueHandler<>)
|
services.AddScoped(queueType);
|
||||||
.MakeGenericType(type.GenericTypeArguments), queueType);
|
|
||||||
|
|
||||||
//todo: bug here
|
var hostedServiceType = typeof(QueueService<>).MakeGenericType(taskType.GenericTypeArguments);
|
||||||
var hostedServiceType = typeof(QueueService<>).MakeGenericType(type.GenericTypeArguments);
|
|
||||||
hostedServiceRegistrator.RegisterHostedService(services, hostedServiceType);
|
hostedServiceRegistrator.RegisterHostedService(services, hostedServiceType);
|
||||||
|
|
||||||
// services.AddSingleton(typeof(IQueueService<>)
|
|
||||||
// .MakeGenericType(type.GenericTypeArguments), );
|
|
||||||
}
|
}
|
||||||
return services;
|
return services;
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ public class HostedServiceRegistrator
|
|||||||
{
|
{
|
||||||
public void RegisterHostedService(IServiceCollection services, Type hostedServiceType)
|
public void RegisterHostedService(IServiceCollection services, Type hostedServiceType)
|
||||||
{
|
{
|
||||||
Type servicesType = typeof(HostedServiceRegistrator);
|
var servicesType = typeof(HostedServiceRegistrator);
|
||||||
MethodInfo methodInfo = servicesType.GetMethod("AddHostedService");
|
var methodInfo = servicesType.GetMethod(nameof(AddHostedService));
|
||||||
MethodInfo genericMethod = methodInfo.MakeGenericMethod(hostedServiceType);
|
var genericMethod = methodInfo.MakeGenericMethod(hostedServiceType);
|
||||||
|
|
||||||
genericMethod.Invoke(this, new object[] { services });
|
genericMethod.Invoke(this, new object[] { services });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Needed as a work-arround because we can't call the extension method with reflection.
|
|
||||||
public IServiceCollection AddHostedService<THostedService>(IServiceCollection services)
|
public IServiceCollection AddHostedService<THostedService>(IServiceCollection services)
|
||||||
where THostedService : class, IHostedService =>
|
where THostedService : class, IHostedService =>
|
||||||
services.AddHostedService<THostedService>();
|
services.AddHostedService<THostedService>();
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ using InServiceQue.Sample;
|
|||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
builder.Services.RegisterInternals();
|
builder.Services.RegisterInternals();
|
||||||
builder.Services.RegisterQueues();
|
builder.Services.AddInServiceQue(builder =>
|
||||||
|
{
|
||||||
|
builder.AddQueue<SendMessageTask, SendMessageHandler>();
|
||||||
|
});
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app.MapGet("/", (string msg) => app.Services.GetService<ITaskRepository>().Insert(new QueueTask(new SendMessageTask(new SendMessagePayload(){To = "John", From = "Garry", Message = msg}))));
|
app.MapGet("/", (string msg) => app.Services.GetService<ITaskRepository>().Insert(new QueueTask(new SendMessageTask(new SendMessagePayload(){To = "John", From = "Garry", Message = msg}))));
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
@@ -20,12 +20,12 @@ public class SendMessageTask: IQueueTask
|
|||||||
{
|
{
|
||||||
_payload = payload;
|
_payload = payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetTypeString()
|
public string GetTypeString()
|
||||||
{
|
{
|
||||||
return nameof(SendMessageTask);
|
return nameof(SendMessageTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetPayloadString()
|
public string GetPayloadString()
|
||||||
{
|
{
|
||||||
return JsonSerializer.Serialize<SendMessagePayload>(_payload);
|
return JsonSerializer.Serialize<SendMessagePayload>(_payload);
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ where T: IQueueTask
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
await TryProcessTaskAsync();
|
await TryProcessTaskAsync();
|
||||||
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
|
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,7 @@ public class QueueTypeRegistry: ITypeRegistry
|
|||||||
public IQueueHandler GetService(IServiceScope scope, string taskType)
|
public IQueueHandler GetService(IServiceScope scope, string taskType)
|
||||||
{
|
{
|
||||||
var classType = _typeRegistry[taskType];
|
var classType = _typeRegistry[taskType];
|
||||||
return (IQueueHandler)scope.ServiceProvider.GetService(classType);
|
var service = scope.ServiceProvider.GetService(classType);
|
||||||
|
return (IQueueHandler)service;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user