创建基于MailKit和MimeKit的.NET基础邮件服务

      邮件服务是一般的系统都会拥有和需要的功能,但是对于.NET项目来说,邮件服务的创建和使用会较为的麻烦。.NET对于邮件功能提供了System.Net.Mail用于创建邮件服务,该基础服务提供邮件的基础操作,并且使用也较为的简单。对于真正将该功能使用于项目的人,就会慢慢发现其中的优缺点,甚至有些时候不能忍受其中的问题。在这里介绍一种微软用于替代System.Net.Mail的邮件服务组件MailKit和MimeKit,官网地址:http://www.mimekit.net/。GitHub地址:https://github.com/jstedfast/MimeKit。下面就具体的介绍一下。

  一.MailKit和MimeKit基础概述:

       MailKit组件的支持的客户端类型比较多,例如SMTP客户端、POP3客户端、IMAP4客户端。该组件是一个跨平台的Email组件,该组件支持.NET 4.0,.NET 4.5,Xamarin.Android,Xamarin.iOS,Windows Phone 8.1等等平台。

     

      MimeKit提供了一个MIME解析器,组件具备的解析特性灵活、性能高、很好的处理各种各样的破碎的MIME格式化。MimeKit的性能实际上与GMime相当。

      该组件在安全性的还是比较高的,处理安全的方式较多,SASL认证、支持S / MIME v3.2、支持OpenPGP、支持DKIM签名等等方式。Mailkit组件可以通过CancellationToken取消对应的操作,CancellationToken传播应取消操作的通知,一个的CancellationToken使线程,线程池工作项目之间,或取消合作任务的对象。过实例化CancellationTokenSource对象来创建取消令牌,该对象管理从其CancellationTokenSource.Token属性检索的取消令牌。然后,将取消令牌传递到应该收到取消通知的任意数量的线程,任务或操作。令牌不能用于启动取消。

     MailKit组件支持异步操作,在内部编写的有关I/O异步操作的类。

  二.创建基础邮件服务:

           介绍过MailKit和MimeKit组建的基础信息,接下来就介绍一下如何使用两个组件的基本功能,在这里我将基本操作做了一个简单的封装,一般的项目可以直接引用封装好的类,大家可以根据实际的情况对该组件进行扩展。

          1.邮件发送基础服务API

/// <summary>

    /// 邮件服务API

    /// </summary>

    public static class MailServiceApi

    {

        /// <summary>

        /// 发送邮件

        /// </summary>

        /// <param name="mailBodyEntity">邮件基础信息</param>

        /// <param name="sendServerConfiguration">发件人基础信息</param>

        public static SendResultEntity SendMail(MailBodyEntity mailBodyEntity,

            SendServerConfigurationEntity sendServerConfiguration)

        {

            if (sendServerConfiguration == null)

            {

                throw new ArgumentNullException();

            }


            if (sendServerConfiguration == null)

            {

                throw new ArgumentNullException();

            }


            var sendResultEntity = new SendResultEntity();


            using (var client = new SmtpClient(new ProtocolLogger(CreateMailLog())))

            {

                client.ServerCertificateValidationCallback = (s, c, h, e) => true;


                Connection(mailBodyEntity, sendServerConfiguration, client, sendResultEntity);


                if (sendResultEntity.ResultStatus == false)

                {

                    return sendResultEntity;

                }


                SmtpClientBaseMessage(client);


                Authenticate(mailBodyEntity, sendServerConfiguration, client, sendResultEntity);


                if (sendResultEntity.ResultStatus == false)

                {

                    return sendResultEntity;

                }


                Send(mailBodyEntity, sendServerConfiguration, client, sendResultEntity);


                if (sendResultEntity.ResultStatus == false)

                {

                    return sendResultEntity;

                }


                client.Disconnect(true);

            }


            return sendResultEntity;

        }



        /// <summary>

        /// 连接服务器

        /// </summary>

        /// <param name="mailBodyEntity">邮件内容</param>

        /// <param name="sendServerConfiguration">发送配置</param>

        /// <param name="client">客户端对象</param>

        /// <param name="sendResultEntity">发送结果</param>

        public static void Connection(MailBodyEntity mailBodyEntity, SendServerConfigurationEntity sendServerConfiguration,

            SmtpClient client, SendResultEntity sendResultEntity)

        {

            try

            {

                client.Connect(sendServerConfiguration.SmtpHost, sendServerConfiguration.SmtpPort);

            }

            catch (SmtpCommandException ex)

            {

                sendResultEntity.ResultInformation = $"尝试连接时出错:{0}" + ex.Message;

                sendResultEntity.ResultStatus = false;

            }

            catch (SmtpProtocolException ex)

            {

                sendResultEntity.ResultInformation = $"尝试连接时的协议错误:{0}" + ex.Message;

                sendResultEntity.ResultStatus = false;

            }

            catch (Exception ex)

            {

                sendResultEntity.ResultInformation = $"服务器连接错误:{0}" + ex.Message;

                sendResultEntity.ResultStatus = false;

            }

        }


        /// <summary>

        /// 账户认证

        /// </summary>

        /// <param name="mailBodyEntity">邮件内容</param>

        /// <param name="sendServerConfiguration">发送配置</param>

        /// <param name="client">客户端对象</param>

        /// <param name="sendResultEntity">发送结果</param>

        public static void Authenticate(MailBodyEntity mailBodyEntity, SendServerConfigurationEntity sendServerConfiguration,

            SmtpClient client, SendResultEntity sendResultEntity)

        {

            try

            {

                client.Authenticate(sendServerConfiguration.SenderAccount, sendServerConfiguration.SenderPassword);

            }

            catch (AuthenticationException ex)

            {

                sendResultEntity.ResultInformation = $"无效的用户名或密码:{0}" + ex.Message;

                sendResultEntity.ResultStatus = false;

            }

            catch (SmtpCommandException ex)

            {

                sendResultEntity.ResultInformation = $"尝试验证错误:{0}" + ex.Message;

                sendResultEntity.ResultStatus = false;

            }

            catch (SmtpProtocolException ex)

            {

                sendResultEntity.ResultInformation = $"尝试验证时的协议错误:{0}" + ex.Message;

                sendResultEntity.ResultStatus = false;

            }

            catch (Exception ex)

            {

                sendResultEntity.ResultInformation = $"账户认证错误:{0}" + ex.Message;

                sendResultEntity.ResultStatus = false;

            }

        }


        /// <summary>

        /// 发送邮件

        /// </summary>

        /// <param name="mailBodyEntity">邮件内容</param>

        /// <param name="sendServerConfiguration">发送配置</param>

        /// <param name="client">客户端对象</param>

        /// <param name="sendResultEntity">发送结果</param>

        public static void Send(MailBodyEntity mailBodyEntity, SendServerConfigurationEntity sendServerConfiguration,

            SmtpClient client, SendResultEntity sendResultEntity)

        {

            try

            {

                client.Send(MailMessage.AssemblyMailMessage(mailBodyEntity));

            }

            catch (SmtpCommandException ex)

            {

                switch (ex.ErrorCode)

                {

                    case SmtpErrorCode.RecipientNotAccepted:

                        sendResultEntity.ResultInformation = $"收件人未被接受:{ex.Message}";

                        break;

                    case SmtpErrorCode.SenderNotAccepted:

                        sendResultEntity.ResultInformation = $"发件人未被接受:{ex.Message}";

                        break;

                    case SmtpErrorCode.MessageNotAccepted:

                        sendResultEntity.ResultInformation = $"消息未被接受:{ex.Message}";

                        break;

                }

                sendResultEntity.ResultStatus = false;

            }

            catch (SmtpProtocolException ex)

            {

                sendResultEntity.ResultInformation = $"发送消息时的协议错误:{ex.Message}";

                sendResultEntity.ResultStatus = false;

            }

            catch (Exception ex)

            {

                sendResultEntity.ResultInformation = $"邮件接收失败:{ex.Message}";

                sendResultEntity.ResultStatus = false;

            }

        }


        /// <summary>

        /// 获取SMTP基础信息

        /// </summary>

        /// <param name="client">客户端对象</param>

        /// <returns></returns>

        public static MailServerInformation SmtpClientBaseMessage(SmtpClient client)

        {

            var mailServerInformation = new MailServerInformation

            {

                Authentication = client.Capabilities.HasFlag(SmtpCapabilities.Authentication),

                BinaryMime = client.Capabilities.HasFlag(SmtpCapabilities.BinaryMime),

                Dsn = client.Capabilities.HasFlag(SmtpCapabilities.Dsn),

                EightBitMime = client.Capabilities.HasFlag(SmtpCapabilities.EightBitMime),

                Size = client.MaxSize

            };


            return mailServerInformation;

        }


        /// <summary>

        /// 创建邮件日志文件

        /// </summary>

        /// <returns></returns>

        public static string CreateMailLog()

        {

            var logPath = AppDomain.CurrentDomain.BaseDirectory + "/DocumentLog/" +

                Guid.NewGuid() + ".txt";


            if (File.Exists(logPath)) return logPath;

            var fs = File.Create(logPath);

            fs.Close();

            return logPath;

        }

    }

   2.组装邮件消息:

/// <summary>

    /// 邮件信息

    /// </summary>

    public static class MailMessage

    {

        /// <summary>

        /// 组装邮件文本/附件邮件信息

        /// </summary>

        /// <param name="mailBodyEntity">邮件消息实体</param>

        /// <returns></returns>

        public static MimeMessage AssemblyMailMessage(MailBodyEntity mailBodyEntity)

        {

            if (mailBodyEntity == null)

            {

                throw new ArgumentNullException(nameof(mailBodyEntity));

            }


            var message = new MimeMessage();


            //设置邮件基本信息

            SetMailBaseMessage(message, mailBodyEntity);


            var multipart = new Multipart("mixed");


            //插入文本消息

            if (string.IsNullOrEmpty(mailBodyEntity.MailTextBody) == false)

            {

                var alternative = new MultipartAlternative

                {

                    AssemblyMailTextMessage(mailBodyEntity.MailTextBody, mailBodyEntity.MailBodyType)

                 };


                multipart.Add(alternative);

            }


            //插入附件

            if (mailBodyEntity.MailFilePath != null && File.Exists(mailBodyEntity.MailFilePath) == false)

            {

                var mimePart = AssemblyMailAttachmentMessage(mailBodyEntity.MailFileType, mailBodyEntity.MailFileSubType,

                     mailBodyEntity.MailFilePath);


                multipart.Add(mimePart);

            }


            //组合邮件内容

            message.Body = multipart;


            return message;

        }


        /// <summary>

        /// 设置邮件基础信息

        /// </summary>

        /// <param name="minMessag"></param>

        /// <param name="mailBodyEntity"></param>

        /// <returns></returns>

        public static MimeMessage SetMailBaseMessage(MimeMessage minMessag, MailBodyEntity mailBodyEntity)

        {

            if (minMessag == null)

            {

                throw new ArgumentNullException();

            }


            if (mailBodyEntity == null)

            {

                throw new ArgumentNullException();

            }


            //插入发件人

            minMessag.From.Add(new MailboxAddress(mailBodyEntity.Sender, mailBodyEntity.SenderAddress));


            //插入收件人

            foreach (var recipients in mailBodyEntity.Recipients)

            {

                minMessag.To.Add(new MailboxAddress(recipients));

            }


            //插入抄送人

            foreach (var cC in mailBodyEntity.Cc)

            {

                minMessag.Cc.Add(new MailboxAddress(cC));

            }


            //插入主题

            minMessag.Subject = mailBodyEntity.Subject;


            return minMessag;

        }


        /// <summary>

        /// 组装邮件文本信息

        /// </summary>

        /// <param name="mailBody">邮件文本内容</param>

        /// <param name="textPartType">邮件文本类型(plain,html,rtf,xml)</param>

        /// <returns></returns>

        public static TextPart AssemblyMailTextMessage(string mailBody, string textPartType)

        {

            if (string.IsNullOrEmpty(mailBody))

            {

                throw new ArgumentNullException();

            }


            if (string.IsNullOrEmpty(textPartType))

            {

                throw new ArgumentNullException();

            }


            var textBody = new TextPart(textPartType)

            {

                Text = mailBody

            };


            return textBody;

        }


        /// <summary>

        /// 组装邮件附件信息

        /// </summary>

        /// <param name="fileAttachmentType">附件类型(image,application)</param>

        /// <param name="fileAttachmentSubType">附件子类型 </param>

        /// <param name="fileAttachmentPath">附件路径</param>

        /// <returns></returns>

        public static MimePart AssemblyMailAttachmentMessage(string fileAttachmentType, string fileAttachmentSubType, string fileAttachmentPath)

        {

            if (string.IsNullOrEmpty(fileAttachmentSubType))

            {

                throw new ArgumentNullException();

            }


            if (string.IsNullOrEmpty(fileAttachmentType))

            {

                throw new ArgumentNullException();

            }


            if (string.IsNullOrEmpty(fileAttachmentPath))

            {

                throw new ArgumentNullException();

            }


            var attachment = new MimePart(fileAttachmentType, fileAttachmentSubType)

            {

                Content = new MimeContent(File.OpenRead(fileAttachmentPath)),

                ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),

                ContentTransferEncoding = ContentEncoding.Base64,

                FileName = Path.GetFileName(fileAttachmentPath)

            };


            return attachment;

        }


    }

   3.邮件基础服务实体:

/// <summary>

    /// 邮件内容实体

    /// </summary>

    public class MailBodyEntity

    {

        /// <summary>

        /// 邮件文本内容

        /// </summary>

        public string MailTextBody { get; set; }


        /// <summary>

        /// 邮件内容类型

        /// </summary>

        public string MailBodyType { get; set; }


        /// <summary>

        /// 邮件附件文件类型

        /// </summary>

        public string MailFileType { get; set; }


        /// <summary>

        /// 邮件附件文件子类型

        /// </summary>

        public string MailFileSubType { get; set; }


        /// <summary>

        /// 邮件附件文件路径

        /// </summary>

        public string MailFilePath { get; set; }


        /// <summary>

        /// 收件人

        /// </summary>

        public List<string> Recipients { get; set; }


        /// <summary>

        /// 抄送

        /// </summary>

        public List<string> Cc { get; set; }


        /// <summary>

        /// 发件人

        /// </summary>

        public string Sender { get; set; }


        /// <summary>

        /// 发件人地址

        /// </summary>

        public string SenderAddress { get; set; }


        /// <summary>

        /// 邮件主题

        /// </summary>

        public string Subject { get; set; }


        /// <summary>

        /// 邮件内容

        /// </summary>

        public string Body { get; set; }

    }


    /// <summary>

    /// 邮件服务器基础信息

    /// </summary>

    public class MailServerInformation

    {

        /// <summary>

        /// SMTP服务器支持SASL机制类型

        /// </summary>

        public bool Authentication { get; set; }


        /// <summary>

        /// SMTP服务器对消息的大小

        /// </summary>

        public uint Size { get; set; }


        /// <summary>

        /// SMTP服务器支持传递状态通知

        /// </summary>

        public bool Dsn { get; set; }


        /// <summary>

        /// SMTP服务器支持Content-Transfer-Encoding

        /// </summary>

        public bool EightBitMime { get; set; }


        /// <summary>

        /// SMTP服务器支持Content-Transfer-Encoding

        /// </summary>

        public bool BinaryMime { get; set; }


        /// <summary>

        /// SMTP服务器在消息头中支持UTF-8

        /// </summary>

        public string UTF8 { get; set; }

    }


    /// <summary>

    /// 邮件发送结果

    /// </summary>

    public class SendResultEntity

    {

        /// <summary>

        /// 结果信息

        /// </summary>

        public string ResultInformation { get; set; } = "发送成功!";


        /// <summary>

        /// 结果状态

        /// </summary>

        public bool ResultStatus { get; set; } = true;

    }


    /// <summary>

    /// 邮件发送服务器配置

    /// </summary>

    public class SendServerConfigurationEntity

    {

        /// <summary>

        /// 邮箱SMTP服务器地址

        /// </summary>

        public string SmtpHost { get; set; }


        /// <summary>

        /// 邮箱SMTP服务器端口

        /// </summary>

        public int SmtpPort { get; set; }


        /// <summary>

        /// 是否启用IsSsl

        /// </summary>

        public bool IsSsl { get; set; }


        /// <summary>

        /// 邮件编码

        /// </summary>

        public string MailEncoding { get; set; }


        /// <summary>

        /// 发件人账号

        /// </summary>

        public string SenderAccount { get; set; }


        /// <summary>

        /// 发件人密码

        /// </summary>

        public string SenderPassword { get; set; }


    }

上面提供了借助MailKit组建创建发送邮件服务,分别是创建邮件服务器连接,组装邮件基础信息,邮件基础实体。发送邮件的基础服务比较的多,下面介绍一下邮件的接收。

/// <summary>

    /// 跟投邮件服务API

    /// </summary>

    public static class ReceiveEmailServiceApi

    {

        /// <summary>

        /// 设置发件人信息

        /// </summary>

        /// <returns></returns>

        public static SendServerConfigurationEntity SetSendMessage()

        {

            var sendServerConfiguration = new SendServerConfigurationEntity

            {

                SmtpHost = ConfigurationManager.AppSettings["SmtpServer"],

                SmtpPort = int.Parse(ConfigurationManager.AppSettings["SmtpPort"]),

                IsSsl = Convert.ToBoolean(ConfigurationManager.AppSettings["IsSsl"]),

                MailEncoding = ConfigurationManager.AppSettings["MailEncoding"],

                SenderAccount = ConfigurationManager.AppSettings["SenderAccount"],

                SenderPassword = ConfigurationManager.AppSettings["SenderPassword"]

            };

            return sendServerConfiguration;

        }



        /// <summary>

        /// 接收邮件

        /// </summary>

        public static void ReceiveEmail()

        {

            var sendServerConfiguration = SetSendMessage();


            if (sendServerConfiguration == null)

            {

                throw new ArgumentNullException();

            }


            using (var client = new ImapClient(new ProtocolLogger(CreateMailLog())))

            {

                client.Connect(sendServerConfiguration.SmtpHost, sendServerConfiguration.SmtpPort,

                    SecureSocketOptions.SslOnConnect);

                client.Authenticate(sendServerConfiguration.SenderAccount, sendServerConfiguration.SenderPassword);

                client.Inbox.Open(FolderAccess.ReadOnly);

                var uids = client.Inbox.Search(SearchQuery.All);

                foreach (var uid in uids)

                {

                    var message = client.Inbox.GetMessage(uid);

                    message.WriteTo($"{uid}.eml");

                }


                client.Disconnect(true);

            }

        }


        /// <summary>

        /// 下载邮件内容

        /// </summary>

        public static void DownloadBodyParts()

        {

            var sendServerConfiguration = SetSendMessage();


            using (var client = new ImapClient())

            {

                client.Connect(sendServerConfiguration.SmtpHost, sendServerConfiguration.SmtpPort,

                    SecureSocketOptions.SslOnConnect);

                client.Authenticate(sendServerConfiguration.SenderAccount, sendServerConfiguration.SenderPassword);

                client.Inbox.Open(FolderAccess.ReadOnly);


                // 搜索Subject标题包含“MimeKit”或“MailKit”的邮件

                var query = SearchQuery.SubjectContains("MimeKit").Or(SearchQuery.SubjectContains("MailKit"));

                var uids = client.Inbox.Search(query);


                // 获取搜索结果的摘要信息(我们需要UID和BODYSTRUCTURE每条消息,以便我们可以提取文本正文和附件)

                var items = client.Inbox.Fetch(uids, MessageSummaryItems.UniqueId | MessageSummaryItems.BodyStructure);


                foreach (var item in items)

                {

                    // 确定一个目录来保存内容

                    var directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "/MailBody", item.UniqueId.ToString());


                    Directory.CreateDirectory(directory);


                    // IMessageSummary.TextBody是一个便利的属性,可以为我们找到“文本/纯文本”的正文部分

                    var bodyPart = item.TextBody;


                    // 下载'text / plain'正文部分

                    var body = (TextPart) client.Inbox.GetBodyPart(item.UniqueId, bodyPart);


                    // TextPart.Text是一个便利的属性,它解码内容并将结果转换为我们的字符串

                    var text = body.Text;


                    File.WriteAllText(Path.Combine(directory, "body.txt"), text);


                    // 现在遍历所有附件并将其保存到磁盘

                    foreach (var attachment in item.Attachments)

                    {

                        // 像我们对内容所做的那样下载附件

                        var entity = client.Inbox.GetBodyPart(item.UniqueId, attachment);


                        // 附件可以是message / rfc822部件或常规MIME部件

                        var messagePart = entity as MessagePart;

                        if (messagePart != null)

                        {

                            var rfc822 = messagePart;


                            var path = Path.Combine(directory, attachment.PartSpecifier + ".eml");


                            rfc822.Message.WriteTo(path);

                        }

                        else

                        {

                            var part = (MimePart) entity;


                            // 注意:这可能是空的,但大多数会指定一个文件名

                            var fileName = part.FileName;


                            var path = Path.Combine(directory, fileName);


                            // decode and save the content to a file

                            using (var stream = File.Create(path))

                                part.Content.DecodeTo(stream);

                        }

                    }

                }


                client.Disconnect(true);

            }

        }


        /// <summary>

        /// 创建邮件日志文件

        /// </summary>

        /// <returns></returns>

        public static string CreateMailLog()

        {

            var logPath = AppDomain.CurrentDomain.BaseDirectory + "/DocumentLog/" +

                DateTime.Now.ToUniversalTime().ToString(CultureInfo.InvariantCulture) + ".txt";


            if (File.Exists(logPath)) return logPath;

            var fs = File.Create(logPath);

            fs.Close();

            return logPath;


        }

    }

面只是简单的介绍了邮件的接收,如果需要更加深入的了解功能,可以进一步对组件源码进行解析,该组件的文档为较为的丰富。

  三.组件使用感悟:

            MailKit和MimeKit组件在项目的使用中较为的便捷,基本包含了所有的基础邮件服务操作。组件提供的SmtpClient类提供的功能很丰富,例如连接邮件服务器,邮件账户认证,组装邮件消息,获取邮件服务器配置信息等等方法的提供,可以让我们在项目中快速的获取邮件服务的所有信息。

           使用过邮件功能的项目 都会有困扰,客户端与邮件服务器的连接是否成功,以及邮件是否发送成功状态没有办法很快的获取,只能根据邮件服务器返回的一场状态进行判断。但是MailKit提供对应的方法和异常类,对邮件服务器返回的异常信息进行解析,客户端可以根据这些异常类获取邮件状态。

           MailKit组件的提供了ProtocolLogger类,该类用于记录SMTP操作基础信息,该类作用为记录邮件服务日志。在邮件发送完毕后,需要及时的关闭连接,调用Disconnect(true)方法。

原文:https://www.cnblogs.com/pengze0902/p/8519715.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321979.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EF Core下利用Mysql进行数据存储在并发访问下的数据同步问题

小故事在开始讲这篇文章之前&#xff0c;我们来说一个小故事&#xff0c;纯素虚构&#xff08;真实的存钱逻辑并非如此&#xff09;小刘发工资后&#xff0c;赶忙拿着现金去银行&#xff0c;准备把钱存起来&#xff0c;而与此同时&#xff0c;小刘的老婆刘嫂知道小刘的品性&…

牛客练习赛50-记录

正题 比赛链接:https://ac.nowcoder.com/acm/contest/1080#question 成绩 本届 升高二届 总结 以后还是不要写太多自己不擅长的写法&#xff0c;空间要多检查&#xff0c;不要像个傻逼一样啥都写错。 尽量不要为了省一点空间和时间写一些不舒服的东西&#xff0c;尽量在能…

物联网框架ServerSuperIO在.NetCore实现跨平台的实践路线

正所谓天下大势&#xff0c;不跟风不行。你不跨平台&#xff0c;很low嘛。java说&#xff1a;你们能跨嘛&#xff0c;跨给我看看。C#说&#xff1a;不要强人所难嘛。java说&#xff1a;能部署在云上吗&#xff1f;docker&#xff1f;微服务&#xff1f;C#说&#xff1a;不要强人…

使用WebApiClient请求和管理Restful Api

前言本篇文章的内容是WebApiClient应用说明篇&#xff0c;如果你没有了解过WebApiClient&#xff0c;可以先阅读以下相关文章&#xff1a;WebApi client 的面向切面编程我来给.Net设计一款HttpClient.Net45下HttpClient的几个缺陷.net的retrofit--WebApiClient库.net的retrofit…

拥抱.NET Core系列:MemoryCache 缓存选项

MSCache项目MSCache 目前最新的正式版是 2.0.0&#xff0c;预览版是2.1.0&#xff0c;会与 .NETCore 2.1 一起发布。本篇用了2.0.0版本开源在 GitHub 上&#xff0c;仓库地址是&#xff1a;https://github.com/aspnet/CachingNuGet地址为&#xff1a;https://www.nuget.org/pac…

牛客练习赛51-记录

正题 比赛链接:https://ac.nowcoder.com/acm/contest/1083#question 成绩 可怜的zycT3zycT3zycT3被n0n0n0卡了半天&#xff0c;这里感谢一下排雷 总结 比赛状态较好&#xff0c;后面没有T6T6T6的题解 T1:abcT1:abcT1:abc 题目大意 给出一个字符串&#xff0c;求有多少个abc…

Metrics.net + influxdb + grafana 构建WebAPI的自动化监控和预警

前言这次主要分享通过Metrics.net influxdb grafana 构建WebAPI的自动化监控和预警方案。通过执行耗时&#xff0c;定位哪些接口拖累了服务的性能&#xff1b;通过请求频次&#xff0c;设置适当的限流和熔断机制&#xff0c;拦截非法或不合理的请求&#xff0c;保障服务的可用…

EF Core 2.1路线图:视图、GROUP BY和惰性加载

Entity Framework Core一直追随着初始Entity Framework的发展&#xff0c;并不断推陈出新。它首先推出的是对视图的支持&#xff0c;这听起来有些耸人听闻。在即将推出的EF Core 2.1之前&#xff0c;EF Core并未对数据库视图提供官方的支持&#xff0c;也不支持缺少主键的数据库…

计算机网络总结

一、计算机网络体系 &#xff08;1&#xff09;OSI分层 &#xff08;7层&#xff09; 物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。 &#xff08;2&#xff09;TCP/IP分层&#xff08;4层&#xff09; 网络接口层、 网际层、运输层、 应用层。 &#xff0…

从技术角度讨论微服务

本文希望从技术角度来探讨下微服务&#xff0c;因此&#xff0c;不会过多地谈及如何根据业务进行微服务划分&#xff0c;更多是介绍微服务的相关技术&#xff0c;微服务的业务划分方法可参考“领域驱动设计“相关方法论。微服务的两个程度一、服务化复杂的单体架构会有以下的挑…

jzoj6344-[NOIP2019模拟2019.9.7]Huge Counting【组合数,状压dp】

正题 题目大意 定义函数f(x)(xf(x)(xf(x)(x为一个序列))) 若任意一个xi1x_i1xi​1那么有f(x)1f(x)1f(x)1 若有一个xi0x_i0xi​0那么有f(x)0f(x)0f(x)0 其他的&#xff0c;有f(x)(∑j1nf(x1...,xj−1,...xn))%2f(x)(\sum_{j1}^nf(x_{1}...,x_j-1,...x_n))\% 2f(x)(j1∑n​f(x1​…

拥抱.NET Core系列:MemoryCache 缓存域

MSCache项目MSCache 目前最新的正式版是 2.0.0&#xff0c;预览版是2.1.0&#xff0c;会与 .NETCore 2.1 一起发布。本篇用了2.0.0版本开源在 GitHub 上&#xff0c;仓库地址是&#xff1a;https://github.com/aspnet/CachingNuGet地址为&#xff1a;https://www.nuget.org/pac…

牛客小白月赛17-记录(附题解)

正题 比赛链接:https://ac.nowcoder.com/acm/contest/1085#question 成绩 总结 除了那道积分数学其他还好 后面没有FFF题的题解 T1:小sun的假期T1:小sun的假期T1:小sun的假期 题目大意 长度为nnn的序列&#xff0c;mmm个区间&#xff0c;求最大的没有被任何区间覆盖的区间…

安全、高效的MySQL DDL解决方案

MySQL作为目前应用最广泛的开源关系型数据库&#xff0c;是许多网站、应用和商业产品的主要数据存储。在生产环境&#xff0c;线上数据库常常面临着持续的、不断变化的表结构修改&#xff08;DDL&#xff09;&#xff0c;如增加、更改、删除字段和索引等等。其中一些DDL操作在M…

DNS总结

一、DNS &#xff08;1&#xff09;简介 域名系统&#xff08;英文&#xff1a;Domain Name System&#xff0c;缩写&#xff1a;DNS&#xff09;是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便地访问互联网。 DNS 协议也是…

谈谈在.NET Core中使用Redis和Memcached的序列化问题

前言在使用分布式缓存的时候&#xff0c;都不可避免的要做这样一步操作&#xff0c;将数据序列化后再存储到缓存中去。序列化这一操作&#xff0c;或许是显式的&#xff0c;或许是隐式的&#xff0c;这个取决于使用的package是否有帮我们做这样一件事。本文会拿在.NET Core环境…

牛客练习赛52-记录

正题 比赛链接:https://ac.nowcoder.com/acm/contest/1084#question 成绩 T1:T1:T1:数数 题目大意 给出nnn&#xff0c;求∑i1n∑j1n(i∗j)\sum_{i1}^n \sum_{j1}^n (i*j)i1∑n​j1∑n​(i∗j) 和 ∏i1n∏j1n(i∗j)\prod_{i1}^n\prod_{j1}^n(i*j)i1∏n​j1∏n​(i∗j) 解题…

Windows Developer Day - Windows AI Platform

本次 Windows Developer Day&#xff0c;最值得期待的莫过于 Windows AI Platform 了&#xff0c;可以说是千呼万唤始出来。观看直播的开发者们&#xff0c;留言最多的也是 Windows AI Platform。下面结合微软提供的展示过程&#xff0c;文档和 Git Sample 来详细分析一下。基础…

EF Core:一统SQL和NoSQL数据库

推出EF Core的初衷之一&#xff0c;就是开发出一种可在很少甚至不更改代码的情况下使用SQL和NoSQL数据库的模型。Microsoft正向此目标迈出第一步&#xff0c;发布了用于Azure Cosmos DB的实验性EF提供程序&#xff08;provider&#xff09;。据EF 2.1路线图介绍&#xff1a;Cos…

Java 并发总结——进程与线程

一、进程与线程 &#xff08;1&#xff09;线程与进程 进程是程序在一个数据集合上运行的过程&#xff0c;它是系统进行资源分配和调度的一个独立单位。进程实体由程序段&#xff0c; 数据段 PCB&#xff08;进程控制块&#xff09;组成。 线程可以看做轻量级进程&#xff0c;…