你的位置:首页 > ASP.net教程

[ASP.net教程]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源码

回到目录