我有一个 Windows 服务,它使用 Entity Framework 5 从数据库中的队列中读取电子邮件,然后使用 System.Net.Mail.SmtpClient 将它们发送到 SMTP 服务器
这是我第一次尝试编写 F# 应用程序,我来自 C# 背景。如何改进它以提供更多功能和/或更充分地利用 F# 的特性?你能解释一下做出这些改变有什么好处吗?
worker 由服务宿主构建,服务启动时调用它的工作函数,服务停止时将 ContinueWorking 设置为 false。
namespace EmailService
open log4net
open System
open System.Linq
open System.Net.Mail
open EmailService.Context
type Worker(contextFactory: EmailContextFactory, mailClient: ISmtpClient, logger: ILog) =
let MapToMessage(email : Email) =
let message = new MailMessage()
message.Sender <- new MailAddress(email.From)
message.From <- new MailAddress(email.From)
message.Subject <- email.Subject
message.Body <- email.Body
message.IsBodyHtml <- email.IsBodyHtml
message.To.Add(email.To)
(email, message)
member val ContinueWorking = true with get, set
member this.Work() =
logger.Info "Starting work"
let mutable unsentEmails = Array.empty<Email>
while this.ContinueWorking do
use context = contextFactory.GetEntities()
while this.ContinueWorking && Array.isEmpty unsentEmails do
System.Threading.Thread.Sleep(1000)
unsentEmails <- query { for q in context.QueueItems do
where (q.Error = null)
select q.Email }
|> query.Take(10)
|> query.toArray
Array.map MapToMessage unsentEmails
|> Array.iter (fun (email, message) ->
try
mailClient.SendMail(message)
email.DateSent <- new Nullable<DateTime>(DateTime.UtcNow)
context.QueueItems.Remove(email.QueueItem) |> ignore
with
| ex ->
logger.Error(ex)
email.QueueItem.Error <- ex.ToString())
context.SaveChanges() |> ignore
logger.Info (sprintf "Sent %d emails" unsentEmails.Length)
logger.Info "Work complete"