.netcore利用DI实现订阅者模式 - xms
结合DI,实现发布者与订阅者的解耦,属于本次事务的对象主体不应定义为订阅者,因为订阅者不应与发布者产生任何关联
一、发布者订阅者模式
发布者发出一个事件主题,一个或多个订阅者接收这个事件,中间通过事件总线通讯(消息队列),并且发布者与订阅者这两者间是无状态的,根据产品实际场景需要,可以自己实现单机单点的发布订阅,也可选择使用目前流行的分布式消息中间件:
RabbitMQ、ActiveMQ、RocketMQ、kafka等
二、观察者与订阅者的区别
观察者与业务主体是耦合的,并且是即时通知的;订阅者与业务主体完全解耦,只通过中间的信息通道通知,互相不知道对方的存在,可以是同步也可以是异步
三、具体实现
本文主要讲解单点模式,有需要随时可以扩展为分布式方案
发布者接口:
namespace Xms.Event.Abstractions
{
/// <summary>
/// 事件发布接口
/// </summary>
public interface IEventPublisher
{
/// <summary>
/// 发布事件
/// </summary>
/// <typeparam name="TEvent">事件类型</typeparam>
/// <param name="e"></param>
void Publish<TEvent>(TEvent e);
}
}
发布者实现:
using System;
using System.Linq;
using Xms.Event.Abstractions;
using Xms.Infrastructure.Inject;
using Xms.Logging.AppLog; namespace Xms.Event
{
/// <summary>
/// 事件发布者
/// </summary>
public class EventPublisher : IEventPublisher
{
private readonly ILogService _logService;
private readonly IServiceResolver _serviceResolver; public EventPublisher(ILogService logService
, IServiceResolver serviceResolver)
{
_logService = logService;
_serviceResolver = serviceResolver;
} #region Methods /// <summary>
/// 发布事件
/// </summary>
/// <typeparam name="TEvent">事件类</typeparam>
/// <param name="e">事件对象</param>
public virtual void Publish<TEvent>(TEvent e)
{
//获取所有事件接收者
var consumers = _serviceResolver.GetAll<IConsumer<TEvent>>().ToList();
foreach (var consumer in consumers)
{
try
{
//处理事件
consumer.HandleEvent(e);
}
catch (Exception exception)
{
_logService.Error(exception);
}
}
} #endregion Methods
}
}
订阅(消费)者接口:
namespace Xms.Event.Abstractions
{
/// <summary>
/// 事件接收接口
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IConsumer<T>
{
/// <summary>
/// 处理事件
/// </summary>
/// <param name="eventMessage">事件</param>
void HandleEvent(T eventMessage);
}
}
事件(消息):
这里只给出一个作为示例,实际上一般会有记录的:“创建”、“修改”、“删除”,流程相关的:“发起审批”、“审批通过”、“审批完成”等等
namespace Xms.Flow.Core.Events
{
/// <summary>
/// 工作流启动后事件
/// </summary>
public class WorkFlowStartedEvent
{
public WorkFlowStartUpContext Context { get; set; }
public WorkFlowExecutionResult Result { get; set; }
}
}
服务注册:
详细实现回看.netcore之DI批量注入(支持泛型)
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Xms.Core;
using Xms.Infrastructure.Inject; namespace Xms.Event
{
/// <summary>
/// 事件模块服务注册
/// </summary>
public class ServiceRegistrar : IServiceRegistrar
{
public int Order => ; public void Add(IServiceCollection services, IConfiguration configuration)
{
//event publisher
services.AddScoped<Event.Abstractions.IEventPublisher, Event.EventPublisher>();
//event consumers
services.RegisterScope(typeof(Event.Abstractions.IConsumer<>));
}
}
}
四、应用场景
比如在工作流启动审批后发送通知
using System.Collections.Generic;
using Xms.Context;
using Xms.Event.Abstractions;
using Xms.Flow.Core.Events;
using Xms.Infrastructure.Utility;
using Xms.Localization.Abstractions;
using Xms.Notify.Abstractions;
using Xms.Notify.Internal; namespace Xms.EventConsumers.Notify
{
/// <summary>
/// 工作流启动审批后发送通知
/// </summary>
public class WorkflowStartedNotify : IConsumer<WorkFlowStartedEvent>
{
private readonly IAppContext _appContext;
private readonly ILocalizedTextProvider _loc;
private readonly IEnumerable<INotify> _notifies; public WorkflowStartedNotify(IAppContext appContext
, IEnumerable<INotify> notifies)
{
_appContext = appContext;
_loc = _appContext.GetFeature<ILocalizedTextProvider>();
_notifies = notifies;
}
public void HandleEvent(WorkFlowStartedEvent eventMessage)
{
//当前节点处理人
foreach (var handlerId in eventMessage.Result.NextHandlerId)
{
//通知方式:微信、短信、邮件、系统消息等
var msg = _loc["workflow_newtasknotify"].FormatWith(eventMessage.Context.EntityMetaData.LocalizedName);
//发送消息
foreach (var notifier in _notifies)
{
notifier.Send(new InternalNotifyBody()
{
TypeCode =
,
Subject = msg
,
Content = "到你审批了,快到碗里来"
,
ToUserId = handlerId
,
LinkTo = "/entity/create?entityid=" + eventMessage.Context.EntityMetaData.EntityId + "&recordid=" + eventMessage.Context.ObjectId
});
}
}
}
}
}
四、总结
前面讲解了订阅者模式的基本概念及与观察者的区别,后面展示了具体实现及实际应用场景,大家记住一点就行,这些设计模式最终都是为了达到解藕的目的,要查看完整代码,请回到这一章
xms跨平台基础框架 - 基于.netcore
.netcore利用DI实现订阅者模式 - xms的更多相关文章
- .netcore之DI批量注入(支持泛型) - xms
一旦系统内模块比较多,按DI标准方法去逐个硬敲AddScoped/AddSingleton/AddTransient缺乏灵活性且效率低下,所以批量注入提供了很大的便捷性,特别是对于泛型的服务类,下面介 ...
- 利用DI实现级联删除 - xms跨平台基础框架 - 基于.netcore
一.引言 所谓级联删除是指删除一条记录后,附带关联记录也一起删除,比如删除客户后,联系人也一起删除: 以往我们会依赖于数据库表的外键约束,但存在着明显的问题,增加数据库压力.提示不友好.职责越界.事务 ...
- AngularJS的简单订阅发布模式例子
控制器之间的交互方式广播 broadcast, 发射 emit 事件 类似于 js中的事件 , 可以自己定义事件 向上传递直到 document 在AngularJs中 向上传递直到 rootScop ...
- js设计模式之代理模式以及订阅发布模式
为啥将两种模式放在一起呢?因为这样文章比较长啊. 写博客的目的我觉得首要目的是整理自己的知识点,进而优化个人所得知识体系.知识成为个人的知识,就在于能够用自己的话表达同一种意义. 本文是设计模式系列文 ...
- RabbitMQ (五) 订阅者模式之分发模式 ( fanout )
前面讲到了简单队列和工作队列. 这两种队列有个非常明显的缺点 : 生产者发送的消息,只能进入到一个队列. 消息只能进入到一个队列就意味着消息只能被一个消费者消费. 尽管工作队列模式中,一个队列中的消息 ...
- C#事件支持发布者/订阅者模式(观察者模式)
C#事件支持发布者/订阅者模式,发布者将事件通知给订阅者,而订阅者在事件发生时调用已经注册好的事件处理函数. public delegate void delUpdate(); //委 ...
- Android 订阅-发布者模式-详解
1.概念简述 Android 简称观察者模式, GoF说道:Observer模式的意图是“定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新”. 有 ...
- Publisher/Subscriber 订阅-发布模式
Publisher/Subscriber 订阅-发布模式 本博后续将陆续整理这些年做的一些预研demo,及一些前沿技术的研究,与大家共研技术,共同进步. 关于发布订阅有很多种实现方式,下面主要介绍WC ...
- 设计模式---订阅发布模式(Subscribe/Publish)
设计模式---订阅发布模式(Subscribe/Publish) 订阅发布模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象.这个主题对象在自身状态变化时,会通知所有订阅者对象,使 ...
随机推荐
- XCTF-Misc
最近无聊在做一下杂项,随便总结一下关于杂项的知识. 一. xcaliflag 这个直接拖进stegsolve里面,大约是在Blue的第3位左右就很清楚了 二.
- ORM查询简化
文章出处 https://www.cnblogs.com/wupeiqi/articles/6216618.html 字段 常用字段 AutoField(Field) - int自增列,必须填入参数 ...
- 04-12 scikit-learn库之随机森林
目录 scikit-learn库之随机森林 一.RandomForestClassifier 1.1 使用场景 1.2 代码 1.3 参数 1.4 属性 1.5 方法 二.RandomForestRe ...
- Java Intellij 第一个HelloWord
前言 最近重心点都在Java, 鉴于避免一些跟我一样学习Java开始啥都不懂,不知如何下手,方便小白快速入门.故写下此文,鉴于分享. (前提是安装jdk, 建议使用版本是1.8) JDK 安装地址:h ...
- bugku 成绩单
看起来像是SQL注入,先来试试. 输入1,2,3显示的是三个人成绩. 来试试是否存在注入. 输入1,正常.输入1' 错误.输入1’#正常,说明存在注入点. 首先来看下有几列从1开始试,1’ order ...
- Web前端学习,需用了解的7大HTML知识点
HTML是web前端开发基础,关于HTML,这里有几个很重要的知识点,在日常开发常常用到,并且在大家面试的时候也会问的,记住这7个重要知识点,助你在面试时优先录用. 1.网页结构 网页结构一般都包含文 ...
- vue在一个方法执行完后再执行另一个方法
vue在一个方法执行完后执行另一个方法 用Promise来实现.Promise是ES6的新特性,用于处理异步操作逻辑,用过给Promise添加then和catch函数,处理成功和失败的情况 ES7中新 ...
- php后端开发要学什么
PHP历史: 1994年创建,1995年对外发表第一个版本,名为:personal home page tools,之后发表PHP1.0.1995年中期,PHP2.0,从此建立了PHP在动态网站开发的 ...
- Orleans 知多少 | 3. Hello Orleans
1. 引言 是的,Orleans v3.0.0 已经发布了,并已经完全支持 .NET Core 3.0. 所以,Orleans 系列是时候继续了,抱歉,让大家久等了. 万丈高楼平地起,这一节我们就先来 ...
- StopWatch任务计时器
介 绍: StopWatch 是用来计算程序块的执行时间工具, 目前有好多框架都有实现提供此工具(实现结果都区别不大), 本文介绍org.springframework.util.StopWatc ...