116 lines
4.5 KiB
C#
116 lines
4.5 KiB
C#
using Medusa.Core.Attributes;
|
|
using Medusa.Core.Handlers;
|
|
using System.Reflection;
|
|
using System.Xml.Linq;
|
|
|
|
namespace Medusa.Core.Services
|
|
{
|
|
public class HandlerService(IServiceProvider serviceProvider, ILogger<HandlerService> logger) : IHandlerService
|
|
{
|
|
private readonly IServiceProvider _serviceProvider = serviceProvider;
|
|
private readonly ILogger<HandlerService> _logger = logger;
|
|
|
|
public List<Type> Handlers { get; set; } = [];
|
|
|
|
public async Task<XDocument> Handle(string model, string module, string method, XDocument body)
|
|
{
|
|
foreach(var handler in Handlers)
|
|
{
|
|
//Module and service are on the attribute
|
|
var handlerAttribute = handler.CustomAttributes.FirstOrDefault(x => x.AttributeType == typeof(HandlerAttribute));
|
|
|
|
if(handlerAttribute is null)
|
|
{
|
|
var response = await HandleInheritanceClass(handler, model, module, method, body);
|
|
|
|
if(response is not null)
|
|
{
|
|
return response;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
var attributeModule = handlerAttribute.ConstructorArguments[0].Value.ToString();
|
|
var attributeMethod = handlerAttribute.ConstructorArguments[1].Value.ToString();
|
|
|
|
if(attributeModule == module && attributeMethod == method)
|
|
{
|
|
// Body param is optional so check for it
|
|
bool requiresXDocumentConstructor = handler.GetConstructors()
|
|
.Any(c => c.GetParameters().Any(p => p.ParameterType == typeof(XDocument)));
|
|
|
|
IHandler handlerInstance = requiresXDocumentConstructor
|
|
? (IHandler)ActivatorUtilities.CreateInstance(_serviceProvider, handler, body)
|
|
: (IHandler)ActivatorUtilities.CreateInstance(_serviceProvider, handler);
|
|
|
|
return await handlerInstance.HandleAsync(model);
|
|
}
|
|
}
|
|
|
|
//If no handler is found return an empty document
|
|
_logger.LogWarning($"No handler found for {model}/{module}/{method}");
|
|
|
|
return new XDocument();
|
|
}
|
|
|
|
private async Task<XDocument?> HandleInheritanceClass(Type handler, string model, string module, string method, XDocument body)
|
|
{
|
|
bool requiredXdocumentConstructor = handler.GetConstructors()
|
|
.Any(c => c.GetParameters().Any(p => p.ParameterType == typeof(XDocument)));
|
|
|
|
Handler handlerInstance = requiredXdocumentConstructor
|
|
? (Handler)ActivatorUtilities.CreateInstance(_serviceProvider, handler, body)
|
|
: (Handler)ActivatorUtilities.CreateInstance(_serviceProvider, handler);
|
|
|
|
try
|
|
{
|
|
var configureMethod = handler.GetMethod("Configure");
|
|
configureMethod?.Invoke(handlerInstance, null);
|
|
}
|
|
catch(NotImplementedException e)
|
|
{
|
|
_logger.LogError(e, "Configure method not implemented for {Handler}", handler.Name);
|
|
return null;
|
|
}
|
|
|
|
var handlerModule = handlerInstance.HandlerModule;
|
|
var handlerMethod = handlerInstance.HandlerMethod;
|
|
|
|
if(string.IsNullOrEmpty(handlerModule))
|
|
{
|
|
_logger.LogError("Module not set for {Handler}", handler.Name);
|
|
return null;
|
|
}
|
|
|
|
if(string.IsNullOrEmpty(handlerMethod))
|
|
{
|
|
_logger.LogError("Method not set for {Handler}", handler.Name);
|
|
return null;
|
|
}
|
|
|
|
if(handlerModule != module && handlerMethod != method)
|
|
return null;
|
|
|
|
var handleMethod = handlerInstance.GetType().GetMethod("Handle", [typeof(string)]);
|
|
var handleAsyncMethod = handlerInstance.GetType().GetMethod("HandleAsync", [typeof(string)]);
|
|
|
|
var response = new XDocument();
|
|
|
|
response = handleMethod?.DeclaringType != typeof(Handler)
|
|
? handlerInstance.Handle(model)
|
|
: handleAsyncMethod?.DeclaringType != typeof(Handler)
|
|
? await handlerInstance.HandleAsync(model)
|
|
: null;
|
|
|
|
if(response is null)
|
|
{
|
|
_logger.LogError("Handle and HandleAsync not implemented for {Handler}", handler.Name);
|
|
return null;
|
|
}
|
|
|
|
return response;
|
|
}
|
|
}
|
|
}
|