在.NET/C#中克隆或使MailMessage成为不可变对象

3
我正在编写一个小型库,其中我编写了一些接口,这些接口接受一个MailMessage对象,并向我返回一个类,该类具有一个抽象的send方法,用于隐藏MailMessage将如何发送的细节。我可以控制执行实际发送的类,但无法控制实现策略类。我想防止任何实现策略类更改MailMessage。我该如何使MailMessage(及其包含的集合)成为不可变的或创建其副本?我在MailMessage本身上没有看到像其他类一样的.Clone方法。我是否需要新建一个MailMessage对象并对该新MailMessage进行逐个属性设置?请注意,我主要是Java开发人员,正在帮助客户处理C#2.0代码,因此对于此类事情的C#/ .NET习语略感陌生。非常感谢您的帮助。

你能对对象进行序列化和反序列化吗? - CodingBarfield
1
System.Net.Mail.MailMessage 无法直接序列化,您需要实现 IXmlSerializable 接口。 - DaveRead
2个回答

2

我认为这个问题没有快速解决方案。 MailMessage 是可变的,不能被克隆或序列化/反序列化。如果您需要确保没有人可以更改它,请不要将其缓存,而是定义一个类来保存消息的值的副本,并从该实例创建新的 MailMessage 实例。


1
我知道这是一个老问题,但最近我不得不实现它,下面是我的做法。虽然这是一个浅拷贝,但通过一些额外的工作可以将其转换为深拷贝。
        private MailMessage MailMessageShallowCopy(MailMessage original)
    {
        string to = original.To.ToString();
        string from = original.From.ToString();
        string subject = original.Subject;
        string body = original.Body;
        string cc = original.CC.ToString();
        string bcc = original.Bcc.ToString();

        MailMessage clone = new MailMessage(from, to, subject, body);
        if (!string.IsNullOrEmpty(cc))
        {
            clone.CC.Add(cc);
        }
        if (!string.IsNullOrEmpty(bcc))
        {
            clone.Bcc.Add(bcc);
        }
        foreach (AlternateView view in original.AlternateViews)
        {
            var clonedView = new AlternateView(view.ContentStream);
            foreach (var resource in view.LinkedResources)
            {
                clonedView.LinkedResources.Add(resource);
            }
            clone.AlternateViews.Add(clonedView);
        }
        foreach (Attachment attachment in original.Attachments)
        {
            clone.Attachments.Add(attachment);
        }
        clone.BodyEncoding = original.BodyEncoding;
        clone.DeliveryNotificationOptions = original.DeliveryNotificationOptions;
        foreach (NameValueCollection header in original.Headers)
        {
            clone.Headers.Add(header);
        }
        clone.HeadersEncoding = original.HeadersEncoding;
        clone.IsBodyHtml = original.IsBodyHtml;
        clone.Priority = original.Priority;
        foreach (MailAddress mailAddress in original.ReplyToList)
        {
            clone.ReplyToList.Add(mailAddress);
        }
        clone.Sender = original.Sender;
        clone.SubjectEncoding = original.SubjectEncoding;
        return clone;
    }

这不是浅复制代码,而是深度复制代码。 - dnk.nitro
1
@dnk.nitro 为什么?所有内部集合的内容都是通过引用复制的。 - M. Mimpen
我同意内部集合是通过引用复制的,但新的集合是实例化的,所以我更愿意称其为混合克隆 :) - dnk.nitro
@SamanGhadirian - 您的编辑似乎很实质性,您可能应该添加一个不同的答案。 - dbc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接