当前位置: 首页 > news >正文

Lind.DDD.Messaging框架通讯组件介绍

大 家好,今天有时间来介绍一下Lind.DDD框架里的消息机制,消息发送这块一般的实现方法是将Email,SMS等集成到一个公用类库里,而本身 Email和SMS没什么关系,它们也不会有什么接口约定,即你想实现某种消息的多态发送,不需要程序代码,基本不可能实现,而在Lind.DDD里面, 大叔将它进行了抽象,消息有自己的统一接口,而对于email和sms只是一种实现而以,这样,就可以发挥面向对象的特性,在sms,email甚至是 rtx上进行消息的灵活切换了,说到这样,您心动了吧!

Lind.DDD.Messaging框架图

接口规范

    /// <summary>
    /// Message Interface
    /// Author:Garrett /// </summary> public interface IMessageManager { /// <summary> /// Sends a message to a channel using a content item as the recipient /// </summary> /// <param name="recipient">接收者</param> /// <param name="subject">主题</param> /// <param name="body">消息主体</param> /// <param name="serverVirtualPath">本参数可以没有,服务端模块级路径,只在xmpp中有意义</param> void Send(string recipient, string subject, string body, string serverVirtualPath = null); /// <summary> /// Sends a message to a channel using a set of content items as the recipients /// </summary> /// <param name="recipients">A set of content items to send the message to. Only one message may be sent if the channel manages it.</param> /// <param name="type">A custom string specifying what type of message is sent. Used in even handlers to define the message.</param> /// <param name="service">The name of the channel to use, e.g. "email"</param> /// <param name="properties">A set of specific properties for the channel.</param> void Send(IEnumerable<string> recipients, string subject, string body, string serverVirtualPath = null); /// <summary> /// Async Sends a message to a channel using a set of content items as the recipients /// </summary> /// <param name="recipients">A set of content items to send the message to. Only one message may be sent if the channel manages it.</param> /// <param name="type">A custom string specifying what type of message is sent. Used in even handlers to define the message.</param> /// <param name="service">The name of the channel to use, e.g. "email"</param> /// <param name="properties">A set of specific properties for the channel.</param> /// <param name="isAsync">is Async</param> void Send(IEnumerable<string> recipients, string subject, string body, bool isAsync, string serverVirtualPath = null); }

从接口定义上,我们看到了异步的影子,大叔把异步这块写在了参数上,当然,一般情况来说,消息应该都是异步的。

消息上下文

 /// <summary>
    /// 消息实体
    /// </summary> public class MessageContext { /// <summary> /// 消息类型 /// </summary> public MessageType Type { get; set; } /// <summary> /// 消息头 /// </summary> public string Subject { get; set; } /// <summary> /// 消息正文 /// </summary> public string Body { get; set; } /// <summary> /// 接受方地址列表 /// </summary> public IEnumerable<string> Addresses { get; set; } /// <summary> /// 是否处于准备发送状态 /// </summary> public bool MessagePrepared { get; set; } public MessageContext() { Addresses = Enumerable.Empty<string>();//这时Addresses!=null,使用Addresses.ToList().ForEach(i => Console.WriteLine(i));不会引发异常  } }

消息上下文就是消息的对象,类型于EF里的DataContext数据上下文或者HttpContext上下文,都是指实现某些功能的数据对象

消息生产者

/// <summary>
    /// 消息生产者
    /// 具体消息生产者是单例,如Email,SMS,Rtx等 /// </summary> public sealed class MessageFactory { /// <summary> /// 消息工厂 /// </summary> public static IMessageManager GetService(MessageType messageType) { switch (messageType) { case MessageType.Email: return EmailMessageManager.Instance; case MessageType.SMS: return SMSMessageManager.Instance; case MessageType.RTX: return RTXMessageManager.Instance; case MessageType.XMPP: return XMPPMessageManager.Instance; default: throw new NotImplementedException("消息生产者未被识别..."); } } }

从生产者代码上可以看出,在一个领域项目里,你可以通过GetService来使用不同的消息,这是对象的,这前大叔的设计存在一些局限性,一个项目只能用一种消息机制,这对于项目来说,是不能满足了,所以,大叔在Lind.DDD框架里对它进行了改善!

Email实现者

    /// <summary>
    ///Email消息服务
    /// </summary> internal class EmailMessageManager : IMessageManager { #region Singleton private static object lockObj = new object(); public static EmailMessageManager Instance; static string email_Address = ConfigurationManager.AppSettings["Email_Address"]; static string email_DisplayName = ConfigurationManager.AppSettings["Email_DisplayName"]; static string email_Host = ConfigurationManager.AppSettings["Email_Host"]; static string email_Password = ConfigurationManager.AppSettings["Email_Password"]; static int email_Port = Convert.ToInt32(ConfigurationManager.AppSettings["Email_Port"] ?? "21"); static string email_UserName = ConfigurationManager.AppSettings["Email_UserName"]; static EmailMessageManager() { lock (lockObj) { if (Instance == null) Instance = new EmailMessageManager(); } } private EmailMessageManager() { } #endregion #region IMessageManager 成员 public void Send(string recipient, string subject, string body, string serverVirtualPath = null) { Send(new List<string> { recipient }, subject, body); } public void Send(IEnumerable<string> recipients, string subject, string body, string serverVirtualPath = null) { Send(recipients, subject, body, false); } public void Send(IEnumerable<string> recipients, string subject, string body, bool isAsync, string serverVirtualPath = null) { try { if (recipients != null && recipients.Any()) { using (SmtpClient client = new SmtpClient() { Host = email_Host, Port = email_Port, Credentials = new NetworkCredential(email_UserName, email_Password), EnableSsl = false,//设置为true会出现"服务器不支持安全连接的错误" DeliveryMethod = SmtpDeliveryMethod.Network, }) { #region Send Message var mail = new MailMessage { From = new MailAddress(email_Address, email_DisplayName), Subject = subject, Body = body, IsBodyHtml = true, }; MailAddressCollection mailAddressCollection = new MailAddressCollection(); recipients.ToList().ForEach(i => { //email有效性验证 if (new Regex(@"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$").IsMatch(i)) mail.To.Add(i); }); if (isAsync) { client.SendCompleted += new SendCompletedEventHandler(client_SendCompleted); client.SendAsync(mail, recipients); } else { client.Send(mail); } #endregion } } } catch (Exception ex) { LoggerFactory.Instance.Logger_Info(ex.Message); } } void client_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { string arr = null; (e.UserState as List<string>).ToList().ForEach(i => { arr += i; }); //发送完成后要做的事件,可能是写日志  } #endregion }

通过代码可以看它自已是个internal的,即对外不公开,对外只能通过消息生成者进行访问,它与SMS,RTX形成了一种策略模式的概念。

SMS实现者,请看Lind.DDD源码

RTX实现者,请看Lind.DDD源码

XMPP实现者,请看Lind.DDD源码

本文转自博客园张占岭(仓储大叔)的博客,原文链接:Lind.DDD.Messaging框架通讯组件介绍,如需转载请自行联系原博主。

相关文章:

  • 未完成.队列
  • vuex的使用
  • 21、PHP和python/JAVA比,哪个更好学?
  • word 2007每次打开总出现setup error
  • C# WinForm开发系列 - GDI+【转】
  • 【自用】 Kotlin 创建自己的对话框
  • 从antlr扯淡到一点点编译原理
  • 用Canvas画一棵二叉树
  • webpack+react环境搭建与hello world
  • iOS 实现UINavigation全屏滑动返回(一)
  • c++那些事儿4 0 多态
  • 1.Node.js
  • 使用Doxygen生成C#帮助文档
  • [喵咪大数据]Hadoop集群模式
  • The working copy is locked due to previous error
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • chrome扩展demo1-小时钟
  •  D - 粉碎叛乱F - 其他起义
  • ECMAScript入门(七)--Module语法
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • Javascript编码规范
  • LintCode 31. partitionArray 数组划分
  • magento 货币换算
  • Node项目之评分系统(二)- 数据库设计
  • Shadow DOM 内部构造及如何构建独立组件
  • 关于Java中分层中遇到的一些问题
  • 好的网址,关于.net 4.0 ,vs 2010
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 聊聊flink的TableFactory
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 如何编写一个可升级的智能合约
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 使用agvtool更改app version/build
  • 用Canvas画一棵二叉树
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • C# - 为值类型重定义相等性
  • 关于Android全面屏虚拟导航栏的适配总结
  • ​Linux·i2c驱动架构​
  • #define,static,const,三种常量的区别
  • (C语言)共用体union的用法举例
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (附源码)计算机毕业设计大学生兼职系统
  • (理论篇)httpmoudle和httphandler一览
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (一)Linux+Windows下安装ffmpeg
  • (原)Matlab的svmtrain和svmclassify
  • .form文件_SSM框架文件上传篇
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)
  • .net web项目 调用webService
  • .NET/C# 使用 SpanT 为字符串处理提升性能