.netcore利用DI實現訂閱者模式 - xms

結合DI,實現發佈者與訂閱者的解耦,屬於本次事務的對象主體不該定義爲訂閱者,由於訂閱者不該與發佈者產生任何關聯html

1、發佈者訂閱者模式設計模式

發佈者發出一個事件主題,一個或多個訂閱者接收這個事件,中間經過事件總線通信(消息隊列),而且發佈者與訂閱者這二者間是無狀態的,根據產品實際場景須要,能夠本身實現單機單點的發佈訂閱,也可選擇使用目前流行的分佈式消息中間件:微信

RabbitMQ、ActiveMQ、RocketMQ、kafka等app

2、觀察者與訂閱者的區別框架

觀察者與業務主體是耦合的,而且是即時通知的;訂閱者與業務主體徹底解耦,只經過中間的信息通道通知,互相不知道對方的存在,能夠是同步也能夠是異步異步

3、具體實現分佈式

本文主要講解單點模式,有須要隨時能夠擴展爲分佈式方案ide

發佈者接口:post

 1 namespace Xms.Event.Abstractions
 2 {
 3     /// <summary>
 4     /// 事件發佈接口
 5     /// </summary>
 6     public interface IEventPublisher
 7     {
 8         /// <summary>
 9         /// 發佈事件
10         /// </summary>
11         /// <typeparam name="TEvent">事件類型</typeparam>
12         /// <param name="e"></param>
13         void Publish<TEvent>(TEvent e);
14     }
15 }

發佈者實現:url

 1 using System;
 2 using System.Linq;
 3 using Xms.Event.Abstractions;
 4 using Xms.Infrastructure.Inject;
 5 using Xms.Logging.AppLog;
 6 
 7 namespace Xms.Event
 8 {
 9     /// <summary>
10     /// 事件發佈者
11     /// </summary>
12     public class EventPublisher : IEventPublisher
13     {
14         private readonly ILogService _logService;
15         private readonly IServiceResolver _serviceResolver;
16 
17         public EventPublisher(ILogService logService
18             , IServiceResolver serviceResolver)
19         {
20             _logService = logService;
21             _serviceResolver = serviceResolver;
22         }
23 
24         #region Methods
25 
26         /// <summary>
27         /// 發佈事件
28         /// </summary>
29         /// <typeparam name="TEvent">事件類</typeparam>
30         /// <param name="e">事件對象</param>
31         public virtual void Publish<TEvent>(TEvent e)
32         {
33             //獲取全部事件接收者
34             var consumers = _serviceResolver.GetAll<IConsumer<TEvent>>().ToList();
35             foreach (var consumer in consumers)
36             {
37                 try
38                 {
39                     //處理事件
40                     consumer.HandleEvent(e);
41                 }
42                 catch (Exception exception)
43                 {
44                     _logService.Error(exception);
45                 }
46             }
47         }
48 
49         #endregion Methods
50     }
51 }

訂閱(消費)者接口:

 1 namespace Xms.Event.Abstractions
 2 {
 3     /// <summary>
 4     /// 事件接收接口
 5     /// </summary>
 6     /// <typeparam name="T"></typeparam>
 7     public interface IConsumer<T>
 8     {
 9         /// <summary>
10         /// 處理事件
11         /// </summary>
12         /// <param name="eventMessage">事件</param>
13         void HandleEvent(T eventMessage);
14     }
15 }

事件(消息):

這裏只給出一個做爲示例,實際上通常會有記錄的:「建立」、「修改」、「刪除」,流程相關的:「發起審批」、「審批經過」、「審批完成」等等

 1 namespace Xms.Flow.Core.Events
 2 {
 3     /// <summary>
 4     /// 工做流啓動後事件
 5     /// </summary>
 6     public class WorkFlowStartedEvent
 7     {
 8         public WorkFlowStartUpContext Context { get; set; }
 9         public WorkFlowExecutionResult Result { get; set; }
10     }
11 }

服務註冊:

詳細實現回看.netcore之DI批量注入(支持泛型)

 1 using Microsoft.Extensions.Configuration;
 2 using Microsoft.Extensions.DependencyInjection;
 3 using Xms.Core;
 4 using Xms.Infrastructure.Inject;
 5 
 6 namespace Xms.Event
 7 {
 8     /// <summary>
 9     /// 事件模塊服務註冊
10     /// </summary>
11     public class ServiceRegistrar : IServiceRegistrar
12     {
13         public int Order => 1;
14 
15         public void Add(IServiceCollection services, IConfiguration configuration)
16         {
17             //event publisher
18             services.AddScoped<Event.Abstractions.IEventPublisher, Event.EventPublisher>();
19             //event consumers
20             services.RegisterScope(typeof(Event.Abstractions.IConsumer<>));
21         }
22     }
23 }

4、應用場景

好比在工做流啓動審批後發送通知

 1 using System.Collections.Generic;
 2 using Xms.Context;
 3 using Xms.Event.Abstractions;
 4 using Xms.Flow.Core.Events;
 5 using Xms.Infrastructure.Utility;
 6 using Xms.Localization.Abstractions;
 7 using Xms.Notify.Abstractions;
 8 using Xms.Notify.Internal;
 9 
10 namespace Xms.EventConsumers.Notify
11 {
12     /// <summary>
13     /// 工做流啓動審批後發送通知
14     /// </summary>
15     public class WorkflowStartedNotify : IConsumer<WorkFlowStartedEvent>
16     {
17         private readonly IAppContext _appContext;
18         private readonly ILocalizedTextProvider _loc;
19         private readonly IEnumerable<INotify> _notifies;
20 
21         public WorkflowStartedNotify(IAppContext appContext
22             , IEnumerable<INotify> notifies)
23         {
24             _appContext = appContext;
25             _loc = _appContext.GetFeature<ILocalizedTextProvider>();
26             _notifies = notifies;
27         }
28         public void HandleEvent(WorkFlowStartedEvent eventMessage)
29         {
30             //當前節點處理人
31             foreach (var handlerId in eventMessage.Result.NextHandlerId)
32             {
33                 //通知方式:微信、短信、郵件、系統消息等
34                 var msg = _loc["workflow_newtasknotify"].FormatWith(eventMessage.Context.EntityMetaData.LocalizedName);
35                 //發送消息
36                 foreach (var notifier in _notifies)
37                 {
38                     notifier.Send(new InternalNotifyBody()
39                     {
40                         TypeCode = 2
41                         ,
42                         Subject = msg
43                         ,
44                         Content = "到你審批了,快到碗裏來"
45                         ,
46                         ToUserId = handlerId
47                         ,
48                         LinkTo = "/entity/create?entityid=" + eventMessage.Context.EntityMetaData.EntityId + "&recordid=" + eventMessage.Context.ObjectId
49                     });
50                 }
51             }
52         }
53     }
54 }

 

4、總結

前面講解了訂閱者模式的基本概念及與觀察者的區別,後面展現了具體實現及實際應用場景,你們記住一點就行,這些設計模式最終都是爲了達到解藕的目的,要查看完整代碼,請回到這一章

xms跨平臺基礎框架 - 基於.netcore

相關文章
相關標籤/搜索