Dot-Net

如何序列化郵件消息?

  • May 5, 2015

使用 los foratter 序列化 mial 消息時,我得到以下資訊。

錯誤:Sys.WebForms.PageRequestManagerServerErrorException:序列化“System.Net.Mail.MailMessage”類型的值“System.Net.Mail.MailMessage”時出錯。

有沒有一種簡單的方法來序列化這個對象,還是我必須單獨序列化每個 fhte 屬性?

我知道這是一篇較舊的文章,但我也遇到了需要序列化 ​​MailAddress 類的問題,因此我創建了一個可序列化的版本。如果您可以使用自定義 MailAddress 類而不是 System.Net.Mail.MailAddress 類,這可能對您有用。

/// <summary>
/// Serializable implementation of <see cref="System.Net.Mail.MailAddress"/>.
/// </summary>
[Serializable]
public class MailAddress : System.Net.Mail.MailAddress, ISerializable
{
   // Keep reference to the display name encoding so we can serialize/deserialize the value
   private readonly Encoding _displayNameEncoding;

   public MailAddress(string address)
       : this(address, null, null)
   {
   }

   public MailAddress(string address, string displayName)
       : this(address, displayName, null)
   {
   }

   public MailAddress(string address, string displayName, Encoding displayNameEncoding)
       : base(address, displayName, displayNameEncoding)
   {
       // Keep reference to the supplied displayNameEncoding so we can serialize/deserialize this value
       _displayNameEncoding = displayNameEncoding ?? Encoding.GetEncoding("utf-8");
   }

   public void GetObjectData(SerializationInfo info, StreamingContext context)
   {
       info.AddValue("Address", base.Address);
       info.AddValue("DisplayName", base.DisplayName);
       info.AddValue("DisplayNameEncoding", _displayNameEncoding);
   }

   protected MailAddress(SerializationInfo info, StreamingContext context)
       : this(info.GetString("Address"), info.GetString("DisplayName"), (Encoding)info.GetValue("DisplayNameEncoding", typeof (Encoding)))
   {
   }
}

對於那些尋找如何將 MailMessage 序列化為由 Keyvan Nayyeri 編寫的 XML 的完整原始碼的人,這裡是他的 github 的連結:

https://github.com/keyvan/Gopi/blob/master/Gopi/Gopi/SerializableMailMessage.cs

以下是他的部落格存檔,現已失效:

http://web.archive.org/web/20131124074822/http://keyvan.io/how-to-serialize-a-mailmessage

以防上面的連結也可能失效,我在這裡重新發布他的部落格:

如何序列化郵件消息

.NET 中有兩個 MailMessage 類。第一個在 System.Web.Mail 命名空間中,在 .NET 2.0 及更高版本中已過時,第二個在 System.Net.Mail 中可用。我不關心過時的,所以我只展示如何序列化 System.Net.Mail.MailMessage 類的實例。

要序列化 ​​MailMessage 對象的屬性,您可以創建一個新類並為其創建一個 MailMessage 類型的屬性,以便將您的 MailMessage 嵌入到該類中。在這個新類中,您可以實現 IXmlSerializable 介面來手動序列化其 MailMessage。

序列化

序列化方面的工作就像實現 WriteXml 方法一樣簡單。下面的程式碼是我為此編寫的。

public void WriteXml(XmlWriter writer)
{
   if (this != null)
   {
       writer.WriteStartElement("MailMessage");
       writer.WriteAttributeString("Priority", Convert.ToInt16(this.Priority).ToString());
       writer.WriteAttributeString("IsBodyHtml", this.IsBodyHtml.ToString());

       // From
       writer.WriteStartElement("From");
       if (!string.IsNullOrEmpty(this.From.DisplayName))
           writer.WriteAttributeString("DisplayName", this.From.DisplayName);
       writer.WriteRaw(this.From.Address);
       writer.WriteEndElement();

       // To
       writer.WriteStartElement("To");
       writer.WriteStartElement("Addresses");
       foreach (MailAddress address in this.To)
       {
           writer.WriteStartElement("Address");
           if (!string.IsNullOrEmpty(address.DisplayName))
               writer.WriteAttributeString("DisplayName", address.DisplayName);
           writer.WriteRaw(address.Address);
           writer.WriteEndElement();
       }
       writer.WriteEndElement();
       writer.WriteEndElement();

       // CC
       if (this.CC.Count > 0)
       {
           writer.WriteStartElement("CC");
           writer.WriteStartElement("Addresses");
           foreach (MailAddress address in this.CC)
           {
               writer.WriteStartElement("Address");
               if (!string.IsNullOrEmpty(address.DisplayName))
                   writer.WriteAttributeString("DisplayName", address.DisplayName);
               writer.WriteRaw(address.Address);
               writer.WriteEndElement();
           }
           writer.WriteEndElement();
           writer.WriteEndElement();
       }

       // Bcc
       if (this.Bcc.Count > 0)
       {
           writer.WriteStartElement("Bcc");
           writer.WriteStartElement("Addresses");
           foreach (MailAddress address in this.Bcc)
           {
               writer.WriteStartElement("Address");
               if (!string.IsNullOrEmpty(address.DisplayName))
                   writer.WriteAttributeString("DisplayName", address.DisplayName);
               writer.WriteRaw(address.Address);
               writer.WriteEndElement();
           }
           writer.WriteEndElement();
           writer.WriteEndElement();
       }

       // Subject
       writer.WriteStartElement("Subject");
       writer.WriteRaw(this.Subject);
       writer.WriteEndElement();

       // Body
       writer.WriteStartElement("Body");
       writer.WriteCData(Body);
       writer.WriteEndElement();

       writer.WriteEndElement();
   }
}

按照相同的方法,您可以序列化其他屬性,如附件。下週我將發布新版本的 Gopi,其中包含序列化所有內容的更新程式碼,因此您可以稍等片刻獲得程式碼。

反序列化

public void ReadXml(XmlReader reader)
{
   XmlDocument xml = new XmlDocument();
   xml.Load(reader);

   // Properties
   XmlNode rootNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage");
   this.IsBodyHtml = Convert.ToBoolean(rootNode.Attributes["IsBodyHtml"].Value);
   this.Priority = (MailPriority)Convert.ToInt16(rootNode.Attributes["Priority"].Value);

   // From
   XmlNode fromNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/From");
   string fromDisplayName = string.Empty;
   if (fromNode.Attributes["DisplayName"] != null)
       fromDisplayName = fromNode.Attributes["DisplayName"].Value;
   MailAddress fromAddress = new MailAddress(fromNode.InnerText, fromDisplayName);
   this.From = fromAddress;

   // To
   XmlNode toNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/To/Addresses");
   foreach (XmlNode node in toNode.ChildNodes)
   {
       string toDisplayName = string.Empty;
       if (node.Attributes["DisplayName"] != null)
           toDisplayName = node.Attributes["DisplayName"].Value;
       MailAddress toAddress = new MailAddress(node.InnerText, toDisplayName);
       this.To.Add(toAddress);
   }

   // CC
   XmlNode ccNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/CC/Addresses");
   foreach (XmlNode node in ccNode.ChildNodes)
   {
       string ccDisplayName = string.Empty;
       if (node.Attributes["DisplayName"] != null)
           ccDisplayName = node.Attributes["DisplayName"].Value;
       MailAddress ccAddress = new MailAddress(node.InnerText, ccDisplayName);
       this.CC.Add(ccAddress);
   }

   // Bcc
   XmlNode bccNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/Bcc/Addresses");
   foreach (XmlNode node in bccNode.ChildNodes)
   {
       string bccDisplayName = string.Empty;
       if (node.Attributes["DisplayName"] != null)
           bccDisplayName = node.Attributes["DisplayName"].Value;
       MailAddress bccAddress = new MailAddress(node.InnerText, bccDisplayName);
       this.Bcc.Add(bccAddress);
   }

   // Subject
   XmlNode subjectNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/Subject");
   this.Subject = subjectNode.InnerText;

   // Body
   XmlNode bodyNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/Body");
   this.Body = bodyNode.InnerText;
}

上面的程式碼使用輔助方法來獲取不同部分的 XmlNode。

public XmlNode GetConfigSection(XmlDocument xml, string nodePath)
{
   return xml.SelectSingleNode(nodePath);
}

此程式碼是不言自明的,不需要任何註釋,但請注意,您需要更新類名的 XPath 表達式。當然,我可以使用反射來使這段程式碼更通用,但有時我是個壞人!

引用自:https://stackoverflow.com/questions/1122058