成员介绍:

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版)的更多相关文章

  1. Guava - EventBus(事件总线)

    Guava在guava-libraries中为我们提供了事件总线EventBus库,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们的模块和领域边界很好的解耦设计 ...

  2. EventBus(事件总线)

    EventBus(事件总线) Guava在guava-libraries中为我们提供了事件总线EventBus库,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们 ...

  3. dhroid - eventbus 事件总线

    你听过onClick 事件,onItemClick 事件,事件总线不一定听过吧, eventbus 事件总线也是一个编程思想,为什么要设计EventBus了,因为他是领域驱动设计中比不可少的模块,它承 ...

  4. EventBus事件总线

    EventBus事件总线的使用-自己实现事件总线   在C#中,我们可以在一个类中定义自己的事件,而其他的类可以订阅该事件,当某些事情发生时,可以通知到该类.这对于桌面应用或者独立的windows服务 ...

  5. EventBus 事件总线 案例

    简介 地址:https://github.com/greenrobot/EventBus EventBus是一个[发布 / 订阅]的事件总线.简单点说,就是两人[约定]好怎么通信,一人发布消息,另外一 ...

  6. C#总结(六)EventBus事件总线的使用-自己实现事件总线

    在C#中,我们可以在一个类中定义自己的事件,而其他的类可以订阅该事件,当某些事情发生时,可以通知到该类.这对于桌面应用或者独立的windows服务来说是非常有用的.但对于一个web应用来说是有点问题的 ...

  7. Android 开发 框架系列 EventBus 事件总线

    介绍 GitHub:https://github.com/greenrobot/EventBus 先聊聊EventBus 线程总线是干什么的,使用环境,优点.缺点. 干什么的? 一句话,简单统一数据传 ...

  8. EventBus 事件总线之我的理解

    用例:假设公司发布了一个公告 需要通过短信 和 邮件分别2种方式 通知员工 1:首先我们建立领域模型 /// <summary> /// 领域核心基类 /// </summary&g ...

  9. Orchard EventBus 事件总线及 IEventHandler作用

    事件总线接口定义: public interface IEventBus : IDependency { IEnumerable Notify(string messageName, IDiction ...

随机推荐

  1. 小白专场-是否同一颗二叉搜索树-c语言实现

    目录 一.题意理解 二.求解思路 三.搜索树表示 程序框架搭建 3.1 如何建搜索树 3.2 如何判别 3.3 清空树 更新.更全的<数据结构与算法>的更新网站,更有python.go.人 ...

  2. [开源]OSharpNS 步步为营系列 - 1. 业务模块设计

    什么是OSharp OSharpNS全称OSharp Framework with .NetStandard2.0,是一个基于.NetStandard2.0开发的一个.NetCore快速开发框架.这个 ...

  3. C++:Copy & Reference Count

    浅拷贝.深拷贝 通常,我们会按如下方式书写拷贝构造函数: class LiF { public: LiF(int _lif = 0) : lif(_lif) {} // 默认构造函数 LiF(cons ...

  4. WebApi安全性 参数签名校验(结合Axios使用)

    接口参数签名校验,是WebApi接口服务最重要的安全防护手段之一. 结合项目中实际使用情况,介绍下前后端参数签名校验实现方案. 签名校验规则 http请求,有两种传参形式: 1.通过url传参,最常见 ...

  5. datalab (原发布 csdn 2018年09月21日 20:42:54)

    首先声明datalab本人未完成,有4道题目没有做出来.本文博客记录下自己的解析,以便以后回忆.如果能帮助到你就更好了,如果觉得本文没啥技术含量,也望多多包涵. /* * bitAnd - x& ...

  6. 三维网格补洞算法(Poisson Method)(转载)

    转载:https://www.cnblogs.com/shushen/p/5864042.html 下面介绍一种基于Poisson方程的三角网格补洞方法.该算法首先需要根据孔洞边界生成一个初始化补洞网 ...

  7. NetCoreApi框架搭建(一、swagger插件使用)

    1.首先用vs2017创建新的项目 2.开始引入swagger插件 右击项目=>管理NuGet程序包=>搜索Swashbuckle.AspNetCore点击安装 3.打开Startup.c ...

  8. 解决:500 Internal Privoxy Error

    500 Internal Privoxy Error Privoxy encountered an error while processing your request: Could not loa ...

  9. Struts2框架简单介绍

    如需,了解Struts2详情,请点击,传送门 工作原理 在Struts2 框架中的处理大概分为以下步骤: 1.客户端初始化一个指向servlet容器(例如Tomcat)的请求. 2.这个请求经过一系列 ...

  10. Python【day 14-2】递归遍历文件夹

    #需求 遍历文件夹中所有的子文件夹及子文件--用递归实现 '''''' ''' 伪代码 1.遍历根目录--listdir for 得到第一级子文件夹(不包含子文件夹的子文件)和文件 2.判断是文件还是 ...