【问题标题】:Clone or make a MailMessage Immutable in .NET / C#在 .NET / C# 中克隆或使 MailMessage 不可变
【发布时间】:2011-07-10 08:20:56
【问题描述】:

我正在编写一个小型库,其中我正在编写一些接口,这些接口接受一个 MailMessage 对象并使用一个发送方法将一个类返回给我,该方法抽象出 MailMessage 的发送方式。我可以控制将执行实际发送的类,但我无法控制实施策略类。我想防止任何实施策略类更改 MailMessage。如何使 MailMessage(及其包含的集合)不可变或创建它的克隆?我没有像在其他类上那样在 MailMessage 本身上看到 .Clone 方法。我是否必须新建一个新的 MailMessage 对象并对该新的 MailMessage 进行逐个属性的设置?

请注意,我主要是 Java 人员,并且正在帮助客户编写 C# 2.0 代码,因此对于此类事情,我对 C# / .NET 习语有点不熟悉。任何帮助表示赞赏。

【问题讨论】:

  • 可以序列化和反序列化对象吗?
  • System.Net.Mail.MailMessage 不能直接序列化,您需要实现 IXmlSerializable 接口。

标签: c# .net clone immutability system.net.mail


【解决方案1】:

我认为没有快速的解决方案。 MailMessage 是继承可变的,不是为克隆或序列化/反序列化而设计的。如果您需要确保没有人可以更改它,请不要缓存它,而是定义一个包含消息值副本的类,并在此实例之外创建新的 MailMessage 实例。

【讨论】:

    【解决方案2】:

    我知道这是一个老问题,但我最近不得不实施这个问题,所以这就是我所做的。 这是一个浅层克隆,虽然需要做更多的工作,但它可以变成一个深层克隆。

            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 为什么?内部集合的所有内容均通过引用复制。
    • 嗯,我同意内部集合是通过引用复制的,但是新集合是实例化的,所以我宁愿称它为混合克隆:)
    • @SamanGhadirian - 您的编辑看起来足够充实,您可能应该添加一个不同的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-28
    • 2020-06-26
    • 1970-01-01
    • 2012-12-24
    • 2012-11-02
    • 2011-05-03
    • 2018-05-15
    相关资源
    最近更新 更多