• 单体程序的事件发布/订阅(EventBus)


    成员介绍:

    IEventBus、EventBus:事件总线

    IEventHandler、xxxEventHandler:事件处理程序

    IEvent、xxxEvent:事件,一个事件可对应多个事件处理程序

    EventHandlerAttribute:事件处理程序的特性,可添加排序信息等

    EvnetHandlerMetadata:IEventHandler信息

    EventHandlerMetadataItem:EventHandler实例信息

    事件总线:

      1     public interface IEventBus
      2     {
      3         void Trigger<TEvent>(TEvent eventData, string topic = null) where TEvent : IEvent;
      4     }
      5     public class EventBus : IEventBus
      6     {
      7         private static System.Collections.Concurrent.ConcurrentDictionary<Type, EvnetHandlerMetadata> _evnetHandlerMetadatas
      8             = new ConcurrentDictionary<Type, EvnetHandlerMetadata>();
      9         private static readonly EventHandlerAttribute DefaultAttribute = new EventHandlerAttribute()
     10         {
     11             IgnoreError = false,
     12             Priority = 0,
     13             Topic = null
     14         };
     15 
     16         static EventBus()
     17         { }
     18 
     19 
     20         public Func<Type, object> Activator { get; set; }
     21 
     22         /// <summary>
     23         /// 触发事件
     24         /// </summary>
     25         /// <typeparam name="IEvent"></typeparam>
     26         /// <param name="eventData"></param>
     27         public void Trigger<TEvent>(TEvent eventData, string topic = null) where TEvent : IEvent
     28         {
     29 
     30             EvnetHandlerMetadata evnetHandlerMetadata = _evnetHandlerMetadatas.GetOrAdd(typeof(TEvent), (key) =>
     31             {
     32                 var handlerType = typeof(IEventHandler<>).MakeGenericType(typeof(TEvent));
     33                 var handlerMetadata = new EvnetHandlerMetadata()
     34                 {
     35                     EventHandlerType = handlerType,
     36                     EventType = key,
     37                     Items = new List<EventHandlerMetadataItem>()
     38                 };
     39                 var handlerInstances = Activator.Invoke(typeof(IEnumerable<>).MakeGenericType(handlerType)) as IEnumerable;
     40                 foreach (var handlerInstance in handlerInstances)
     41                 {
     42                     var typeInfo = handlerInstance.GetType().GetTypeInfo();
     43                     var handleMethods = typeInfo.DeclaredMethods.Where(t => t.Name.EndsWith($"{key.Name}>.Handle") || t.Name == "Handle");
     44                     var method = handleMethods.FirstOrDefault();
     45                     if (method == null) continue;
     46                     var attr = method.GetCustomAttribute<EventHandlerAttribute>()
     47                         ?? handlerInstance.GetType().GetCustomAttribute<EventHandlerAttribute>()
     48                         ?? DefaultAttribute
     49                         ;
     50                     handlerMetadata.Items.Add(new EventHandlerMetadataItem()
     51                     {
     52                         Method = method,
     53                         IgnoreError = attr.IgnoreError,
     54                         Priority = attr.Priority,
     55                         Type = handlerInstance.GetType()
     56                     });
     57                 }
     58                 handlerMetadata.Items = handlerMetadata.Items.OrderByDescending(p => p.Priority).ThenBy(x => x.Type.Name).ToList();
     59                 return handlerMetadata;
     60             });
     61 
     62             var handlers = evnetHandlerMetadata.Items
     63                 .WhereIf(p => p.Topic == topic, !string.IsNullOrEmpty(topic))
     64                 .Select(x => new { Instance = Activator.Invoke(x.Type), Meta = x })
     65                 .ToList()
     66                 ;
     67             foreach (var handler in handlers)
     68             {
     69                 try
     70                 {
     71                     handler.Meta.Method.Invoke(handler.Instance, new object[] { eventData });
     72                 }
     73                 catch (Exception ex)
     74                 {
     75                     if (!handler.Meta.IgnoreError)
     76                     {
     77                         while (true)
     78                         {
     79                             if (ex.InnerException == null)
     80                             {
     81                                 throw ex;
     82                             }
     83                             else
     84                             {
     85                                 ex = ex.InnerException;
     86                             }
     87                         }
     88 
     89                     }
     90                 }
     91             }
     92         }
     93 
     94         public class EventHandlerMetadataItem
     95         {
     96             public Type Type { get; set; }
     97             public MethodInfo Method { get; set; }
     98             public int Priority { get; set; }
     99             public bool IgnoreError { get; set; }
    100             public string Topic { get; set; }
    101 
    102         }
    103 
    104         public class EvnetHandlerMetadata
    105         {
    106             public List<EventHandlerMetadataItem> Items { get; set; }
    107             public Type EventHandlerType { get; set; }
    108             public Type EventType { get; set; }
    109 
    110         }
    111     }

    事件处理接口:

     1     /// <summary>
     2     /// 事件处理接口
     3     /// </summary>
     4     /// <typeparam name="TEvent">继承IEvent对象的事件源对象</typeparam>
     5     public interface IEventHandler<T> where T : IEvent
     6     {
     7         /// <summary>
     8         /// 处理程序
     9         /// </summary>
    10         /// <param name="evt"></param>
    11         void Handle(T evt);
    12     }
    13 
    14     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    15     public class EventHandlerAttribute : Attribute
    16     {
    17         /// <summary>
    18         /// 执行优先级
    19         /// </summary>
    20         public int Priority { get; set; }
    21         public bool IgnoreError { get; set; }
    22         public string Topic { get; set; }
    23         public EventHandlerAttribute()
    24         {
    25 
    26         }
    27     }

    public interface IEvent
    {
    }

    具体事件处理:

     1     /// <summary>
     2     /// 文件上传事件处理
     3     /// </summary>
     4     [EventHandler(Priority =1, IgnoreError = true)]
     5     public class FileUploadEventHandler : IEventHandler<FileUploadEvent>
     6     {
     7         private readonly IFeeService _feeService;
     8         private readonly ILogger _logger;
     9 
    10         public FileUploadEventHandler(
    11             IFeeService feeService,
    12             ILogger<FileUploadEventHandler> logger
    13             )
    14         {
    15             _feeService = feeService;
    16             _logger = logger;
    17         }
    18 
    19         public void Handle(FileUploadEvent evt)
    20         {
    21            // _logger.LogInformation(evt.FileName);
    22             ////扣减存储空间
    23             //var useResult=_feeService.UseFeeItem(Enums.Finance_FeeItem.Storage, evt.FileSize, $"上传文件{evt.FileName}");
    24             //if (!useResult.Success)
    25             //{
    26             //    throw new Exception(useResult.Message);
    27             //}
    28         }
    29     }

    事件触发:

    var eventBus = _serviceLocator.GetService<IEventBus>();
    eventBus.Trigger(new FileUploadEvent() { OwnUserID = globalValue.User.ID, UserID = globalValue.User.OwnUserID, Url = uploadResult.Data.Url, FileName = file.FileName, FileSize = file.Length, FileType = fileType });

    参考:https://www.cnblogs.com/lwqlun/p/10468058.html

  • 相关阅读:
    JAVA 优先获取外网Ip,再获取内网Ip
    session 关于localhost和本地IP地址 不共享问题
    读取properties的简单方法,使用@Configuration
    数组和工具类练习
    for循环练习题
    eclipse 的输入输出练习
    用eclispe练习常、变量数据类型之间的转换
    第一个java小程序
    Java基础理论(1)
    字符集
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/11971178.html
Copyright © 2020-2023  润新知