回到目录

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

Lind.DDD.Messaging框架图

aaarticlea/png;base64,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" alt="" />

接口规范

    /// <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源码

回到目录

最新文章

  1. js 批量设置css样式
  2. thinkphp一句话疑难解决笔记 3
  3. Python字符串的encode与decode研究心得乱码问题解决方法
  4. WPF学习之路(十二)控件(Content控件)
  5. NOIP“对偶”题:还教室
  6. 01-UIKit
  7. 没有理由,就是要上一波C++的东西
  8. 2017年9月3日 Spring及Mybatis中连接数据库的不同方式
  9. ubuntu-16.04使用MDK3伪造wifi热点和攻击wifi热点至死
  10. 关于 Be 主
  11. Unity3D动态生成多边形
  12. 在平衡树的海洋中畅游(四)——FHQ Treap
  13. WyBox使用shell脚本检测io口是否正常
  14. Ntfs 下的链接符号创建
  15. module &#39;pip&#39; has no attribute &#39;pep425tags&#39;
  16. Activity2.java
  17. 第一次Sprint冲刺结果评价
  18. [转载]未能从程序集“System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”中加载类型“System.Web.WebPages.DisplayModeProvider”
  19. [转载]在Windows下为PHP5.6安装redis扩展和memcached扩展
  20. 假回溯-uva140带宽

热门文章

  1. Castle中AdditionalInterfaces用法介绍
  2. Everything search syntax
  3. .NET Memory Profiler 查看内存使用情况
  4. PHP面向对象笔记
  5. rabbitMQ第五篇:Spring集成RabbitMQ
  6. Leetcode-2 Add Two Numbers
  7. Constraint3:check约束 和 null
  8. Web APi之HttpClient注意事项以及建议(四)
  9. win7系统下如何配置php-Apache-mysql环境
  10. EasyUI管理后台模板(附源码)