EventBus事件总线(牛x版)
成员介绍:
IEventBus、EventBus:事件总线
IEventHandler、xxxEventHandler:事件处理程序
IEvent、xxxEvent:事件,一个事件可对应多个事件处理程序
EventHandlerAttribute:事件处理程序的特性,可添加排序信息等
EvnetHandlerMetadata:IEventHandler信息
EventHandlerMetadataItem:EventHandler实例信息
事件总线:
- public interface IEventBus
- {
- void Trigger<TEvent>(TEvent eventData, string topic = null) where TEvent : IEvent;
- }
- public class EventBus : IEventBus
- {
- private static System.Collections.Concurrent.ConcurrentDictionary<Type, EvnetHandlerMetadata> _evnetHandlerMetadatas
- = new ConcurrentDictionary<Type, EvnetHandlerMetadata>();
- private static readonly EventHandlerAttribute DefaultAttribute = new EventHandlerAttribute()
- {
- IgnoreError = false,
- Priority = ,
- Topic = null
- };
- static EventBus()
- { }
- public Func<Type, object> Activator { get; set; }
- /// <summary>
- /// 触发事件
- /// </summary>
- /// <typeparam name="IEvent"></typeparam>
- /// <param name="eventData"></param>
- public void Trigger<TEvent>(TEvent eventData, string topic = null) where TEvent : IEvent
- {
- EvnetHandlerMetadata evnetHandlerMetadata = _evnetHandlerMetadatas.GetOrAdd(typeof(TEvent), (key) =>
- {
- var handlerType = typeof(IEventHandler<>).MakeGenericType(typeof(TEvent));
- var handlerMetadata = new EvnetHandlerMetadata()
- {
- EventHandlerType = handlerType,
- EventType = key,
- Items = new List<EventHandlerMetadataItem>()
- };
- var handlerInstances = Activator.Invoke(typeof(IEnumerable<>).MakeGenericType(handlerType)) as IEnumerable;
- foreach (var handlerInstance in handlerInstances)
- {
- var typeInfo = handlerInstance.GetType().GetTypeInfo();
- var handleMethods = typeInfo.DeclaredMethods.Where(t => t.Name.EndsWith($"{key.Name}>.Handle") || t.Name == "Handle");
- var method = handleMethods.FirstOrDefault();
- if (method == null) continue;
- var attr = method.GetCustomAttribute<EventHandlerAttribute>()
- ?? handlerInstance.GetType().GetCustomAttribute<EventHandlerAttribute>()
- ?? DefaultAttribute
- ;
- handlerMetadata.Items.Add(new EventHandlerMetadataItem()
- {
- Method = method,
- IgnoreError = attr.IgnoreError,
- Priority = attr.Priority,
- Type = handlerInstance.GetType()
- });
- }
- handlerMetadata.Items = handlerMetadata.Items.OrderByDescending(p => p.Priority).ThenBy(x => x.Type.Name).ToList();
- return handlerMetadata;
- });
- var handlers = evnetHandlerMetadata.Items
- .WhereIf(p => p.Topic == topic, !string.IsNullOrEmpty(topic))
- .Select(x => new { Instance = Activator.Invoke(x.Type), Meta = x })
- .ToList()
- ;
- foreach (var handler in handlers)
- {
- try
- {
- handler.Meta.Method.Invoke(handler.Instance, new object[] { eventData });
- }
- catch (Exception ex)
- {
- if (!handler.Meta.IgnoreError)
- {
- while (true)
- {
- if (ex.InnerException == null)
- {
- throw ex;
- }
- else
- {
- ex = ex.InnerException;
- }
- }
- }
- }
- }
- }
- public class EventHandlerMetadataItem
- {
- public Type Type { get; set; }
- public MethodInfo Method { get; set; }
- public int Priority { get; set; }
- public bool IgnoreError { get; set; }
- public string Topic { get; set; }
- }
- public class EvnetHandlerMetadata
- {
- public List<EventHandlerMetadataItem> Items { get; set; }
- public Type EventHandlerType { get; set; }
- public Type EventType { get; set; }
- }
- }
事件处理接口:
- /// <summary>
- /// 事件处理接口
- /// </summary>
- /// <typeparam name="TEvent">继承IEvent对象的事件源对象</typeparam>
- public interface IEventHandler<T> where T : IEvent
- {
- /// <summary>
- /// 处理程序
- /// </summary>
- /// <param name="evt"></param>
- void Handle(T evt);
- }
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
- public class EventHandlerAttribute : Attribute
- {
- /// <summary>
- /// 执行优先级
- /// </summary>
- public int Priority { get; set; }
- public bool IgnoreError { get; set; }
- public string Topic { get; set; }
- public EventHandlerAttribute()
- {
- }
- }
public interface IEvent
{
}
具体事件处理:
- /// <summary>
- /// 文件上传事件处理
- /// </summary>
- [EventHandler(Priority =, IgnoreError = true)]
- public class FileUploadEventHandler : IEventHandler<FileUploadEvent>
- {
- private readonly IFeeService _feeService;
- private readonly ILogger _logger;
- public FileUploadEventHandler(
- IFeeService feeService,
- ILogger<FileUploadEventHandler> logger
- )
- {
- _feeService = feeService;
- _logger = logger;
- }
- public void Handle(FileUploadEvent evt)
- {
- // _logger.LogInformation(evt.FileName);
- ////扣减存储空间
- //var useResult=_feeService.UseFeeItem(Enums.Finance_FeeItem.Storage, evt.FileSize, $"上传文件{evt.FileName}");
- //if (!useResult.Success)
- //{
- // throw new Exception(useResult.Message);
- //}
- }
- }
事件触发:
- 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
EventBus事件总线(牛x版)的更多相关文章
- Guava - EventBus(事件总线)
Guava在guava-libraries中为我们提供了事件总线EventBus库,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们的模块和领域边界很好的解耦设计 ...
- EventBus(事件总线)
EventBus(事件总线) Guava在guava-libraries中为我们提供了事件总线EventBus库,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们 ...
- dhroid - eventbus 事件总线
你听过onClick 事件,onItemClick 事件,事件总线不一定听过吧, eventbus 事件总线也是一个编程思想,为什么要设计EventBus了,因为他是领域驱动设计中比不可少的模块,它承 ...
- EventBus事件总线
EventBus事件总线的使用-自己实现事件总线 在C#中,我们可以在一个类中定义自己的事件,而其他的类可以订阅该事件,当某些事情发生时,可以通知到该类.这对于桌面应用或者独立的windows服务 ...
- EventBus 事件总线 案例
简介 地址:https://github.com/greenrobot/EventBus EventBus是一个[发布 / 订阅]的事件总线.简单点说,就是两人[约定]好怎么通信,一人发布消息,另外一 ...
- C#总结(六)EventBus事件总线的使用-自己实现事件总线
在C#中,我们可以在一个类中定义自己的事件,而其他的类可以订阅该事件,当某些事情发生时,可以通知到该类.这对于桌面应用或者独立的windows服务来说是非常有用的.但对于一个web应用来说是有点问题的 ...
- Android 开发 框架系列 EventBus 事件总线
介绍 GitHub:https://github.com/greenrobot/EventBus 先聊聊EventBus 线程总线是干什么的,使用环境,优点.缺点. 干什么的? 一句话,简单统一数据传 ...
- EventBus 事件总线之我的理解
用例:假设公司发布了一个公告 需要通过短信 和 邮件分别2种方式 通知员工 1:首先我们建立领域模型 /// <summary> /// 领域核心基类 /// </summary&g ...
- Orchard EventBus 事件总线及 IEventHandler作用
事件总线接口定义: public interface IEventBus : IDependency { IEnumerable Notify(string messageName, IDiction ...
随机推荐
- MySQL实战45讲学习笔记:第三十五讲
一.本节概述 在上一篇文章中,我和你介绍了 join 语句的两种算法,分别是 Index Nested-LoopJoin(NLJ) 和 Block Nested-Loop Join(BNL). 我们发 ...
- Harbor + Https 部署
关闭防火墙和selinux systemctl stop firewalld sed -i 's/SELINUX=.*/SELINUX=disabled/g' /etc/sysconfig/selin ...
- springboot项目POM文件第一行报错 Unknown Error
改成 war 不错了,但是打包麻烦 pom 文件报错 UnKnown Error第一次碰到这个问题,花了几个小时才解决,除了UnKnown 没有任何提示.网上搜的大部分情况都不是我遇到的. 还是没有解 ...
- 基于OceanStor Dorado V3存储之精简高效 Smart 系列特性
基于OceanStor Dorado V3存储之精简高效 Smart 系列特性 1.1 在线重删 1.2 在线压缩 1.3 智能精简配置 1.4 智能服务质量控制 1.5 异构虚拟化 1.6 ...
- RFC的远程调用-异步
接上篇RFC的远程调用-同步(https://www.cnblogs.com/BruceKing/p/11169930.html). TABLES:USR21. DATA:A TYPE USR21-P ...
- 【机器学习笔记】来吧!解析k-NN
序: 监督型学习与无监督学习,其最主要区别在于:已知的数据里面有没有标签(作为区别数据的内容). 监督学习大概是这个套路: 1.给定很多很多数据(假设2000个图片),并且给每个数据加上标签(与图片一 ...
- js函数定义及一些说明
1.javascript定义函数的三种方法一.function语句//这个方法比较常用function fn(){ alert("这是使用function语句进行函数定义");}f ...
- background 设置文本框背景图
background 属性的作用是给元素设置背景,它是一个复合属性,常用的子属性如下: background-color 指定元素的背景颜色. background-image 指定元素的背景图像. ...
- Python - 输入和输出 - 第十七天
Python 输入和输出 在前面几个章节中,我们其实已经接触了 Python 的输入输出的功能.本章节我们将具体介绍 Python 的输入输出. 输出格式美化 Python两种输出值的方式: 表达式语 ...
- 从VisualStudio资源文件看.NET资源处理
c# 工程里面,经常会添加资源文件. 作用: 一处文本多个地方的UI使用,最好把文本抽成资源,多处调用使用一处资源. 多语言版本支持,一份代码支持多国语言.配置多国语言的资源文件,调用处引用资源. 例 ...