using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PasteApeart.Application.Contracts;
using PasteApeart.Handler.Extensions;
using System.Collections.Concurrent;
using System.Reflection;
using System.Text.Json;
namespace PasteApeart.Handler
{
/// <summary>
/// 队列处理 可以被RabbitMQ或者Channel的消费者调用
/// </summary>
public class EventActionHandler : IEventActionHandler
{
private const string DefaultHandleMethodName = "HandleEventAsync";
private readonly ILogger<EventActionHandler> _logger;
private readonly IServiceProvider _serviceProvider;
private readonly IChannelHelper _channelHelper;
private readonly Type[] _dtoTypeArray = null;
/// <summary>
/// 事件名 -> 事件类型。找不到时不写缓存。
/// 全系统 types 是同一份,所以 key 只放 eventName。
/// </summary>
private readonly ConcurrentDictionary<string, Type> _eventTypeCache = new();
/// <summary>
/// (事件类型, 处理方法名) -> (处理器接口类型, 处理方法)。
/// methodName 有不同入口,必须进 key。
/// </summary>
private readonly ConcurrentDictionary<(Type EventType, string MethodName), (Type HandlerType, MethodInfo HandleMethod)> _handlerCache = new();
/// <summary>
///
/// </summary>
/// <param name="logger"></param>
/// <param name="serviceProvider"></param>
/// <param name="channelHelper"></param>
/// <param name="dtoTypes"></param>
public EventActionHandler(ILogger<EventActionHandler> logger, IServiceProvider serviceProvider, IChannelHelper channelHelper, Type[] dtoTypes = null)
{
_logger = logger;
_serviceProvider = serviceProvider;
_channelHelper = channelHelper;
if (dtoTypes != null)
{
_dtoTypeArray = dtoTypes;
}
}
#region 字符串入口
/// <summary>
///
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public async Task ActionMessageAsync(string msg)
{
if (string.IsNullOrWhiteSpace(msg))
{
return;
}
if (_dtoTypeArray?.Any() != true)
{
_logger.LogError("ActionMessageAsync 的string模式下,构造函数的dtoTypes是必传的,表示EventModel所在程序集的类型集合");
return;
}
await ActionReturnResultAsync(msg, _dtoTypeArray);
}
/// <summary>
///
/// </summary>
/// <param name="msg"></param>
/// <param name="types"></param>
/// <returns></returns>
public async Task ActionMessageAsync(string msg, Type[] types)
{
if (string.IsNullOrWhiteSpace(msg))
{
return;
}
await ActionReturnResultAsync(msg, types);
}
/// <summary>
///
/// </summary>
/// <param name="msg"></param>
/// <param name="methodName"></param>
/// <returns></returns>
public async Task<object> ActionResultAsync(string msg, string methodName = DefaultHandleMethodName)
{
if (string.IsNullOrWhiteSpace(msg))
{
_logger.LogError("传入的数据不能为空");
return null;
}
if (_dtoTypeArray?.Any() != true)
{
_logger.LogError("ActionMessageAsync 的string模式下,构造函数的dtoTypes是必传的,表示EventModel所在程序集的类型集合");
return null;
}
return await ActionReturnResultAsync(msg, _dtoTypeArray, methodName);
}
/// <summary>
///
/// </summary>
/// <param name="msg"></param>
/// <param name="types"></param>
/// <param name="methodName"></param>
/// <returns></returns>
public async Task<object> ActionResultAsync(string msg, Type[] types, string methodName = DefaultHandleMethodName)
{
if (string.IsNullOrWhiteSpace(msg))
{
return null;
}
return await ActionReturnResultAsync(msg, types, methodName);
}
/// <summary>
///
/// </summary>
/// <param name="msg"></param>
/// <param name="types"></param>
/// <param name="methodName"></param>
/// <returns></returns>
public virtual async Task<object> ActionReturnResultAsync(string msg, Type[] types, string methodName = DefaultHandleMethodName)
{
object handler = null;
try
{
using var jsonDoc = JsonDocument.Parse(msg);
var root = jsonDoc.RootElement;
JsonElement eventNameProperty;
if (!root.TryGetProperty("eventName", out eventNameProperty))
{
root.TryGetProperty("EventName", out eventNameProperty);
}
string eventName = eventNameProperty.GetString();
if (string.IsNullOrEmpty(eventName))
{
_logger.LogError($"EventName 字段值为空: {msg}");
return null;
}
var modelType = ResolveEventType(eventName, types);
if (modelType == null)
{
_logger.LogError($"未找到事件类型: {eventName}");
return null;
}
var input = JsonSerializer.Deserialize(msg, modelType, JsonConfig.Options);
if (input == null)
{
_logger.LogError($"无法将消息反序列化为类型 {eventName}: {msg}");
return null;
}
using var scope = _serviceProvider.CreateScope();
if (input is IEventModel tryModel && tryModel.ExpireSecond > 0)
{
await _channelHelper.WriteAutoQueueAsync(tryModel);
return null;
}
var (handlerType, handleMethod) = ResolveHandlerInfo(modelType, methodName);
if (handleMethod == null)
{
_logger.LogError($"处理器 {handlerType.Name} 没有 {methodName} 方法");
return null;
}
handler = scope.ServiceProvider.GetRequiredService(handlerType);
if (handler == null)
{
_logger.LogError($"没有找到 {eventName} 的 IEventHandler 实现");
return null;
}
try
{
var task = handleMethod.Invoke(handler, new[] { input }) as Task;
if (task != null)
{
await task;
var resultProp = handler.GetType().GetProperty("Result");
return resultProp?.GetValue(handler);
}
else
{
_logger.LogError($"无法调用 {eventName} 的处理方法");
}
}
catch (Exception handlerExl)
{
_logger.LogException(handlerExl);
}
finally
{
await DisposeHandlerAsync(handler);
}
}
catch (Exception ex)
{
_logger.LogException(ex);
}
return null;
}
#endregion
#region 对象入口(本地 Channel 模式)
/// <summary>
///
/// </summary>
/// <param name="read"></param>
/// <returns></returns>
[Obsolete("Use ActionMessageAsync")]
public async Task HanlderEventMessage(IEventModel read)
{
await ActionMessageAsync(read);
}
/// <summary>
///
/// </summary>
/// <param name="read"></param>
/// <returns></returns>
[Obsolete("Use ActionMessageAsync")]
public async Task HanlderEventMessage(string read)
{
await ActionMessageAsync(read);
}
/// <summary>
///
/// </summary>
/// <param name="read"></param>
/// <returns></returns>
public virtual async Task ActionMessageAsync(IEventModel read)
{
if (read == null)
{
_logger.LogError("read 不能为空");
return;
}
_logger.LogInformation($"Event Msg:{read.EventName}");
var eventType = read.GetType();
var typeName = eventType.Name;
object handler = null;
try
{
using var scope = _serviceProvider.CreateScope();
var (handlerType, handleMethod) = ResolveHandlerInfo(eventType, DefaultHandleMethodName);
if (handleMethod == null)
{
_logger.LogError($"无法找到 {typeName} 的 {DefaultHandleMethodName} 方法");
return;
}
handler = scope.ServiceProvider.GetService(handlerType);
if (handler == null)
{
_logger.LogError($"没有找到 {typeName} 的 IEventHandler 实现!");
return;
}
var task = handleMethod.Invoke(handler, new[] { read }) as Task;
if (task != null)
{
await task;
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"处理事件 {eventType.Name} 时发生错误");
}
finally
{
await DisposeHandlerAsync(handler);
}
}
#endregion
#region 缓存解析 & 公共方法
/// <summary>
///
/// </summary>
/// <param name="eventName"></param>
/// <param name="types"></param>
/// <returns></returns>
private Type ResolveEventType(string eventName, Type[] types)
{
if (types == null || types.Length == 0)
{
return null;
}
if (_eventTypeCache.TryGetValue(eventName, out var cached))
{
return cached;
}
var modelType = types.FirstOrDefault(x => x.Name == eventName);
if (modelType != null)
{
_eventTypeCache.TryAdd(eventName, modelType);
}
return modelType;
}
/// <summary>
///
/// </summary>
/// <param name="eventType"></param>
/// <param name="methodName"></param>
/// <returns></returns>
private (Type HandlerType, MethodInfo HandleMethod) ResolveHandlerInfo(Type eventType, string methodName)
{
if (string.IsNullOrEmpty(methodName))
{
methodName = DefaultHandleMethodName;
}
return _handlerCache.GetOrAdd((eventType, methodName), key =>
{
var handlerType = typeof(IEventHandler<>).MakeGenericType(key.EventType);
var handleMethod = handlerType.GetMethod(key.MethodName);
return (handlerType, handleMethod);
});
}
/// <summary>
///
/// </summary>
/// <param name="handler"></param>
/// <returns></returns>
private async Task DisposeHandlerAsync(object handler)
{
if (handler == null)
{
return;
}
try
{
if (handler is IAsyncDisposable asyncDisposable)
{
await asyncDisposable.DisposeAsync();
}
else if (handler is IDisposable disposable)
{
disposable.Dispose();
}
}
catch (Exception ex)
{
_logger.LogException(ex);
}
}
#endregion
}
#region 以下是历史代码
///// <summary>
///// 队列处理 可以被RabbitMQ或者Channel的消费者调用
///// </summary>
//public class EventActionHandler : IEventActionHandler
//{
// private readonly ILogger<EventActionHandler> _logger;
// private readonly IServiceProvider _serviceProvider;
// private readonly IChannelHelper _channelHelper;
// private readonly Type[] _dtoTypeArray = null;
// /// <summary>
// /// 队列处理 可以被RabbitMQ或者Channel的消费者调用
// /// </summary>
// /// <param name="logger"></param>
// /// <param name="serviceProvider"></param>
// /// <param name="channelHelper"></param>
// /// <param name="dtoTypes"></param>
// public EventActionHandler(ILogger<EventActionHandler> logger, IServiceProvider serviceProvider, IChannelHelper channelHelper, Type[] dtoTypes = null)
// {
// _logger = logger;
// _serviceProvider = serviceProvider;
// _channelHelper = channelHelper;
// if (dtoTypes != null)
// {
// _dtoTypeArray = dtoTypes;
// }
// }
// private readonly ConcurrentDictionary<string, Type> _eventTypeCache = new();
// private readonly ConcurrentDictionary<Type, (Type HandlerType, MethodInfo HandleMethod)> _handlerCache = new();
// /// <summary>
// /// 主要适用于分布式队列 比如RabitMQ等
// /// </summary>
// /// <param name="msg"></param>
// /// <returns></returns>
// public async Task ActionMessageAsync(string msg)
// {
// if (string.IsNullOrWhiteSpace(msg))
// {
// return;
// }
// if (_dtoTypeArray?.Any() != true)
// {
// _logger.LogError("ActionMessageAsync 的string模式下,构造函数的dtoTypes是必传的,表示EventModel所在程序集的类型集合");
// return;
// }
// await ActionReturnResultAsync(msg, _dtoTypeArray);
// }
// /// <summary>
// ///
// /// </summary>
// /// <param name="msg"></param>
// /// <param name="types"></param>
// /// <returns></returns>
// public async Task ActionMessageAsync(string msg, Type[] types)
// {
// if (string.IsNullOrWhiteSpace(msg))
// {
// return;
// }
// await ActionReturnResultAsync(msg, types);
// }
// /// <summary>
// ///
// /// </summary>
// /// <param name="msg"></param>
// /// <param name="methodName"></param>
// /// <returns></returns>
// public async Task<object> ActionResultAsync(string msg, string methodName = "HandleEventAsync")
// {
// if (string.IsNullOrWhiteSpace(msg))
// {
// _logger.LogError("传入的数据不能为空");
// return null;
// }
// if (_dtoTypeArray?.Any() != true)
// {
// _logger.LogError("ActionMessageAsync 的string模式下,构造函数的dtoTypes是必传的,表示EventModel所在程序集的类型集合");
// return null;
// }
// return await ActionReturnResultAsync(msg, _dtoTypeArray, methodName);
// }
// /// <summary>
// ///
// /// </summary>
// /// <param name="msg"></param>
// /// <param name="types"></param>
// /// <param name="methodName"></param>
// /// <returns></returns>
// public async Task<object> ActionResultAsync(string msg, Type[] types, string methodName = "HandleEventAsync")
// {
// if (string.IsNullOrWhiteSpace(msg))
// {
// return null;
// }
// return await ActionReturnResultAsync(msg, types, methodName);
// }
// /// <summary>
// ///
// /// </summary>
// /// <param name="msg"></param>
// /// <param name="types"></param>
// /// <returns></returns>
// private async Task ActionAsync(string msg, Type[] types)
// {
// object input = null;
// object handler = null;
// try
// {
// // 1. 只反序列化一次,使用 System.Text.Json 性能更好
// using var jsonDoc = JsonDocument.Parse(msg);
// var root = jsonDoc.RootElement;
// JsonElement eventNameProperty;
// // 使用不区分大小写的匹配,更健壮
// if (!root.TryGetProperty("eventName", out eventNameProperty))
// {
// root.TryGetProperty("EventName", out eventNameProperty);
// }
// // 获取字符串值并验证
// string eventName = eventNameProperty.GetString();
// if (string.IsNullOrEmpty(eventName))
// {
// _logger.LogError($"EventName 字段值为空: {msg}");
// return;
// }
// // 2. 获取事件类型(带缓存)
// var modelType = _eventTypeCache.GetOrAdd(eventName, name =>
// {
// return types.FirstOrDefault(x => x.Name == name);
// });
// if (modelType == null)
// {
// _logger.LogError($"未找到事件类型: {eventName}");
// return;
// }
// // 3. 反序列化为具体类型
// input = JsonSerializer.Deserialize(msg, modelType, JsonConfig.Options);
// if (input == null)
// {
// _logger.LogError($"无法将消息反序列化为类型 {eventName}: {msg}");
// return;
// }
// using var scope = _serviceProvider.CreateScope();
// if (input is IEventModel tryModel)
// {
// if (tryModel.ExpireSecond > 0)
// {
// await _channelHelper.WriteAutoQueueAsync(tryModel);
// return;
// }
// }
// // 4. 获取处理器信息(带缓存)
// var (handlerType, handleMethod) = _handlerCache.GetOrAdd(modelType, type =>
// {
// var hType = typeof(IEventHandler<>).MakeGenericType(type);
// var method = hType.GetMethod("HandleEventAsync");
// return (hType, method);
// });
// if (handleMethod == null)
// {
// _logger.LogError($"处理器 {handlerType.Name} 没有 HandleEventAsync 方法");
// return;
// }
// handler = scope.ServiceProvider.GetRequiredService(handlerType);
// if (handler == null)
// {
// _logger.LogError($"没有找到 {eventName} 的 IEventHandler 实现");
// return;
// }
// try
// {
// // 5. 执行处理
// var task = handleMethod.Invoke(handler, new[] { input }) as Task;
// if (task != null)
// {
// await task;
// }
// else
// {
// _logger.LogError($"无法调用 {eventName} 的处理方法");
// }
// }
// catch (Exception handlerExl)
// {
// _logger.LogException(handlerExl);
// }
// finally
// {
// try
// {
// if (handler is IDisposable disposable)
// {
// disposable.Dispose();
// }
// if (handler is IAsyncDisposable disposable1)
// {
// await disposable1.DisposeAsync();
// }
// }
// catch (Exception exlDisposable)
// {
// _logger.LogException(exlDisposable);
// }
// }
// }
// catch (Exception ex)
// {
// _logger.LogException(ex);
// }
// }
// /// <summary>
// ///
// /// </summary>
// /// <param name="msg"></param>
// /// <param name="types"></param>
// /// <param name="methodName"></param>
// /// <returns></returns>
// public virtual async Task<object> ActionReturnResultAsync(string msg, Type[] types, string methodName = "HandleEventAsync")
// {
// object input = null;
// object handler = null;
// try
// {
// // 1. 只反序列化一次,使用 System.Text.Json 性能更好
// using var jsonDoc = JsonDocument.Parse(msg);
// var root = jsonDoc.RootElement;
// JsonElement eventNameProperty;
// // 使用不区分大小写的匹配,更健壮
// if (!root.TryGetProperty("eventName", out eventNameProperty))
// {
// root.TryGetProperty("EventName", out eventNameProperty);
// }
// // 获取字符串值并验证
// string eventName = eventNameProperty.GetString();
// if (string.IsNullOrEmpty(eventName))
// {
// _logger.LogError($"EventName 字段值为空: {msg}");
// return null;
// }
// // 2. 获取事件类型(带缓存)
// var modelType = _eventTypeCache.GetOrAdd(eventName, name =>
// {
// return types.FirstOrDefault(x => x.Name == name);
// });
// if (modelType == null)
// {
// _logger.LogError($"未找到事件类型: {eventName}");
// return null;
// }
// // 3. 反序列化为具体类型
// input = JsonSerializer.Deserialize(msg, modelType, JsonConfig.Options);
// if (input == null)
// {
// _logger.LogError($"无法将消息反序列化为类型 {eventName}: {msg}");
// return null;
// }
// using var scope = _serviceProvider.CreateScope();
// if (input is IEventModel tryModel)
// {
// if (tryModel.ExpireSecond > 0)
// {
// await _channelHelper.WriteAutoQueueAsync(tryModel);
// return null;
// }
// }
// // 4. 获取处理器信息(带缓存)
// var (handlerType, handleMethod) = _handlerCache.GetOrAdd(modelType, type =>
// {
// var hType = typeof(IEventHandler<>).MakeGenericType(type);
// var method = hType.GetMethod(methodName);
// return (hType, method);
// });
// if (handleMethod == null)
// {
// _logger.LogError($"处理器 {handlerType.Name} 没有 {methodName} 方法");
// return null;
// }
// handler = scope.ServiceProvider.GetRequiredService(handlerType);
// if (handler == null)
// {
// _logger.LogError($"没有找到 {eventName} 的 IEventHandler 实现");
// return null;
// }
// try
// {
// // 5. 执行处理
// var task = handleMethod.Invoke(handler, new[] { input }) as Task;
// if (task != null)
// {
// await task;
// //// 从 handler 接口上读 Result 属性(而不是从 Task<T> 里读)
// //var resultProp = handlerType.GetProperty("Result");
// //return resultProp?.GetValue(handler);
// // 用具体类型读,而不是接口类型
// var resultProp = handler.GetType().GetProperty("Result");
// return resultProp?.GetValue(handler);
// }
// else
// {
// _logger.LogError($"无法调用 {eventName} 的处理方法");
// }
// }
// catch (Exception handlerExl)
// {
// _logger.LogException(handlerExl);
// //TODO 是否自动尝试... .. .
// if (input is IEventModel inputModel)
// {
// //if(inputModel.tr)
// }
// }
// finally
// {
// try
// {
// if (handler is IDisposable disposable)
// {
// disposable.Dispose();
// }
// if (handler is IAsyncDisposable disposable1)
// {
// await disposable1.DisposeAsync();
// }
// }
// catch (Exception exlDisposable)
// {
// _logger.LogException(exlDisposable);
// }
// }
// }
// catch (Exception ex)
// {
// _logger.LogException(ex);
// }
// return null;
// }
// private readonly ConcurrentDictionary<Type, Type> _eventHandlerCache = new();
// private readonly ConcurrentDictionary<Type, MethodInfo> _handleMethodCache = new();
// /// <summary>
// ///
// /// </summary>
// /// <param name="read"></param>
// /// <returns></returns>
// [Obsolete("Use ActionMessageAsync")]
// public async Task HanlderEventMessage(IEventModel read)
// {
// await ActionMessageAsync(read);
// }
// /// <summary>
// ///
// /// </summary>
// /// <param name="read"></param>
// /// <returns></returns>
// [Obsolete("Use ActionMessageAsync")]
// public async Task HanlderEventMessage(string read)
// {
// await ActionMessageAsync(read);
// }
// /// <summary>
// /// 主要适用于本地Chennel模式
// /// </summary>
// /// <param name="read"></param>
// /// <returns></returns>
// public virtual async Task ActionMessageAsync(IEventModel read)
// {
// _logger.LogInformation($"Event Msg:{read.EventName}");
// //read是一个IEventModel
// var typeName = read.GetType().Name;
// var eventType = read.GetType();
// using var _scope = _serviceProvider.CreateScope();
// var handlerType = _eventHandlerCache.GetOrAdd(eventType, t => typeof(IEventHandler<>).MakeGenericType(t));
// var handler = _scope.ServiceProvider.GetService(handlerType);
// // 通过依赖注入获取处理器实例
// if (handler == null)
// {
// _logger.LogError($"没有找到 {typeName} 的 IEventHandler 实现!");
// return;
// }
// // 获取处理方法(带缓存)
// //var handleMethod = _handleMethodCache.GetOrAdd(eventType, t =>
// // handlerType.GetMethod("HandleEventAsync"));
// var handleMethod = _handleMethodCache.GetOrAdd(handlerType, t => t.GetMethod("HandleEventAsync"));
// if (handleMethod == null)
// {
// _logger.LogError($"无法找到 {typeName} 的 HandleEventAsync 方法");
// return;
// }
// try
// {
// var task = handleMethod.Invoke(handler, new[] { read }) as Task;
// if (task != null)
// {
// await task;
// }
// //_logger.LogInformation($"执行了 {typeName} 的 HandleEventAsync 函数");
// }
// catch (Exception ex)
// {
// _logger.LogError(ex, $"处理事件 {eventType.Name} 时发生错误");
// }
// finally
// {
// try
// {
// if (handler is IDisposable disposable)
// {
// disposable.Dispose();
// }
// if (handler is IAsyncDisposable disposable1)
// {
// await disposable1.DisposeAsync();
// }
// }
// catch (Exception exl)
// {
// _logger.LogException(exl);
// }
// }
// }
//}
#endregion
}