如何将C#邮件模型映射为MS Graph API所需的不同结构列表
问题
我有一个用于绑定JSON邮件数据的模型,包含发件人、收件人、抄送、密送等字段,结构如下:
public class Email { public string From { get; set; } public IEnumerable<Contact> To { get; set; } public IEnumerable<Contact> Cc { get; set; } public IEnumerable<Contact> Bcc { get; set; } public string Subject { get; set; } public string Body { get; set; } public List<IFormFile> FileAttachments { get; set; } } public class Contact { public string EmailAddress { get; set; } }
但使用MS Graph API发送邮件时,需要转换为完全不同的列表结构,示例如下:
var message = new Message { ToRecipients = new List<Recipient> { new Recipient { EmailAddress = new EmailAddress { Address = "email@email.com", Name = "Joen Doe", }, }, new Recipient { EmailAddress = new EmailAddress { Address = "email2@email.com", Name = "Jane Dane", }, }, } };
请问如何动态将模型中的列表映射为该结构?我需要对抄送和密送采用相同的处理方式,但无法在初始化括号内嵌套foreach循环,是否需要先创建列表再赋值?
解决方案
1. 直接用LINQ转换(无需提前创建列表)
可以利用LINQ的Select方法直接将Contact集合转换为MS Graph要求的Recipient集合,无需手动循环创建列表,能直接在对象初始化器中使用:
var message = new Message { Subject = email.Subject, // MS Graph的Body是ItemBody类型,需将字符串转换为对应结构 Body = new ItemBody { Content = email.Body, ContentType = BodyType.Text // 或BodyType.Html,根据需求选择 }, // 转换收件人列表 ToRecipients = email.To?.Select(contact => new Recipient { EmailAddress = new EmailAddress { Address = contact.EmailAddress } }).ToList(), // 转换抄送列表 CcRecipients = email.Cc?.Select(contact => new Recipient { EmailAddress = new EmailAddress { Address = contact.EmailAddress } }).ToList(), // 转换密送列表 BccRecipients = email.Bcc?.Select(contact => new Recipient { EmailAddress = new EmailAddress { Address = contact.EmailAddress } }).ToList(), // 转换发件人(MS Graph的From为Recipient类型) From = string.IsNullOrEmpty(email.From) ? null : new Recipient { EmailAddress = new EmailAddress { Address = email.From } } };
注:使用
?.空传播运算符避免email.To/Cc/Bcc为null时出现空引用异常,转换后的结果通过ToList()转为List<Recipient>,符合MS Graph的类型要求。
2. 封装复用方法(避免重复代码)
因为收件人、抄送、密送的转换逻辑完全一致,封装通用方法可复用代码,让结构更清晰:
// 封装转换逻辑 private List<Recipient> MapContactsToRecipients(IEnumerable<Contact> contacts) { // 若contacts为null,返回空列表而非null,避免后续调用异常 return contacts?.Select(contact => new Recipient { EmailAddress = new EmailAddress { Address = contact.EmailAddress } }).ToList() ?? new List<Recipient>(); } // 使用示例 var message = new Message { Subject = email.Subject, Body = new ItemBody { Content = email.Body, ContentType = BodyType.Text }, ToRecipients = MapContactsToRecipients(email.To), CcRecipients = MapContactsToRecipients(email.Cc), BccRecipients = MapContactsToRecipients(email.Bcc), From = string.IsNullOrEmpty(email.From) ? null : new Recipient { EmailAddress = new EmailAddress { Address = email.From } } };
3. 附件的补充转换(可选)
如果需要处理模型中的FileAttachments,可以用类似方式转换为MS Graph的FileAttachment集合:
// 同步版本 message.Attachments = email.FileAttachments?.Select(file => { using var stream = file.OpenReadStream(); var contentBytes = new byte[stream.Length]; stream.Read(contentBytes, 0, (int)stream.Length); return new FileAttachment { Name = file.FileName, ContentBytes = contentBytes, ContentType = file.ContentType }; }).ToList(); // 异步版本(若在异步方法中使用) message.Attachments = await Task.WhenAll(email.FileAttachments?.Select(async file => { using var stream = file.OpenReadStream(); var contentBytes = new byte[stream.Length]; await stream.ReadAsync(contentBytes, 0, (int)stream.Length); return new FileAttachment { Name = file.FileName, ContentBytes = contentBytes, ContentType = file.ContentType }) ?? Enumerable.Empty<Task<FileAttachment>>());
内容的提问来源于stack exchange,提问作者Qiuzman
相关产品推荐
相关产品推荐

