<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Donetframework on DoDoRo的梦想空间-码农,数学,算法,哲学,园艺</title>
    <link>https://dodoro.chouxiangpai.com/categories/donetframework/</link>
    <description>Recent content in Donetframework on DoDoRo的梦想空间-码农,数学,算法,哲学,园艺</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Tue, 25 Mar 2025 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://dodoro.chouxiangpai.com/categories/donetframework/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>回顾我和编程之缘</title>
      <link>https://dodoro.chouxiangpai.com/archives/2089/</link>
      <pubDate>Tue, 25 Mar 2025 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/2089/</guid>
      <description>&lt;p&gt;回顾自己十六年来的编程经历，我很乐意分享我和计算机编程结缘的过程。&lt;/p&gt;
&lt;p&gt;高中毕业的时候，我从邻居家借到一本Basic语言的书籍，我被它迷住了，那时候我没有计算机，只是在草稿纸上模仿书本上的例子进行四则运算和解方程运算。事实上我从小梦想是做一名数学家，所以我大学专业是数学与应用数学。那时候计算机在中国是热门专业，所以数学系也开了很多计算机的课程，我认真学了一个学期的C语言程序设计，我一直被计算机编程的能力震撼，那时候我知道Matlab和Mathematica可以调用C语言的类库进行非常复杂的数值运行，我在大学参加数学建模比赛就是用计算机算法去验证数学模型。&lt;/p&gt;
&lt;p&gt;大二的时候我第一次接触Delphi，第一次接触Pascal语言，被它的简洁语法吸引，不过Delphi那时候已经走下坡路，微软的MFC已经蚕食它的市场份额，而Delphi的创始人安德斯海尔斯伯格也被比尔盖茨挖到微软。大二结束的时候我参加学校编程社团，第一次学习C#并且使用ASP.NET WebForm开发网站，从同学那里，我也了解C#的创始人海尔斯伯格的传奇经历，我被两者深刻吸引。&lt;/p&gt;
&lt;p&gt;大学毕业的时候我很幸运加入一家有名的软件公司方正集团，我继续使用C#和.NET开发网站，那时候我独立开发了一个CMS系统，虽然很简单但是非常实用，后来我深入参与电子报纸和电子图书的算法设计和软件开发。移动互联网刚刚诞生的时候，我和另外一位工程师基于Mac版本的FBReader开发了ios版本的图书阅读器，那时候我第一次接触object-c。&lt;/p&gt;
&lt;p&gt;我也喜欢linux，自己会安装linux操作系统来学习，所以我在工作之余自学了php语言，但是我更喜欢C#这门语言，所以我一直没有转移到其他开发语言。微软和我Windows的闭源一直是我心疼之痛，后来我接触开源Mono，这是.NET在linux的一个实现，但是Mono的重点在桌面和游戏开发。&lt;/p&gt;
&lt;p&gt;我加入百度公司之后有机会在linux生态系统下进行软件开发，我们使用php语言和mysql，这段经历扩宽了我的技术视野，让我对编程语言有了更深刻的理解：语言大同小异，最核心的还是算法和数据结构，以为优秀的开发人员应该能同时使用多种编程语言。&lt;/p&gt;
&lt;p&gt;离开百度之后，我加入一家初创企业，我负责组建团队并开发互联网产品和软件，选择公司技术栈的时候我面临在php和c#之间二选一。那时候.NET已经开源，Mono的作者也创立了新公司Xamarin，专注于使用C#开发跨平台的移动应用。加上结合公司的情况，我继续选择使用C#作为主开发语言，但是我们也使用mysql、memcached和Redis等技术。我们的第一个移动应用也用C#来开发，那时候是属于很前卫的选择，还好我们坚持了下来，因为到了2016年微软换CTO了，开始拥抱开源，紧接着是收购Xamarin，还有筹划.NET Core的开发。我一直关注.NET Core的进展，后来看到StackOverflow使用.NET Core2.1，他们极大提升了性能，于是我开始在我们的新开发产品中使用.NET Core，到了.NET Core3.1的时候开始将legacy code迁移到.NET Core。&lt;/p&gt;
&lt;p&gt;这里不得不提一段我学习深度学习的插曲，2018年左右我认真学习了Michael A. Nielsen的《神经网络与深度学习》，并熟读第二章的多元微积分公式和证明，我甚至在纸上推导了全过程，这是我再次接触神经网络算法（大学数学建模的时候我学习过）。我似乎又回到了大学学习数学分析的时候，这本书写得非常好，作者从最根本最朴素的思想开始，结合实践进入深度神经网络，我认为这本书堪称神经网络的几何原本。我没有继续深入到深度学习中去，但是我认为它最根本的核心还在这本书里。也许哪一天，我还会重新捡回这段技术经历。&lt;/p&gt;</description>
    </item>
    <item>
      <title>委托和接口的选择</title>
      <link>https://dodoro.chouxiangpai.com/archives/2087/</link>
      <pubDate>Wed, 05 Mar 2025 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/2087/</guid>
      <description>&lt;p&gt;A delegate design might be a better choice than an interface design if one or more of these conditions are true: • The interface defines only a single method. • Multicast capability is needed. • The subscriber needs to implement the interface multiple times.&lt;/p&gt;
&lt;p&gt;如果满足以下一个或多个条件，委托设计可能比接口设计更好： • 接口仅定义一个方法。 • 需要多播功能。 • 订阅者需要多次实现该接口。&lt;/p&gt;</description>
    </item>
    <item>
      <title>部署NextJS到Azure WebApp Deployment Error报错: cannot find module ../server/require-hook</title>
      <link>https://dodoro.chouxiangpai.com/archives/2079/</link>
      <pubDate>Thu, 27 Feb 2025 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/2079/</guid>
      <description>&lt;p&gt;当我将nextjs应用程序部署到azure web应用程序的时候报错：cannot find module ../server/require-hook。&lt;/p&gt;
&lt;p&gt;我通过github-actions构建和部署成功完成，但是部署后，我在url 中收到错误，并且在azure日志流利发现这个错误。刚刚开始我不明白是什么原因造成的，因为“npm start”在我的本地机器上使用相同的 npm 版本构建和运行。&lt;/p&gt;
&lt;p&gt;通过网上查找，发现是因为githhb的action默认不会把.next文件夹打包加入zip并且发布到azure。所以需要在默认的工作流基础上修改：&lt;/p&gt;
&lt;p&gt;1、adding &amp;ldquo;startAzure&amp;rdquo;: &amp;ldquo;./node_modules/next/dist/bin/next start&amp;rdquo; in package.json; 还需要在azure应用程序网站的配置立加上 the startup command of the azure web app like &amp;ldquo;npm run startAzure&amp;rdquo;&lt;/p&gt;
&lt;p&gt;2、添加这个到azure的 pipeline (在创建 zip了之后)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- name: Zip artifact &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; deployment run: zip release.zip ./* -r
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- name: Add .next folder to zip artifact &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; deployment run: zip -r release.zip &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;.next&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    <item>
      <title>MiniProfiler工具介绍</title>
      <link>https://dodoro.chouxiangpai.com/archives/2051/</link>
      <pubDate>Wed, 26 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/2051/</guid>
      <description>&lt;p&gt;在日常开发中，应用程序的性能是我们需要关注的一个重点问题。当然我们有很多工具来分析程序性能：如：Zipkin等；但这些过于复杂，需要单独搭建。&lt;/p&gt;
&lt;p&gt;MiniProfiler就是一款简单，但功能强大的应用新能分析工具；可以帮助我们定位：SQL性能问题、响应慢等问题。&lt;/p&gt;
&lt;p&gt;MiniProfiler是一款针对.NET, Ruby, Go and Node.js的性能分析的轻量级程序。可以对一个页面本身，及该页面通过直接引用、Ajax、Iframe形式访问的其它页面进行监控,监控内容包括数据库内容，并可以显示数据库访问的SQL（支持EF、EF CodeFirst等 ）。并且以很友好的方式展现在页面上。&lt;/p&gt;
&lt;p&gt;MiniProfiler官网：&lt;a href=&#34;http://miniprofiler.com/&#34;&gt;http://miniprofiler.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;MiniProfiler的一个特别有用的功能是它与数据库框架的集成。除了.NET原生的 DbConnection类，MiniProfiler还内置了对实体框架（Entity Framework）以及LINQ to SQL、RavenDb和MongoDB的支持。任何执行的Step都会包括当时查询的次数和所花费的时间。为了检测常见的错误，如N+1反模式，profiler将检测仅有参数值存在差异的多个查询。&lt;/p&gt;</description>
    </item>
    <item>
      <title>数据访问策略： Dapper和Entity Framework混合应用</title>
      <link>https://dodoro.chouxiangpai.com/archives/2049/</link>
      <pubDate>Tue, 25 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/2049/</guid>
      <description>&lt;p&gt;作者 Julie Lerman&lt;/p&gt;
&lt;p&gt;你大概注意到了，自 2008 年以来，我写过许多关于 Entity Framework（即 Microsoft 对象关系映射器 (ORM)）的文章，ORM 一直是主要的 .NET 数据访问 API。市面上还有许多其他 .NET ORM，但是有一个特殊类别因其强大的性能得到的关注最高，那就是微型 ORM。我听人提到最多的微型 ORM 是 Dapper。据不同的开发者说，他们使用 EF 和 Dapper 制定了混合解决方案，让每个 ORM 能够在单个应用程序中做它最擅长的事，这最终激发了我的兴趣，促使我在最近抽出时间来一探究竟。&lt;/p&gt;
&lt;p&gt;在阅读大量文章和博客文章，与开发者聊过天并熟悉过 Dapper 后，我想与大家分享我的一些发现，尤其是和像我这样，可能听说过 Dapper 但并不知道它是什么或者并不知道它的工作原理的人分享，同时说说人们为什么这么喜欢它。需要提醒你的是，我根本不是什么专家。目前我只是为了满足我的好奇心而变得足够了解，并且希望激发你的兴趣，从而进一步探索。&lt;/p&gt;
&lt;p&gt;为什么是 Dapper？ Dapper 的历史十分有趣，它是从你可能再熟悉不过的资源中衍生的： Marc Gravell 和 Sam Saffron 在研究 Stack Overflow，解决此平台的性能问题时构建了 Dapper。考虑到 Stack Overflow 是一个流量极高的站点，那么必然存在性能上的问题。根据 Stack Exchange About 网页，在 2015 年，Stack Overflow 拥有 57 亿的网页浏览量。在 2011 年，Saffron 撰写过一篇关于他和 Gravell 所做的工作的博客文章，名为“我如何学会不再担忧和编写我自己的 ORM”(bit.ly/)，这篇文章介绍了 Stack 当时存在的性能问题，该问题源于 LINQ to SQL 的使用。他在文中详细介绍了为什么编写自定义 ORM，其中 Dapper 就是优化 Stack Overflow 上的数据访问的答案。五年后的今天，Dapper 已被广泛使用并已成为开源软件。Gravell 和 Stack 及团队成员 Nick Craver 继续在 github.com/StackExchange/dapper-dot-net 上积极地管理项目。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Entity Framework Core：一对多关系</title>
      <link>https://dodoro.chouxiangpai.com/archives/2047/</link>
      <pubDate>Sun, 23 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/2047/</guid>
      <description>&lt;p&gt;当一个实体类型的任意数量的实体与相同或另一个实体类型的任意数量的实体相关联时，将使用多对多关系。 例如，Post 可以有多个关联的 Tags，并且每个 Tag 可以与任意数量的 Posts 关联。&lt;/p&gt;
&lt;p&gt;了解多对多关系 多对多关系不同于一对多和一对一关系，因为它们不能仅使用外键以简单方式表示。 相反，需要其他实体类型来“联接”关系的两端。 这称为“联接实体类型”，并映射到关系数据库中的“联接表”。 此联接实体类型的实体包含外键值对，其中一对指向关系一端的实体，另一对指向关系另一端的实体。 因此，每个联接实体以及联接表中的每一行都表示关系中实体类型之间的一个关联。&lt;/p&gt;
&lt;p&gt;EF Core 可以隐藏联接实体类型并在后台对其进行管理。 这允许以自然方式使用多对多关系的导航，从而根据需要在每一端添加或删除实体。 但是，了解后台发生的情况非常有用，以便其整体行为（尤其是映射关系数据库）有意义。 让我们从关系数据库架构设置开始，以表示帖子和标记之间的多对多关系：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CREATE TABLE &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Posts&amp;#34;&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Id&amp;#34;&lt;/span&gt; INTEGER NOT NULL CONSTRAINT &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PK_Posts&amp;#34;&lt;/span&gt; PRIMARY KEY AUTOINCREMENT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CREATE TABLE &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Tags&amp;#34;&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Id&amp;#34;&lt;/span&gt; INTEGER NOT NULL CONSTRAINT &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PK_Tags&amp;#34;&lt;/span&gt; PRIMARY KEY AUTOINCREMENT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CREATE TABLE &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PostTag&amp;#34;&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PostsId&amp;#34;&lt;/span&gt; INTEGER NOT NULL,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TagsId&amp;#34;&lt;/span&gt; INTEGER NOT NULL,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CONSTRAINT &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PK_PostTag&amp;#34;&lt;/span&gt; PRIMARY KEY (&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PostsId&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TagsId&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CONSTRAINT &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;FK_PostTag_Posts_PostsId&amp;#34;&lt;/span&gt; FOREIGN KEY (&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PostsId&amp;#34;&lt;/span&gt;) REFERENCES &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Posts&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Id&amp;#34;&lt;/span&gt;) ON DELETE CASCADE,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CONSTRAINT &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;FK_PostTag_Tags_TagsId&amp;#34;&lt;/span&gt; FOREIGN KEY (&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TagsId&amp;#34;&lt;/span&gt;) REFERENCES &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Tags&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Id&amp;#34;&lt;/span&gt;) ON DELETE CASCADE);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在此架构中，PostTag 是联接表。 它包含两列：PostsId（指向 Posts 表的主键的外键）和 TagsId（指向 Tags 表的主键的外键）。 因此，此表中的每一行都表示一个 Post 和一个 Tag 之间的关联。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Entity Framework Core：一对多关系</title>
      <link>https://dodoro.chouxiangpai.com/archives/2042/</link>
      <pubDate>Fri, 21 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/2042/</guid>
      <description>&lt;p&gt;当单个实体与任意数量的其他实体关联时，将使用一对多关系。 例如，Blog 可以有多个关联的 Posts，但每个 Post 都只与一个 Blog 相关联。&lt;/p&gt;
&lt;p&gt;本文档采用围绕大量示例展开的结构。 这些示例从常见情况着手，还引入了一些概念。 后面的示例介绍了不太常见的配置类型。 此处介绍了一个不错的方法，即了解前几个示例和概念，再根据特定需求转到后面的示例。 基于此方法，我们将从简单的“必需”和“可选”的一对多关系开始。&lt;/p&gt;
&lt;p&gt;提示&lt;/p&gt;
&lt;p&gt;可在 OneToMany.cs 中找到以下所有示例的代码。&lt;/p&gt;
&lt;p&gt;必需的一对多&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Principal (parent)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Blog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; Id { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; ICollection&amp;lt;Post&amp;gt; Posts { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; } = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;Post&amp;gt;(); &lt;span style=&#34;color:#75715e&#34;&gt;// Collection navigation containing dependents&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Dependent (child)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Post&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; Id { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; BlogId { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; } &lt;span style=&#34;color:#75715e&#34;&gt;// Required foreign key property&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Blog Blog { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; } = &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;!; &lt;span style=&#34;color:#75715e&#34;&gt;// Required reference navigation to principal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一对多关系由以下部分组成：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Entity Framework Core：一对一关系</title>
      <link>https://dodoro.chouxiangpai.com/archives/2040/</link>
      <pubDate>Thu, 20 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/2040/</guid>
      <description>&lt;p&gt;当一个实体与最多一个其他实体关联时，将使用一对一关系。 例如，Blog 有一个 BlogHeader，并且 BlogHeader 属于单个 Blog。&lt;/p&gt;
&lt;p&gt;本文档采用围绕大量示例展开的结构。 这些示例从常见情况着手，还引入了一些概念。 后面的示例介绍了不太常见的配置类型。 此处介绍了一个不错的方法，即了解前几个示例和概念，再根据特定需求转到后面的示例。 基于此方法，我们将从简单的“必需”和“可选”的一对一关系开始。&lt;/p&gt;
&lt;p&gt;可在 OneToOne.cs 中找到以下所有示例的代码。&lt;/p&gt;
&lt;p&gt;必需的一对一&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Principal (parent)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Blog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; Id { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; BlogHeader? Header { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; } &lt;span style=&#34;color:#75715e&#34;&gt;// Reference navigation to dependent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Dependent (child)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BlogHeader&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; Id { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; BlogId { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; } &lt;span style=&#34;color:#75715e&#34;&gt;// Required foreign key property&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Blog Blog { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; } = &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;!; &lt;span style=&#34;color:#75715e&#34;&gt;// Required reference navigation to principal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一对一关系由以下部分组成：&lt;/p&gt;
&lt;p&gt;主体实体上的一个或多个主键或备用键属性。 例如 Blog.Id。 依赖实体上的一个或多个外键属性。 例如 BlogHeader.BlogId。 （可选）引用依赖实体的主体实体上的引用导航。 例如 Blog.Header。 （可选）引用主体实体的依赖实体上的引用导航。 例如，BlogHeader.Blog。 提示&lt;/p&gt;</description>
    </item>
    <item>
      <title>Blazor server VS Blazor WebAssembly</title>
      <link>https://dodoro.chouxiangpai.com/archives/2029/</link>
      <pubDate>Wed, 12 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/2029/</guid>
      <description>&lt;p&gt;Blazor WebAssembly 主要的 Blazor 托管模型在 WebAssembly 上的浏览器中运行客户端。 将 Blazor 应用、其依赖项以及 .NET 运行时下载到浏览器。 应用将在浏览器线程中直接执行。 UI 更新和事件处理在同一进程中进行。 应用资产作为静态文件部署到可为客户端提供静态内容的 Web 服务器或服务中。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;file&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/2029/images/image-1718171979210.png&#34;&gt; Blazor WebAssembly:Blazor 应用在浏览器内部的 UI 线程上运行。&lt;/p&gt;
&lt;p&gt;如果创建了 Blazor WebAssembly 应用进行部署，但没有后端 ASP.NET Core 应用来为其文件提供服务，那么该应用被称为独立 Blazor WebAssembly 应用。 如果创建了应用进行部署，但没有后端应用来为其文件提供服务，那么该应用被称为托管的 Blazor WebAssembly 应用。 托管的 Blazor WebAssembly Client 应用通常使用 Web API 调用或 SignalR（结合使用 ASP.NET Core SignalR 和 Blazor）通过网络与后端 Server 应用交互。&lt;/p&gt;
&lt;p&gt;blazor.webassembly.js 脚本由框架和句柄提供：&lt;/p&gt;
&lt;p&gt;下载 .NET 运行时、应用和应用依赖项。 初始化运行应用的运行时。 Blazor WebAssembly 托管模型具有以下优点：&lt;/p&gt;
&lt;p&gt;没有 .NET 服务器端依赖项。 应用下载到客户端后即可正常运行。 可充分利用客户端资源和功能。 工作可从服务器转移到客户端。 无需 ASP.NET Core Web 服务器即可托管应用。 无服务器部署方案可行，例如通过内容分发网络 (CDN) 为应用提供服务的方案。 Blazor WebAssembly 托管模型具有以下局限性：&lt;/p&gt;</description>
    </item>
    <item>
      <title>结合使用 ASP.NET Core SignalR 和 Blazor</title>
      <link>https://dodoro.chouxiangpai.com/archives/2033/</link>
      <pubDate>Wed, 12 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/2033/</guid>
      <description>&lt;p&gt;本教程提供了使用 SignalR 和 Blazor 生成实时应用的基本工作经验。 本文适用于已经熟悉 SignalR 并正在寻求了解如何在 SignalR 应用中使用 Blazor 的开发人员。 有关 SignalR 和 Blazor 框架的详细指南，请参阅以下参考文档集和 API 文档：&lt;/p&gt;
&lt;p&gt;ASP.NET Core SignalR 概述 ASP.NET Core Blazor .NET API 浏览器 了解如何：&lt;/p&gt;
&lt;p&gt;创建 Blazor 应用 添加 SignalR 客户端库 添加 SignalR 集线器 添加 SignalR 服务和 SignalR 中心的终结点 添加用于聊天的 Razor 组件代码 在本教程结束时，你将拥有一个正常运行的聊天应用。&lt;/p&gt;
&lt;p&gt;先决条件 Visual Studio Visual Studio Code .NET CLI 具有“ASP.NET 和 Web 开发”工作负载的 Visual Studio 2022 或更高版本&lt;/p&gt;
&lt;p&gt;示例应用 本教程不需要下载教程的示例聊天应用。 示例应用是按照本教程的步骤生成的最终工作应用。&lt;/p&gt;
&lt;p&gt;查看或下载示例代码（如何下载）&lt;/p&gt;
&lt;p&gt;创建 Blazor Web 应用 按照所选工具的指南进行操作：&lt;/p&gt;</description>
    </item>
    <item>
      <title>EF Add-Migration总结</title>
      <link>https://dodoro.chouxiangpai.com/archives/2016/</link>
      <pubDate>Sat, 08 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/2016/</guid>
      <description>&lt;p&gt;EF CodeFirst对数据库任何的操作，千万不要手工去修改。&lt;/p&gt;
&lt;p&gt;解释：add-migration命令是code first migration中的关键命令之一。当您对领域域模型进行更改并需要将它们时添加到数据库中，您将创建一个新的迁移。这是通过Add-Migration命令完成的。用最简单的形式，你只需要提供迁移名称&lt;/p&gt;
&lt;p&gt;展现形式：命令将您的更改构建到一个cs文件中。这个cs文件与配置文件放在同一个文件夹中，服务于您要瞄准的DbContext&lt;/p&gt;
&lt;p&gt;1.常用的命令：&lt;/p&gt;
&lt;p&gt;Add-Migration 、 Update-DataBase 、 Script-Migration&lt;/p&gt;
&lt;p&gt;(1)vs的程序包管理控制台输入 get-help Add-Migration -detailed以查看详细信息&lt;/p&gt;
&lt;p&gt;Add-Migration [-Name] ：指定自定义脚本 的名字 [-Force] [-ProjectName ] ：如果要重新构建现有迁移，必须使用-Force参数。然而，只有在迁移尚未应用到数据库时，才能重新构建框架。否则你 需要回复到要重新构建的迁移之前的迁移 [-StartUpProjectName ] ：是从 解决方案资源管理器中选择一个项目 作为启动项目。如果我们忽略的话，就会默认为解决方案资源管理器中的启动项目。 [-ConfigurationTypeName ] ：项目中有多个DbContext，那么您需要指出哪个数据库会更新。这可以用-ConfigurationTypeName做。ConfigurationTypeName方法是迁移文件夹中配置类的名称。 [-ConnectionStringName ] ：从应用程序的配置文件中指定要使用的连接字符串的名字。我们用两个参数-ConnectionString -ConnectionProviderName ，或者用这样一个参数代替 [-IgnoreChanges] ：假设目标数据库模式与当前的模型是一致的。构建一个空迁移和对应的空的迁移文件，忽略在当前模型中检测到的任何挂起的更改。可用于创建初始的空迁移，以支持对现有数据库的迁移。 [-AppDomainBaseDirectory ]：指定用于运行数据迁移代码的app-domain的路径，从而app-domain 可以找到所有需要的程序集。这是一个高级选项，只有当解决方案包含多个项目时才会需要。这样的话，context和configuration所需要的程序集就不仅仅从那些包含context和包含migrations的项目中获取 CommonParameters&lt;/p&gt;
&lt;p&gt;Add-Migration （你的迁移文件名称）&lt;/p&gt;
&lt;p&gt;若在一个项目里，操作多个DbConext的方法则需要指定context名称&lt;/p&gt;
&lt;p&gt;add-migration 迁移名称 -c ConfigurationDbContext&lt;/p&gt;
&lt;p&gt;update-database -c ConfigurationDbContext&lt;/p&gt;</description>
    </item>
    <item>
      <title>[转]MediatR知多少</title>
      <link>https://dodoro.chouxiangpai.com/archives/1999/</link>
      <pubDate>Wed, 05 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1999/</guid>
      <description>&lt;p&gt;原文：&lt;a href=&#34;https://www.cnblogs.com/sheng-jie/p/10280336.html&#34;&gt;https://www.cnblogs.com/sheng-jie/p/10280336.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;引言 首先不用查字典了，词典查无此词。猜测是作者笔误将Mediator写成MediatR了。废话少说，转入正题。&lt;/p&gt;
&lt;p&gt;先来简单了解下这个开源项目MediatR（作者Jimmy Bogard，也是开源项目AutoMapper的创建者，在此表示膜拜）：&lt;/p&gt;
&lt;p&gt;Simple mediator implementation in .NET. In-process messaging with no dependencies. Supports request/response, commands, queries, notifications and events, synchronous and async with intelligent dispatching via C# generic variance. .NET中的简单中介者模式实现，一种进程内消息传递机制（无其他外部依赖）。 支持以同步或异步的形式进行请求/响应，命令，查询，通知和事件的消息传递，并通过C#泛型支持消息的智能调度。&lt;/p&gt;
&lt;p&gt;如上所述，其核心是一个中介者模式的.NET实现，其目的是消息发送和消息处理的解耦。它支持以单播和多播形式使用同步或异步的模式来发布消息，创建和侦听事件。&lt;/p&gt;
&lt;p&gt;中介者模式既然是对中介者模式的一种实现，那么我们就有必要简要介绍下中介者这个设计模式，以便后续展开。 &lt;img alt=&#34;file&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1999/images/image-1717599447834.png&#34;&gt; 中介者模式类图 中介者模式：用一个中介对象封装一系列的对象交互，中介者使各对象不需要显示地相互作用，从而使耦合松散，而且可以独立地改变它们之间的交互。&lt;/p&gt;
&lt;p&gt;看上面的官方定义可能还是有点绕，那么下面这张图应该能帮助你对中介者模式有个直观了解。 &lt;img alt=&#34;file&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1999/images/image-1717599471125.png&#34;&gt; 使用中介模式，对象之间的交互将封装在中介对象中。对象不再直接相互交互（解耦），而是通过中介进行交互。这减少了对象之间的依赖性，从而减少了耦合。&lt;/p&gt;
&lt;p&gt;那其优缺点也在图中很容易看出：&lt;/p&gt;
&lt;p&gt;优点：中介者模式的优点就是减少类间的依赖，把原有的一对多的依赖变成了一对一的依赖，同事类只依赖中介者，减少了依赖，当然同时也降低了类间的耦合 缺点：中介者模式的缺点就是中介者会膨胀得很大，而且逻辑复杂，原本N个对象直接的相互依赖关系转换为中介者和同事类的依赖关系，同事类越多，中介者的逻辑就越复杂。&lt;/p&gt;
&lt;p&gt;Hello MeidatR 在开始之前，我们先来了解下其基本用法。&lt;/p&gt;
&lt;p&gt;单播消息传输 单播消息传输，也就是一对一的消息传递，一个消息对应一个消息处理。其通过IRequest来抽象单播消息，用IRequestHandler进行消息处理。&lt;/p&gt;
&lt;p&gt;//构建 消息请求 public class Ping : IRequest { } //构建 消息处理 public class PingHandler : IRequestHandler&amp;lt;Ping, string&amp;gt; { public Task Handle(Ping request, CancellationToken cancellationToken) { return Task.FromResult(&amp;ldquo;Pong&amp;rdquo;); } } //发送 请求 var response = await mediator.Send(new Ping()); Debug.WriteLine(response); // &amp;ldquo;Pong&amp;rdquo;&lt;/p&gt;</description>
    </item>
    <item>
      <title>MediatR Official Document</title>
      <link>https://dodoro.chouxiangpai.com/archives/2010/</link>
      <pubDate>Wed, 05 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/2010/</guid>
      <description>&lt;p&gt;&lt;strong&gt;MediatR&lt;/strong&gt; is a low-ambition library trying to solve a simple problem — decoupling the in-process sending of messages from handling messages. Cross-platform, supporting &lt;code&gt;netstandard2.0&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;setup&#34;&gt;Setup&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;#setup&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Install the package via NuGet first: &lt;code&gt;Install-Package MediatR&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;MediatR directly references &lt;code&gt;Microsoft.Extensions.DependencyInjection.Abstractions&lt;/code&gt; leveraging &lt;code&gt;IServiceProvider&lt;/code&gt;. Typical usage is to use &lt;code&gt;IServiceCollection&lt;/code&gt; directly:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;services.AddMediatR(cfg =&amp;gt; {
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This method registers the known MediatR types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;IMediator&lt;/code&gt; as transient&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ISender&lt;/code&gt; as transient&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IPublisher&lt;/code&gt; as transient&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For each assembly registered, the &lt;code&gt;AddMediatR&lt;/code&gt; method will scan those assemblies for MediatR types (excluding behaviors):&lt;/p&gt;</description>
    </item>
    <item>
      <title>MSBuild介绍</title>
      <link>https://dodoro.chouxiangpai.com/archives/1983/</link>
      <pubDate>Tue, 04 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1983/</guid>
      <description>&lt;p&gt;Microsoft 生成引擎是一个用于生成应用程序的平台。 此引擎（也称为 MSBuild）为项目文件提供了一个 XML 架构，用于控制生成平台处理和生成软件的方式。 Visual Studio 会使用 MSBuild，但 MSBuild 不依赖于 Visual Studio。 通过在项目或解决方案文件中调用 msbuild.exe 或 dotnet build，可以在未安装 Visual Studio 的环境中安排和生成产品。&lt;/p&gt;
&lt;p&gt;Visual Studio 使用 MSBuild 来加载和生成托管项目。 Visual Studio 中的项目文件（.csproj、.vbproj、vcxproj 等）包含 MSBuild XML 代码，当你使用 IDE 来生成项目时，此代码就会运行。 Visual Studio 项目会导入所有必要的设置和生成过程来执行典型的开发工作，但你可以从 Visual Studio 内或通过使用 XML 编辑器对其进行扩展或修改。&lt;/p&gt;
&lt;p&gt;若要在没有 Visual Studio 的 Windows 系统上安装 MSBuild，请转到下载页面上的 Visual Studio 生成工具。 通过此方法安装 MSBuild 可获得 MSBuild.exe。&lt;/p&gt;
&lt;p&gt;对于 .NET Core 和 .NET 5 或更高版本，获取 MSBuild 等效项的另一种方法是安装 .NET SDK。 .NET 生成命令 dotnet build 可与 macOS、Windows 或 Linux 上的 .NET SDK 一起使用。 .NET 生成命令 dotnet build 是 .NET Core 版本 MSBuild.exe 的精简包装器。 可以使用 .NET Core 命令行接口 (CLI)（使用 MSBuild）来生成面向 .NET Core 和 .NET 5 及更高版本的项目。&lt;/p&gt;</description>
    </item>
    <item>
      <title>NSwag 和 ASP.NET Core 入门</title>
      <link>https://dodoro.chouxiangpai.com/archives/1981/</link>
      <pubDate>Tue, 04 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1981/</guid>
      <description>&lt;p&gt;NSwag 提供了下列功能：&lt;/p&gt;
&lt;p&gt;能够使用 Swagger UI 和 Swagger 生成器。 灵活的代码生成功能。 借助 NSwag，无需使用现有 API。也就是说，可使用包含 Swagger 的第三方 API，并生成客户端实现。 使用 NSwag，可以加快开发周期，并轻松适应 API 更改。&lt;/p&gt;
&lt;p&gt;包安装 将 NSwag 安装到：&lt;/p&gt;
&lt;p&gt;生成已实现的 Web API 的 Swagger 规范。 为 Swagger UI 提供服务以浏览和测试 Web API。 为 Redoc 提供服务，以为 Web API 添加 API 文档。 若要使用 NSwag ASP.NET Core 中间件，请安装 NSwag.AspNetCore NuGet 包。 此包内的中间件可用于生成并提供Swagger 规范、Swagger UI（v2 和 v3）和 ReDoc UI。 NSwag 14 仅支持 v3 版的 Swagger UI 规范。&lt;/p&gt;
&lt;p&gt;若要安装 NSwag NuGet 包，请使用以下方法之一：&lt;/p&gt;</description>
    </item>
    <item>
      <title>NSwag.MSBuild使用</title>
      <link>https://dodoro.chouxiangpai.com/archives/1985/</link>
      <pubDate>Tue, 04 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1985/</guid>
      <description>&lt;p&gt;Package: NSwag.MSBuild&lt;/p&gt;
&lt;p&gt;Important for .NET Core: Assembly loading#net-core&lt;/p&gt;
&lt;p&gt;After installing the NSwag.MSBuild NuGet package in your project, you can use the variable $(NSwagExe) in your .csproj file to run the NSwag command line tool in an MSBuild target. This way the tools can easily be updated via NuGet. The /controller parameter can be omitted to generate a Swagger specification for all controllers.&lt;/p&gt;
&lt;p&gt;For better testability and stable output (defaults may change), it is recommended to create an NSwag Configuration Document (e.g. with NSwagStudio) and use:&lt;/p&gt;</description>
    </item>
    <item>
      <title>关于MSBuild和NSwag的深入学习</title>
      <link>https://dodoro.chouxiangpai.com/archives/1990/</link>
      <pubDate>Tue, 04 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1990/</guid>
      <description>&lt;p&gt;这段时间学习一个整洁架构的开源项目，这是一名澳大利亚的软件架构师在github上面分享的项目：&lt;a href=&#34;https://github.com/jasontaylordev/CleanArchitecture&#34;&gt;https://github.com/jasontaylordev/CleanArchitecture&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;作者的架构根底扎实，而且能灵活运用各种最新最简洁的技术知识，这个项目就用到非常多，我把代码pull下来之后发现直接编译过程中出了不少错误，花了两天时间都解决了。其中很大一部分是关于前端项目的内容，作者直接使用MSBuild来完成打包和创建，这只是我第一次看到。&lt;/p&gt;
&lt;p&gt;另外还通过NSwag.MSBuild完成Open API代码的生成和typescript代码生成（运用于Angular），其中一个让我很惊讶的是：他居然在项目编译的时候初始化了数据库，弄得我云里雾里。我修改连接字符串，从报错信息才知道是执行这部分脚本的时候，MSWage的内核里初始化了Core的项目，调用到了初始化数据库代码：&lt;/p&gt;
&lt;p&gt;Executing file &amp;lsquo;config.nswag&amp;rsquo; with variables &amp;lsquo;Configuration=Debug&amp;rsquo;&amp;hellip; C:\Users\csuma.nuget\packages\nswag.msbuild\14.0.7\tools\Net80&lt;/p&gt;
&lt;p&gt;下面是报错信息：&lt;/p&gt;
&lt;p&gt;Error NSwag command line tool for .NET Core Net80, toolchain v14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0));Visit &lt;a href=&#34;http://NSwag.org&#34;&gt;http://NSwag.org&lt;/a&gt; for more information.;NSwag bin directory: C:\Users\csuma.nuget\packages\nswag.msbuild\14.0.7\tools\Net80;Executing file &amp;lsquo;config.nswag&amp;rsquo; with variables &amp;lsquo;Configuration=Debug&amp;rsquo;&amp;hellip;;Launcher directory: C:\Users\csuma.nuget\packages\nswag.msbuild\14.0.7\tools\Net80;fail: CleanArchitecture.Infrastructure.Data.ApplicationDbContextInitialiser[0];An error occurred while initialising the database.;Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.&amp;lt;&amp;gt;c&lt;strong&gt;DisplayClass20_0.&amp;lt;b&lt;/strong&gt;0&amp;gt;d.MoveNext();&amp;mdash; End of stack trace from previous location &amp;mdash;;at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.&amp;lt;&amp;gt;c&lt;strong&gt;DisplayClass20_0.&amp;lt;b&lt;/strong&gt;0&amp;gt;d.MoveNext();&amp;mdash; End of stack trace from previous location &amp;mdash;;at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func&lt;code&gt;4 operation, Func&lt;/code&gt;4 verifySucceeded, CancellationToken cancellationToken);at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.ExistsAsync(CancellationToken cancellationToken);at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.MigrateAsync(String targetMigration, CancellationToken cancellationToken);at CleanArchitecture.Infrastructure.Data.ApplicationDbContextInitialiser.InitialiseAsync() in D:\project\CleanArchitecture\CleanArchitecture-main\CleanArchitecture-main\src\Infrastructure\Data\ApplicationDbContextInitialiser.cs:line 46;at CleanArchitecture.Infrastructure.Data.InitialiserExtensions.InitialiseDatabaseAsync(WebApplication app) in D:\project\CleanArchitecture\CleanArchitecture-main\CleanArchitecture-main\src\Infrastructure\Data\ApplicationDbContextInitialiser.cs:line 21;at Program.&lt;/p&gt;</description>
    </item>
    <item>
      <title>命令行执行NSwag</title>
      <link>https://dodoro.chouxiangpai.com/archives/1987/</link>
      <pubDate>Tue, 04 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1987/</guid>
      <description>&lt;p&gt;Important for .NET Core: Assembly loading#net-core&lt;/p&gt;
&lt;p&gt;To use the command line tool nswag.exe (.NET 4.6+) / dotnet-nswag.dll (.NET Core), choose one of the following methods:&lt;/p&gt;
&lt;p&gt;NSwag NPM Module: Bindings for the .NET 4.6+ and .NET Core command line tools (depending on installed framework/OS platform) Download latest NSwagStudio MSI installer or install package NSwagStudio via Chocolatey: After installing the application, the path to the nswag.exe binary is registered in the PATH variable so that the tool can be used in the Windows command line. Download the latest command line tools: Extract the ZIP archive and use the nswag.exe binary in the Windows command line. NSwag.MSBuild NuGet package To see all available commands and parameters, run the command line application &amp;ldquo;nswag.exe&amp;rdquo; without parameters and enter &amp;ldquo;help&amp;rdquo; as command. All &amp;ldquo;input&amp;rdquo; parameters accept file paths, URLs and JSON data.&lt;/p&gt;</description>
    </item>
    <item>
      <title>使用Visual Studio 2022 中的 .http 文件， ASP.NET Core API快速测试</title>
      <link>https://dodoro.chouxiangpai.com/archives/1977/</link>
      <pubDate>Sat, 01 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1977/</guid>
      <description>&lt;p&gt;Visual Studio 2022.http 文件编辑器提供了一种便捷的方式来测试 ASP.NET Core项目，尤其是 API 应用。 编辑器提供一个 UI，用于：&lt;/p&gt;
&lt;p&gt;创建和更新 .http 文件。 发送 .http 文件中指定的 HTTP 请求。 显示响应。 本文包含以下文档：&lt;/p&gt;
&lt;p&gt;.http 文件语法。 如何创建 .http 文件。 如何从 .http 文件发送请求。 在何处查找可配置的 .http 文件选项。 如何使用 Visual Studio 2022 终结点资源管理器在 .http 文件中创建请求。 .http 文件格式和编辑器受 Visual Studio Code REST 客户端扩展的启发。 Visual Studio 2022 .http 编辑器将 .rest 识别为相同文件格式的替代文件扩展名。&lt;/p&gt;
&lt;p&gt;先决条件 安装了“ASP.NET 和 Web 部署”工作负载的 Visual Studio 2022 版本 17.8 或更高版本。 .http 文件语法 以下部分介绍 .http 文件语法。&lt;/p&gt;
&lt;p&gt;请求 HTTP 请求的格式为 HTTPMethod URL HTTPVersion，全部在一行上，其中：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Orchard Core 中文文档</title>
      <link>https://dodoro.chouxiangpai.com/archives/1945/</link>
      <pubDate>Fri, 10 May 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1945/</guid>
      <description>&lt;p&gt;Orchard Core 是基于 Orchard CMS 使用 ASP.NET Core 重新构建的。&lt;/p&gt;
&lt;p&gt;Orchard Core 由两个不同的目标组成:&lt;/p&gt;
&lt;p&gt;Orchard Core Framework: 一个应用程序框架，用于构建模块化、多租户 的ASP.NET Core应用程序。 Orchard Core CMS: 一个建立在Orchard Core Framework之上的网络内容管理系统（CMS)。&lt;/p&gt;
&lt;p&gt;需要注意框架和 CMS 之间的差异非常重要。一些想要开发 SaaS 应用程序的开发人员只会对模块化框架感兴趣。其他想要构建可管理网站的用户将专注于 CMS 并构建模块来增强其网站或整个生态系统。&lt;/p&gt;
&lt;p&gt;Building Software as a Service (SaaS) solutions with the Orchard Core Framework&lt;/p&gt;
&lt;p&gt;了解Orchard Core Framework是独立于nuget.org上的CMS分发的，这一点非常重要。我们在 &lt;a href=&#34;https://github.com/OrchardCMS/OrchardCore.Samples&#34;&gt;https://github.com/OrchardCMS/OrchardCore.Samples&lt;/a&gt; 提供了一些示例程序，它将指导您如何仅使用Orchard Core Framework来构建模块化 和 多租户 的应用程序，而无需任何 CMS 特定功能。&lt;/p&gt;
&lt;p&gt;我们的目标之一是启用托管应用程序的基于社区的生态系统，这些生态系统可以通过模块（如电子商务系统、博客引擎等）进行扩展。Orchard Core Framework支持模块化环境，允许不同的团队处理应用程序的不同部分，并使组件跨项目可重用。&lt;/p&gt;
&lt;p&gt;B站演示视频：&lt;a href=&#34;https://www.bilibili.com/video/BV17T4y177fW/&#34;&gt;https://www.bilibili.com/video/BV17T4y177fW/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;使用Orchard Core CMS 构建网站&lt;/p&gt;
&lt;p&gt;Orchard Core CMS 是基于Orchard CMS 使用ASP.NET Core 重写的。它不仅仅是一个端口，因为我们希望大幅提高性能，并尽可能与的ASP.NET Core 的开发模型一致。&lt;/p&gt;</description>
    </item>
    <item>
      <title>OrchardCore实现模块化核心原理分析</title>
      <link>https://dodoro.chouxiangpai.com/archives/1947/</link>
      <pubDate>Wed, 10 Jan 2024 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1947/</guid>
      <description>&lt;p&gt;若改造项目，也因历史遗留问题，数据库表设计也可能存在不合理，此时从头开始再搭建如此庞大的架子，感觉会有点虚空，同时也要考虑团队内部情况，不是那么容易上手，反而可能会违背初心，花更多时间和精力在各种模型理解上&lt;/p&gt;
&lt;p&gt;我们完全可以为后续做铺垫，先搭建出底层基本设施，再基于此做灵活扩展即可，每个公司项目具体情况都不一样，比如仓储模式可能需要结合项目进行对应 改造，仓储只是提供了一种基本思想，若真将网上普遍流传的模式照搬可能并不是那么好用，可能会认为仓储莫不是一种反模式&lt;/p&gt;
&lt;p&gt;.NET Core模块化插件&lt;/p&gt;
&lt;p&gt;.NET Core内置提供了AssemblyLoadContext加载dll插件方式实现模块化，然后将其进行注册&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;        var mvcBuilder = services.AddMvc();
        foreach (var module in modules)
        {
            // Register controller from modules
            mvcBuilder.AddApplicationPart(module.Assembly);
        }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这种方式虽可行，在我看来只能作为一种临时解决方案并不利于长期，因为需额外创建一个新的项目，然后加载所生成dll，由于没有底层设施做支撑，所以极易引起版本不一致问题，而且手动被迫性质太强，实现模块化方案最终的目标则只需关注业务逻辑实现，我们来看看OrchardCore如何实现模块化。&lt;/p&gt;
&lt;p&gt;OrchardCore模块化思想&lt;/p&gt;
&lt;p&gt;这里我们并不讨论和ABP vNext二者谁更强大，没有任何意义，比如需结合现有项目情况、项目大小、是否为多租户、实施难度等等多方面考虑才能得出基本结论，而不是一味追求当前主流&lt;/p&gt;
&lt;p&gt;比如我们只是想实现模块化方案，建议选择OrchardCore来实施，因为很简单，我们可将其剥离为我所用，而后结合项目情况是否考虑利用ABP vNext来进行分层处理。借鉴核心思想、才能保证一切可在控制范围内&lt;/p&gt;
&lt;p&gt;首先我们先从整体上对OrchardCore做个认识，细枝末节暂不考虑：基于ASP.NET Core多租户模块化应用框架。&lt;/p&gt;
&lt;p&gt;版本管理：无论是底层设施、基本框架、模块都通过包管理，同时框架和包版本基本（包管理走框架包版本）可以统一管理（对于版本升级很重要）&lt;/p&gt;
&lt;p&gt;核心思想：模块实现模块特性，通过MSBuild构建主程序所添加实现模块特性的模块包，底层设施扫描模块特性将其注册到容器中，当然模块和模块特性都可进行基本信息描述&lt;/p&gt;
&lt;p&gt;OrchardCore模块化原理&lt;/p&gt;
&lt;p&gt;整个项目架构如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;file&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1947/images/image-1717047673501.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;OrchardCore：底层设施以及可能需要添加的组件（比如本地化、日志、文件存储、缓存、Lucene等）&lt;/p&gt;
&lt;p&gt;OrchardCore.Frameworks：MVC框架&lt;/p&gt;
&lt;p&gt;OrchardCore.Modules：模块化包（比如邮件服务、后台作业服务、第三方集成等等）&lt;/p&gt;
&lt;p&gt;OrchardCore.Modules.Cms：Cms模块包&lt;/p&gt;
&lt;p&gt;OrchardCore.Themes：主题管理&lt;/p&gt;
&lt;p&gt;OrchardCore.Cms.Web：主程序&lt;/p&gt;
&lt;p&gt;我以内置所提供示例程序给大家讲解整个详细流程，而后有需要更细致了解的童鞋就可以很快上手了，如下示例主程序加载示例模块，主程序直接采用引用该示例模块（实际则是通过nuget下载该模块）&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;file&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1947/images/image-1717047710410.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;正常情况下我们通过nuget直接下载的是程序包，而OrchardCore对于入口则是利用MSBuild加载targets文件（其他组件则直接下载对应包），而targets引用对应包，通过这种中转方式根据我的理解主要解决了两个问题，其一则是可以屏蔽底层设施包（一次性下载），最重要的是通过targets文件可自动添加主程序程序集所加载模块包特性&lt;/p&gt;
&lt;p&gt;是不是感觉有点懵，那到底是如何加载模块包特性的呢？来，请看如下图，我们以实际操作从头再来做一个完整梳理（注意：为排版美观，如下都将省略OrchardCore前缀）&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;file&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1947/images/image-1717047738808.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;【1】创建Mvc.Web程序，在nuget上下载Application.Mvc.Targets包&lt;/p&gt;
&lt;p&gt;【2】创建Mvc.HelloWorld模块，在nuget上下载引用Module.Targets包&lt;/p&gt;
&lt;p&gt;【3】Mvc.Web主程序引用我们所使用的Mvc.HelloWorld模块&lt;/p&gt;
&lt;p&gt;【4】Application.Mvc.Targets包引用Application.Targets（引入底层设施）和MVC.Core（引入MVC框架）&lt;/p&gt;
&lt;p&gt;【5】示例模块引入模块包，该包中存在模块特性（Module类）&lt;/p&gt;
&lt;p&gt;【6】Application.Targets包下存在Application.Targets.targets文件，由于主程序引用了该包，添加所引用实现模块特性的包程序集信息到主程序集&lt;/p&gt;
&lt;p&gt;到这里我们已经研究完主程序如何识别模块包，接下来则是如何加载模块包以及对应注册服务信息&lt;/p&gt;
&lt;p&gt;OrcharCore核心在于OrchardCore和OrchardCore.Abstractions这两个底层设施包&lt;/p&gt;
&lt;p&gt;归根到底，其底层设施源码一部分可能从官方源码拷贝过来（自我猜测），为实现多租户模式，势必要构建租户的容器和路由中间件，这中间就涉及在容器中需要维护每一个租户上下文（ShellContext），并且也要跟踪每个租户的状态。&lt;/p&gt;
&lt;p&gt;ModularTenantContainerMiddleware作为创建租户容器中间件&lt;/p&gt;
&lt;p&gt;ModularTenantRouterMiddleware作为租户路由中间件&lt;/p&gt;</description>
    </item>
    <item>
      <title>OrchardCore入门指南：创建Orchard Core CMS网站</title>
      <link>https://dodoro.chouxiangpai.com/archives/1956/</link>
      <pubDate>Fri, 30 Jun 2023 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1956/</guid>
      <description>&lt;p&gt;在本指南中，您将使用项目模板将Orchard Core设置为内容管理系统。&lt;/p&gt;
&lt;p&gt;您需要什么&lt;/p&gt;
&lt;p&gt;.NET SDK的当前版本。您可以从以下网址下载它：&lt;a href=&#34;https://dotnet.microsoft.com/download&#34;&gt;https://dotnet.microsoft.com/download&lt;/a&gt;. 文本编辑器和终端，您可以在其中键入 dotnet 命令。&lt;/p&gt;
&lt;p&gt;创建项目&lt;/p&gt;
&lt;p&gt;有多种创建Orchard Core网站和模块的方法。您可以在这里了解更多信息。&lt;/p&gt;
&lt;p&gt;在本指南中，我们将使用“代码生成模板”。您可以使用此命令安装最新稳定版本的模板：&lt;/p&gt;
&lt;p&gt;dotnet new install OrchardCore.ProjectTemplates::1.5.0-*&lt;/p&gt;
&lt;p&gt;注意&lt;/p&gt;
&lt;p&gt;要使用模板的开发分支，请添加 &amp;ndash;nuget-source &lt;a href=&#34;https://nuget.cloudsmith.io/orchardcore/preview/v3/index.json&#34;&gt;https://nuget.cloudsmith.io/orchardcore/preview/v3/index.json&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;创建一个空文件夹来存放你的网站。打开终端，进入该文件夹并运行以下命令：&lt;/p&gt;
&lt;p&gt;dotnet new occms -n MySite&lt;/p&gt;
&lt;p&gt;这样就在一个名为 MySite 的文件夹中创建了一个新的Orchard Core CMS项目。&lt;/p&gt;
&lt;p&gt;设置站点&lt;/p&gt;
&lt;p&gt;应用程序已经由模板创建，但尚未设置。&lt;/p&gt;
&lt;p&gt;通过执行以下命令启动应用程序：&lt;/p&gt;
&lt;p&gt;dotnet run &amp;ndash;project .\MySite\MySite.csproj&lt;/p&gt;
&lt;p&gt;Note&lt;/p&gt;
&lt;p&gt;如果你正在使用模板的开发分支，请在运行应用程序之前运行dotnet restore .\MySite\MySite.csproj &amp;ndash;source &lt;a href=&#34;https://nuget.cloudsmith.io/orchardcore/preview/v3/index.json&#34;&gt;https://nuget.cloudsmith.io/orchardcore/preview/v3/index.json&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;现在您的应用程序应该正在运行，并监听以下端口： 现在监听 on: &lt;a href=&#34;https://localhost:5001&#34;&gt;https://localhost:5001&lt;/a&gt; 和 on: &lt;a href=&#34;http://localhost:5000%E3%80%82%E5%BA%94%E7%94%A8%E5%B7%B2%E7%BB%8F%E5%90%AF%E5%8A%A8%EF%BC%8C%E6%8C%89&#34;&gt;http://localhost:5000。应用已经启动，按&lt;/a&gt; Ctrl+C 可以关闭应用。&lt;/p&gt;
&lt;p&gt;在浏览器中打开 &lt;a href=&#34;https://localhost:5001&#34;&gt;https://localhost:5001&lt;/a&gt; 可以显示设置屏幕。&lt;/p&gt;
&lt;p&gt;为了演示的目的，我们将使用 Blog 配方创建网站。Blog 配方是 Orchard Core 的 入门配方之一，其中包含一系列功能和配置 Orchard Core 网站的步骤。&lt;/p&gt;
&lt;p&gt;完成设置表单，选择 Blog 配方和 SQLite 数据库。&lt;/p&gt;
&lt;p&gt;提交表单后，几秒钟后您将可以看到一个博客站点。&lt;/p&gt;
&lt;p&gt;为了配置并开始编写内容，您可以转到 &lt;a href=&#34;https://localhost:5001/admin&#34;&gt;https://localhost:5001/admin&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;概要&lt;/p&gt;</description>
    </item>
    <item>
      <title>OrchardCore入门指南：创建一个模块化的 ASP.NET Core 应用程序</title>
      <link>https://dodoro.chouxiangpai.com/archives/1954/</link>
      <pubDate>Fri, 30 Jun 2023 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1954/</guid>
      <description>&lt;p&gt;你将要构建什么&lt;/p&gt;
&lt;p&gt;您将创建一个模块化的 ASP.NET Core MVC 网络应用程序，类似于包含在 Orchard Core 中的 &amp;ldquo;Hello World&amp;rdquo; 应用程序示例。它包括一个网络应用程序和一个模块。网络应用程序提供了布局，而模块注册了路由并响应首页请求。您可以参考 Orchard Core 中的以下项目以获取更多信息。&lt;/p&gt;
&lt;p&gt;src/OrchardCore.Mvc.Web src/OrchardCore.Modules/OrchardCore.Mvc.HelloWorld 所需材料 当前版本的 .NET SDK。您可以从此处下载: &lt;a href=&#34;https://dotnet.microsoft.com/download&#34;&gt;https://dotnet.microsoft.com/download&lt;/a&gt;. 一个文本编辑器和一个终端，您可以在其中运行 dotnet CLI 命令。 创建 Orchard Core 网站和模块 有不同的方法可以为 Orchard Core 创建网站和模块。您可以在 此处 了解更多信息。&lt;/p&gt;
&lt;p&gt;在本指南中，我们将使用我们的代码生成模板。您可以使用以下命令安装模板的最新稳定版本： dotnet new install OrchardCore.ProjectTemplates::1.5.0-*&lt;/p&gt;
&lt;p&gt;Note&lt;/p&gt;
&lt;p&gt;如果想使用模板的开发分支，请添加 &amp;ndash;nuget-source &lt;a href=&#34;https://nuget.cloudsmith.io/orchardcore/preview/v3/index.json&#34;&gt;https://nuget.cloudsmith.io/orchardcore/preview/v3/index.json&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;创建一个名为OrchardCore.Mvc的空文件夹，它将包含我们的项目。打开一个终端，进入该文件夹并运行以下命令来创建Web应用程序：&lt;/p&gt;
&lt;p&gt;dotnet new ocmvc -n OrchardCore.Mvc.Web&lt;/p&gt;
&lt;p&gt;接下来，创建“ Hello World”模块。&lt;/p&gt;
&lt;p&gt;dotnet new ocmodulemvc -n OrchardCore.Mvc.HelloWorld&lt;/p&gt;
&lt;p&gt;将Web应用程序中指向该模块的项目引用添加到其中。&lt;/p&gt;
&lt;p&gt;dotnet add OrchardCore.Mvc.Web reference OrchardCore.Mvc.HelloWorld&lt;/p&gt;
&lt;p&gt;可选地，您可以添加一个解决方案文件，该文件引用了Web应用程序和模块，以便在Visual Studio中打开解决方案。&lt;/p&gt;
&lt;p&gt;dotnet new sln -n OrchardCore.Mvc dotnet sln add OrchardCore.Mvc.Web\OrchardCore.Mvc.Web.csproj dotnet sln add OrchardCore.Mvc.HelloWorld\OrchardCore.Mvc.HelloWorld.csproj 测试生成的应用程序 从包含两个项目的OrchardCore.Mvc根文件夹中运行以下命令启动Web应用程序：&lt;/p&gt;</description>
    </item>
    <item>
      <title>OrchardCore入门指南</title>
      <link>https://dodoro.chouxiangpai.com/archives/1952/</link>
      <pubDate>Tue, 20 Jun 2023 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1952/</guid>
      <description>&lt;p&gt;指南 无论你在构建什么，这些指南旨在让你尽快使用最新的Orchard Core项目版本和Orchard团队推荐的技术，进入工作状态。&lt;/p&gt;
&lt;p&gt;入门指南 这些指南旨在在15-30分钟内完成，提供快速的、实践操作的指令，用于使用Orchard Core构建任何开发任务的“Hello World”。在大多数情况下，唯一的先决条件是一个.NET SDK和一个文本编辑器。&lt;/p&gt;
&lt;p&gt;创建一个模块化的ASP.NET Core应用程序 在启动时运行代码 自定义编码设置 Orchard Core CMS指南 这些指南专门针对Orchard Core CMS：&lt;/p&gt;
&lt;p&gt;创建Orchard Core CMS网站 向管理导航添加菜单项 安装本地化文件 如何使用资产转码器/绑定器/缩小器管道- 集成 Facebook 插件 实现全文检索 将 AzureAD 集成为外部提供程序 教程 这些教程旨在在2-3小时内完成，提供更深入、上下文探讨企业应用程序开发主题，并让您准备实现现实世界的解决方案。&lt;/p&gt;
&lt;p&gt;使用 Razor Pages 构建解耦的网站 构建一个来自 Web 模板的网站（待定） 实施自助式 SaaS 解决方案（待定）&lt;/p&gt;</description>
    </item>
    <item>
      <title>Entity Framework Core 创建DbContext的两种方法</title>
      <link>https://dodoro.chouxiangpai.com/archives/1940/</link>
      <pubDate>Mon, 08 May 2023 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1940/</guid>
      <description>&lt;p&gt;最近创建基于firstcode的开发模式，整理了一下如何使用Entity Framework Core 创建DbContext。&lt;/p&gt;
&lt;p&gt;1、第一种重写DbContext的OnConfiguring方法，每次生成一个DbContext的方法的时候就会重新来这个方法这里读一下配置。&lt;/p&gt;
&lt;p&gt;这种情况下，首先尝试通过调用 Program.CreateHostBuilder()、调用 Build()，然后访问 Services 属性来获取服务提供程序。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Main(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;[] args)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        =&amp;gt; CreateHostBuilder(args).Build().Run();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// EF Core uses this method at design time to access the DbContext&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; IHostBuilder CreateHostBuilder(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;[] args)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        =&amp;gt; Host.CreateDefaultBuilder(args)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .ConfigureWebHostDefaults(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                webBuilder =&amp;gt; webBuilder.UseStartup&amp;lt;Startup&amp;gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Startup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; ConfigureServices(IServiceCollection services)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        =&amp;gt; services.AddDbContext&amp;lt;ApplicationDbContext&amp;gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Configure(IApplicationBuilder app, IWebHostEnvironment env)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ApplicationDbContext&lt;/span&gt; : DbContext
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; ApplicationDbContext(DbContextOptions&amp;lt;ApplicationDbContext&amp;gt; options)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        : &lt;span style=&#34;color:#66d9ef&#34;&gt;base&lt;/span&gt;(options)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;2、使用不带参数的构造函数&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#中引用类型的赋值、浅拷贝和深拷贝</title>
      <link>https://dodoro.chouxiangpai.com/archives/1895/</link>
      <pubDate>Fri, 07 Apr 2023 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1895/</guid>
      <description>&lt;p&gt;赋值和深复制、浅复制并不是一样的，含义是不一样的。赋值。指的是 “ 等号= ”。它相当于是给引用对象起一个别名。浅度复制和深度复制。指的是类实现 ICloneable接口，重写该接口的唯一方法。注意：不管是深度复制还是浅度复制，都是通过ICloneable接口去实现的。&lt;/p&gt;
&lt;p&gt;值类型变量存储的是变量的值，直接储存在栈内存中。引用类型变量存储的是变量所在的内存地址，引用类型变量的实际数据存储于托管堆，变量本身仅仅是一个指向堆中实际数据的地址，存储于栈内存中，通常是四个字节。&lt;/p&gt;
&lt;p&gt;值类型Value存储在线程堆栈中。引用类型Reference存储在托管堆上。&lt;/p&gt;
&lt;p&gt;全局数据区：存放全局变量，静态数据，常量。代码区：存放所有的程序代码。栈区：存放为运行而分配的局部变量，参数，返回数据，返回地址等。堆区：即自由存储区&lt;/p&gt;
&lt;p&gt;为了理解值类型变量和引用类型变量的内存分配模型，我们应先区分两种不同的内存区域——线程堆栈Thread Stack和托管堆Managed Heap。每一个正在运行的程序都对应着一个进程Process，在一个进程内部，可以有一个或多个线程Thread，每个线程都拥有一块“自留地”，成为线程堆栈,大小为1M，用于保存自身的一些数据，如函数中定义的局部变量、函数调用时传送的参数值等。现在我们可以解释第一句话——值类型存储在线程堆栈中，也就是说所有值类型的变量都是在线程堆栈中分配的。另一块内存区域称为堆Heap,在.NET这种托管环境下，堆由CLR（Common Language Runtime）管理，所以又称托管堆Managed Heap。例如使用new关键字创建类的对象实例时，分配给对象的内存单元就位于托管堆中。&lt;/p&gt;
&lt;p&gt;1、赋值。赋值和深度复制，浅度复制完全是不同的概念，并没有什么关系，很多文章说赋值对于值类型是深度复制，对于引用类型是浅度复制，这种说法是不正确的，它的本质是在线程栈上产生一样的副本。&lt;/p&gt;
&lt;p&gt;2、浅度复制。值类型成员独立，但是引用类型成员共享。&lt;/p&gt;
&lt;p&gt;3、深度复制。值类型成员和引用类型成员都是独立的，即完完全全的一个全新的副本，称之为深度复制。&lt;/p&gt;
&lt;p&gt;（1）String字符串对象是引用对象，但是很特殊，它表现的如值对象一样，即对它进行赋值，分割，合并，并不是对原有的字符串进行操作，而是返回一个新的字符串对象。但这其实是运算符重载的结果，将string实现为语义遵循一般的、直观的字符串规则。 String对象被分配在堆上,而不是栈上。&lt;/p&gt;
&lt;p&gt;（2）Array数组对象是引用对象，在进行赋值的时候，实际上返回的是源对象的另一份引用而已；因此如果要对数组对象进行真正的复制（深拷贝），那么需要新建一份数组对象，然后将源数组的值逐一拷贝到目的对象中。&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#实现两个顺序链表的合并</title>
      <link>https://dodoro.chouxiangpai.com/archives/1897/</link>
      <pubDate>Fri, 07 Apr 2023 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1897/</guid>
      <description>&lt;p&gt;最近开始刷leetcode，刷了一周时间，确实会上瘾，不过能巩固很多基础知识，包括算法和语言。我现在是架构与编码并行。今天遇到的是两个列表的合并，刚开始我自己写了一个笨方法来合并，虽然通过了测试，但是代码质量不高，于是研究了其他人写的代码。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;//传入的两个链表本身是从小到大排序好&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; ListNode MergeTwoLists(ListNode list1, ListNode list2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ListNode head = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ListNode(); &lt;span style=&#34;color:#75715e&#34;&gt;//定义新的链表头&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ListNode current = head;&lt;span style=&#34;color:#75715e&#34;&gt;//定义链表最新的next地址&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;//遍历两个链表，任何一个完毕后就终止循环&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (list1 != &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt; &amp;amp;&amp;amp; list2 != &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (list1.val &amp;lt; list2.val)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;//如果list1的元素值小，则把当前list1赋予current.next，注意这里相当于head.next&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            current.next = list1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            list1 = list1.next;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            current.next = list2;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            list2 = list2.next;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;//将current变量指向current.next，相当于head.next,当进入下一次循环给current.next赋值的时候，相当于是给head.next.next赋值了，一直这么循环到最后&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        current = current.next;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;//head链表的next指向未循环完成的部分&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    current.next = list1 == &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt; ? list2 : list1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;//返回合并后的链表&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; head.next;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我刚开始发懵了，居然没理解这部分代码，因为忽略了“每次循环之后current的引用指向已经发生变化”。&lt;/p&gt;</description>
    </item>
    <item>
      <title>.NET7下string的改进</title>
      <link>https://dodoro.chouxiangpai.com/archives/1830/</link>
      <pubDate>Thu, 12 Jan 2023 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1830/</guid>
      <description>&lt;p&gt;string是开发过程中，使用频度最高的类型之一，所以在构建类型时作了很多处理，如“不可变性”，“保留性”等特点。string的常量是在&amp;quot;&amp;ldquo;引号中进行赋值的。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; str1 = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;这是一段文字&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(str1);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;为了字符串的格式化，引入了$&amp;ldquo;&amp;ldquo;定义方式，这样就可以在字符串中用{}来标注格式化的内容了。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; str2 = &lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;时间：{DateTime.Now}&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(str2);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;//输出结果是：时间：1/6/2023 15:37:13&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; str2_1 = &lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;时间：{DateTime.Now:yyyy-MM-dd}&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(str2_1);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;//输出结果是：时间：2023-01-06&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;为了解决字符串内容的换行，引定入@&amp;quot;&amp;quot;，来定义有换行的字符串，比如下面的一条SQL查询，可以按格式化后的样式来定义。$和@可以混用，不分先后。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; str3 = &lt;span style=&#34;color:#e6db74&#34;&gt;@&amp;#34;SELECT ID
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    ,Question
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    ,Score
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    ,QuestionTypeID
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    ,SubjectTypeID
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    FROM Questions&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(str3);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; str3_1 = &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;SELECT ID
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    ,Question
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    ,Score
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    ,QuestionTypeID
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    ,SubjectTypeID
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    FROM Questions WHERE Score&amp;gt;{10}&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(str3_1);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其实原始字符串还解决了一个问题，就是字符串中有&amp;quot;的问题，以前需要有转义字符来实现，现在原始字符串都搞定了。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\&amp;#34;a\&amp;#34; 是小写的&amp;#34;&lt;/span&gt;);&lt;span style=&#34;color:#75715e&#34;&gt;//通过\来转义&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;@&amp;#34;&amp;#34;&amp;#34;a&amp;#34;&amp;#34; 是小写的&amp;#34;&lt;/span&gt;);&lt;span style=&#34;color:#75715e&#34;&gt;//前缀是@时，通过&amp;#34;转义&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最佳demo是json字符串的定义，用原始字符串的方式定义json字符串，最合适不过了。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; jsonString = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;irstName&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;John&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;astName&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Smith&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ex&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;male&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ge&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;25&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ddress&amp;#34;&lt;/span&gt;: 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;treetAddress&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;21 2nd Street&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ity&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;New York&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tate&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;NY&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ostalCode&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;10021&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(jsonString)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;通过下图，看到的json原始字符串，一目了然：&lt;/p&gt;</description>
    </item>
    <item>
      <title>[转]NPM和webpack的关系</title>
      <link>https://dodoro.chouxiangpai.com/archives/1798/</link>
      <pubDate>Mon, 02 Jan 2023 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1798/</guid>
      <description>&lt;p&gt;入门前端的坑也很久了，以前很多大小项目，前端都是传统式开发，一直在重复造轮子；接触VUE后，对vue-cli有了解后，仅仅知道vue-cli是一个vue项目的脚手架，可以快速的构建一个vue的基于npm的模块化项目，vue内部的打包机制其实还是借助webpack；但是对webpack\npm\node\nodejs这几个在前端模块化中的高频词总是傻傻分不清，不知道他们之间的具体关系，今天花了些功夫查阅了网上大神的回答和官方教程给出的解释写一篇小白文，总结一下这几个概念或者说高频词汇之间的关系&lt;/p&gt;
&lt;h2 id=&#34;what-is-webpack&#34;&gt;what is webpack?&lt;/h2&gt;
&lt;p&gt;Webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析，然后将这些模块按照指定的规则生成对应的静态资源。即WebPack可以看做是模块打包机：它做的事情是，分析你的项目结构，找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言（Scss，TypeScript等），并将其转换和打包为合适的格式供浏览器使用。&lt;/p&gt;
&lt;h2 id=&#34;webpack的核心作用&#34;&gt;webpack的核心作用&lt;/h2&gt;
&lt;p&gt;模块化开发中，我们会编写大量模块，如果不打包就上线，那么页面加载或交互时，将会发起大量请求。为了性能优化，需要使用webpack这样的打包器对模块进行打包整合，以减少请求数。就像简单的vue项目，所有组件最终都将被打包到一个app.js中。 相较于无差别打包依赖模块的传统打包器，webpack的核心优势在于它从入口文件出发，递归构建依赖关系图。通过这样的依赖梳理，webpack打包出的bundle不会包含重复或未使用的模块，实现了按需打包，极大的减少了冗余。&lt;/p&gt;
&lt;p&gt;webpack是一个工具，这个工具可以帮你处理好各个包/模块之间的依赖关系（modules with dependencies），并将这些复杂依赖关系的静态文件打包成一个或很少的静态文件，提供给浏览器访问使用；除此之外，webpack因为可以提高兼容性，可以将一些浏览器尚不支持的新特性转换为可以支持格式，进而减少由新特性带来的浏览器的兼容性问题。&lt;/p&gt;
&lt;p&gt;好，我们通过介绍，我们有个概念，webpack是一个打包工具，可以帮你把你的项目这里的项目其实就是指通过模块化开发的项目 打包为简洁版的浏览器可识别的静态资源。&lt;/p&gt;
&lt;h2 id=&#34;what-is-npm&#34;&gt;what is npm?&lt;/h2&gt;
&lt;p&gt;介绍了webpack，我们可能会疑问，我的JS，CSS，HTML文件分开写，挺好的呀，为什么要使用webpack工具，进行复杂的各项配置。在传统前端开发模式下，我们确实是按照JS/CSS/HTML文件分开写的模式就可以，但是随着前端的发展，社区的壮大，各种前端的库和框架层出不穷，我们项目中可能会使用很多额外的库，如何有效管理这些引入的库文件是一个大问题，而且我们知道基于在HTML中使用script引入的方式，有两个弊端，一个是会重复引入，二是当库文件数量很多时管理成为一个大难题。面对这样的局面，为了简化开发的复杂度，前端社区涌现了很多实践方法。模块化就是其中一项成功实践，而npm就是这样在社区 其实就是node社区中产生的。&lt;/p&gt;
&lt;p&gt;npm 由三个独立的部分组成：网站、注册表（registry）、命令行工具 (CLI)。&lt;/p&gt;
&lt;p&gt;网站 是开发者查找包（package）、设置参数以及管理 npm 使用体验的主要途径。 注册表 是一个巨大的数据库，保存了每个包（package）的信息。CLI 通过命令行或终端运行。开发者通过 CLI 与 npm 打交道。&lt;/p&gt;
&lt;p&gt;一般来说提起npm有两个含义，一个是说npm官方网站，一个就是说npm包管理工具。npm社区或官网是一个巨大的Node生态系统，社区成员可以随意发布和安装npm生态中的包，也就是不用在重复造轮子了，别人造好了，你直接安装到你的项目中就可以使用，但是因为前面说了，当包引入数量很多时管理就成为了一个问题，这个就是npm为开发者行了方便之处，npm已经为你做好了依赖和版本的控制，也就是说使用npm可以让你从繁杂的依赖安装和版本冲突中解脱出来，进而关注你的业务而不是库的管理。&lt;/p&gt;
&lt;p&gt;webpack就是将你从npm中安装的包打包成更小的浏览器可读的静态资源，这里需要注意的是，webpack只是一个前端的打包工具，打包的是静态资源，和后台没有关系，虽然webpack依赖于node环境。&lt;/p&gt;
&lt;h2 id=&#34;what-is-node-or-nodejs&#34;&gt;what is node or nodejs？&lt;/h2&gt;
&lt;p&gt;其实node和nodejs两个概念没有太大差别，我个人认为唯一的区别就是，人们说起node的时候语境更多的是再说node环境，而说nodejs时更多的是在说node是一门可以提供后端能力的技术。本质上来说，node就是nodejs，nodejs就是node&lt;/p&gt;
&lt;p&gt;简单的说 Node.js 就是运行在服务端的 JavaScript。Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。Node.js是一个事件驱动I/O服务端JavaScript环境，基于Google的V8引擎，V8引擎执行Javascript的速度非常快，性能非常好。&lt;/p&gt;
&lt;p&gt;node环境基于V8引擎提供了一种可以让JS代码跑在后端的能力，这就是node。其实这里的node本身和我们这篇讲的前端模块化没啥关系。但是因为npm是产生与node社区，node中也是通过npm来加载模块的，所以有必要说一下他们之间的关系。&lt;/p&gt;
&lt;p&gt;npm 是 Node.js 官方提供的包管理工具，他已经成了 Node.js 包的标准发布平台，用于 Node.js 包的发布、传播、依赖控制。&lt;/p&gt;
&lt;h2 id=&#34;webpack-npm-node之间关系&#34;&gt;webpack npm node之间关系？&lt;/h2&gt;
&lt;p&gt;webpack是npm生态中的一个模块，我们可以通过全局安装webpack来使用webpack对项目进行打包；&lt;/p&gt;
&lt;p&gt;webpack的运行依赖于node的环境，没有node是不能打包的，但是webpack打包后的项目本身只是前端静态资源和后台没有关系，也就是说不依赖与node，只要有后台能力的都可以部署项目。&lt;/p&gt;
&lt;p&gt;npm是于Node社区中产生的，是nodejs的官方包管理工具，当你下载安装好node的时候，npm cli 就自动安装好了。&lt;/p&gt;
&lt;p&gt;正是因为npm的包管理，使得项目可以模块化的开发，而模块化的开发带来的这些改进确实大大的提高了我们的开发效率，但是利用它们开发的文件往往需要进行额外的处理才能让浏览器识别，而手动处理又是非常繁琐的，这就是webpack工具存在的意义&lt;/p&gt;
&lt;p&gt;原文地址：&lt;a href=&#34;https://blog.csdn.net/AngelLover2017/article/details/84801673&#34;&gt;https://blog.csdn.net/AngelLover2017/article/details/84801673&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#泛型接口的协变和逆变</title>
      <link>https://dodoro.chouxiangpai.com/archives/1781/</link>
      <pubDate>Fri, 21 Oct 2022 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1781/</guid>
      <description>&lt;h2 id=&#34;一协变和逆变是什么&#34;&gt;一、协变和逆变是什么？&lt;/h2&gt;
&lt;p&gt;先从字面上理解 协变(Covariance)、逆变(Contravariance)。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;co- &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;是英文中表示“协同”、“合作”的前缀。协变&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;的字面意思就是&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;“与变化的方向相同”。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;contra- &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;是英文中表示“相反”的前缀，逆变&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;的字面意思就是是&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;“与变化方向相反”。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;官方：协变和逆变都是术语，前者指能够使用比原始指定的派生类型的派生程度更大（更具体的）的类型，后者指能够使用比原始指定的派生类型的派生程度更小（不太具体的）的类型。&lt;/p&gt;
&lt;p&gt;那么问题来了，这里的“变化方向”指的是什么？&lt;/p&gt;
&lt;p&gt;C# 中对于对象（即对象引用），仅存在一种隐式类型转换，即 子类型的对象引用到父类型的对象引用的转换。这里的变化指的就是这种 子-&amp;gt;父 的类型转换。&lt;/p&gt;
&lt;p&gt;协变与逆变虽然从名字上看是两个完全相反的转换，但其实只是“子类型引用到父类型引用”这一过程在函数中使用的“两个不同阶段”而已，接下来将详细说明这点。&lt;/p&gt;
&lt;h2 id=&#34;二为什么需要协变和逆变&#34;&gt;二、为什么需要协变和逆变&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;images/0.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1781/images/0.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;三协变例子&#34;&gt;三、协变例子&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;images/1.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1781/images/1.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;四逆变例子&#34;&gt;四、逆变例子&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;images/2.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1781/images/2.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;五net自带的协变和逆变委托和泛型&#34;&gt;五、.NET自带的协变和逆变委托和泛型&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;images/3.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1781/images/3.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#委托之Action和Func的用法</title>
      <link>https://dodoro.chouxiangpai.com/archives/1779/</link>
      <pubDate>Thu, 20 Oct 2022 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1779/</guid>
      <description>&lt;p&gt;我们在使用委托的过程中，除了为每个参数和返回类型定义一个委托之外，也就是说为每一个方法（作为参数的方法）定义一个委托，我们还可以使用Action和Func委托。&lt;/p&gt;
&lt;p&gt;泛型Action委托表示引用一个void返回类型的方法。Action委托类存在不同的变体，可以传递至多16种不同的参数类型，没有泛型参数的Action类可以调用没有参数的方法。例如：Action调用带一个参数的方法，Action&amp;lt;in T1,in T2&amp;gt;调用带两个参数的方法等&lt;/p&gt;
&lt;p&gt;Func的用法和Action用法类似，但是Func表示引用一个带返回类型的方法，Func也存在不同的变体，至多可以传递16个参数类型和1个返回类型，例如：Func&amp;lt;in T1,out Resout&amp;gt;表示带一个参数的方法，Func&amp;lt;in T1,in T2,out Resout&amp;gt;表示调用带两个参数的方法。&lt;/p&gt;
&lt;p&gt;总结 1：Action用于没有返回值的方法（参数可以根据自己情况进行传递）;2：Func恰恰相反用于有返回值的方法（同样参数根据自己情况情况）;3：记住无返回就用action，有返回就用Func&lt;/p&gt;</description>
    </item>
    <item>
      <title>[转]Azure Container App 应用介绍</title>
      <link>https://dodoro.chouxiangpai.com/archives/1772/</link>
      <pubDate>Mon, 10 Oct 2022 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1772/</guid>
      <description>&lt;p&gt;容器技术正日益成为打包、部署应用程序的第一选择。Azure提供了许多使用容器的选项。例如，我们可以使用Azure容器注册表来存储和管理Docker Images。Azure Container Instance或Azure应用服务可用于运行隔离容器。对于需要完整容器编排、自动缩放和服务发现的更复杂的场景，Azure Kubernetes服务是一个很好的选择。问题是，Azure Kubernetes虽然是托管的，但 用起来还是有些困难，开发人员必须得学习掌握一些运维知识。&lt;/p&gt;
&lt;p&gt;2021年，Azure提出了新服务 Azure Container App。该服务旨在减少构建 AKS 应用程序所需的知识和配置量，从而可能降低解决方案成本并加快上市时间。&lt;/p&gt;
&lt;h2 id=&#34;1什么是-azure-container-app-&#34;&gt;1，什么是 Azure Container App ？？&lt;/h2&gt;
&lt;p&gt;Azure Container App 提供位于 AKS 服务之上的无服务器托管服务，允许您部署多个容器而无需处理底层基础结构。事实上，Azure Container App 甚至不向用户公开 Kubernetes API。&lt;/p&gt;
&lt;p&gt;当我们在 Azure Container App中部署或更改容器时，该服务将自动创建应用程序的快照&amp;mdash;&amp;ndash;修订版，并在一个 pod 中运行它的容器。就像在 Azure Kubernetes 中一样，这些容器共享相同的应用程序生命周期、网络和磁盘。它们可以相互交流。此外，由于它与基于 Kubernetes 的事件驱动自动缩放的集成，该服务将根据 HTTP 并发请求数等指标自动增加/减少（不支持垂直缩放）与修订相关的 Pod 数量和内存使用。作为节省一些费用上开支，我们还可以将最小副本数设置为 0。如果应用程序没有请求，该服务会将活动 pod 的数量缩减为 0，我们无需支付任何费用。&lt;/p&gt;
&lt;p&gt;同时多个 Azure Container App 也可以部署到单个环境中。通过这样做，它们将被置于同一个虚拟网络下并与外界隔离。为了提供监视功能，每个环境都有自己的 Log Analytics 工作区，该工作区与其中的 Azure Container App共享。对于熟悉 Kubernetes 的人来说，我们可以将 Azure Container App Environment 视为 Kubernetes Namespace，将 Azure Container App Revision 视为 Kubernetes Deployment。&lt;/p&gt;</description>
    </item>
    <item>
      <title>依赖注入简单易懂的详解</title>
      <link>https://dodoro.chouxiangpai.com/archives/1761/</link>
      <pubDate>Fri, 09 Sep 2022 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1761/</guid>
      <description>&lt;p&gt;之前记录的依赖注入太复杂，今天认真看了《C#高级编程》里面对依赖注入的解释，明显就简单很多。&lt;/p&gt;
&lt;h2 id=&#34;1什么是依赖注入为什么需要它&#34;&gt;&lt;strong&gt;1、什么是依赖注入？为什么需要它？&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;更快的开发周期需要单元测试和更好的可更新性。更改一些代码，不应该导致意外位罝出现错误。创建更模块化的、减少依赖项的应用程序，有助于防止这种错误。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;依赖注入(Dependency Injection,DI)允许从类的外部注入依赖项，因此注入依赖项的类只需要知道一个协定(通常是C#接口)。这个类可以独立于其对象的创建。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;依赖注入更便于进行单元测试。在单元测试中，只需要测试特定的类，需要的依赖项可以替换为包含测试数据的特殊模拟类。&lt;/p&gt;
&lt;p&gt;还可以使用不同的实现区分生产模式和开发模式。例如，在生产过程中，可能需要访问SAP服务器，或者可能需要对所有开发人员都无法访问的特定活动目录进行身份验证。在开发的每个调试会话期间，都不希望等待成功的身份验证，也不需要SAP服务器开发用户界面。在这里，可以给相同的协定使用不同的实现来模拟身份验证，可以使用测试数据而不是访问SAP服务器。&lt;/p&gt;
&lt;p&gt;也可以在不同的平台上使用不同的实现。例如，可&lt;strong&gt;以创建一个.NET标准库，在其中为UWP、WPF和Xamarin应用程序实现所有公共功能，并可以根据需要重定向到特定于平台的代码。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;依赖注入还允许用自定义特性替换标准功能。ASP.NETCore和EntityFrameworkCore主要基于依赖注入。这些技术使用数百个协定一例如，来找到控制器，将HTTP请求映射到控制器，将接收到的数据转换为参数，将数据库表映射到实体类型等。使用不同的实现，可以轻松地替换自定义功能。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DI是敏捷软件开发和持续软件交付实践的核心模式。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;**依赖注入不需要依赖注入容器，但该容器有助于管理依赖项。**依赖注入容器管理的服务列表越来越长，就可以看到它的优点。ASP.NETCore和EntityFrameworkCore使用Microsoft.Exteosions.DependencyInjection作为容器来管理所有依赖项，以此管理数百个服务。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;尽管依赖注入和依赖注入容器在非常小的应用程序中会增加复杂性，但是一旦应用程序变得更大，需要多个服务，依赖注入就会降低复杂性，并促进非紧密绑定的实现。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;2没有依赖注入&#34;&gt;&lt;strong&gt;2、没有依赖注入&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;下面的示例没有使用依赖注入；稍后将更改它，以使用依赖注入。所用的服务实现在类GreetingService中定义。这个类定义了返回字符串的Greet方法：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;GreetingService&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Greet(stringname)=&amp;gt;&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;Hello,{name}&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;类HomeController使用这个服务。在Hello方法中，实例化了GreetingService,并且调用Greet方法:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;HomeController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Hello(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; service = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; GreetingService();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; service.Greet(name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;下面看看Program类的Main()方法。其中实例化了HomeController,调用Hello方法，将结果写入控制台:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Main()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; controller=&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; HomeController();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; result=controller.Hello(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Stephanie&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Console.WriteLine(result);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;程序运行时，把Hello，Stephanie写入控制台。这有什么问题吗？&lt;/p&gt;
&lt;p&gt;**HomeController和GreetingService是紧密稱合的。要用不同的实现取代HomeController中的GreetingService并不容易。**这个GreetingService是一个返回字符串的简单服务。在正常的应用程序中，场景通常更复杂。例如，GreetingService可能使用HTTP请求访问API服务，或者使用EntityFramewoik访问数据库。可能要更改在一个地方使用的服务，而不是査找使用服务的所有位置。&lt;/p&gt;
&lt;p&gt;另外，为HomeController创建单元测试时，也会测试GreetingService。在单元测试中，希望仅测试单个类的方法的功能，而不需要使用其他依赖项。在HomeController中，不能很容易地为单元测试替换GreetingService。从技术上讲，为单元测试替换GreetingService方法的内部实现是可能的。使用Microsoft Fakes框架，可以通过替换GreetingSeivice类的特定方法和属性，来更改方法的实现。这个变更是在单元测试中定义的，并且只有在单元测试运行时才会发生：通过另一个方法来“伪造”原来的方法。&lt;strong&gt;其实这有更好的方法：使用依赖注入。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;下一节将介绍如何更改此实现，以使用依赖注入。&lt;/p&gt;
&lt;h2 id=&#34;3使用依赖注入实现&#34;&gt;&lt;strong&gt;3、使用依赖注入实现&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;下面使HomeController独立于GreetingService的实现。为此，可以创建接口IGreetingService,它定义了HomeController所需的功能:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IGreetingService&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Greet(stringname);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;GreetingService现在实现了接口IGreetingService:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;GreetingService&lt;/span&gt;:IGreetingService
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Greet(stringname)=&amp;gt;&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;Hello,{name}&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;HomeController现在只需要对一个对象的引用，该对象实现了接口IGreetingService。它用HomeController的构造函数注入，分配给私有字段，通过方法Hello来使用:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;HomeController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; IGreetingService _greetingService;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; HomeController(IGreetingService greetingService)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        _greetingService=greetingService??
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ArgumentMullException(nameof(greetingService));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Hello(stringname) =&amp;gt; _greetingService.Greet(name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在这个实现中，HomeController利用了控制反转的设计原理。HomeController没有像以前那样实例化GreetingService。相反，定义由HomeController使用的具体类的控件在外部给出；换句话说，控制是反转的。&lt;/p&gt;</description>
    </item>
    <item>
      <title>https请求报错block:mixed-content</title>
      <link>https://dodoro.chouxiangpai.com/archives/1759/</link>
      <pubDate>Mon, 05 Sep 2022 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1759/</guid>
      <description>&lt;p&gt;开发过程中，可能会遇到在https里面请求内容的时候报混合调用的错误，一般是因为网站启用了https，但是老的网页链接和请求中还有使用http的情况。接口会错block: mixed-content，图片则会报错：Mixed block。解决的办法有两种。&lt;/p&gt;
&lt;p&gt;第一种， 页面的head中加入下面代码（将调用的http请求升级成https请求并调用）：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;http-equiv&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Content-Security-Policy&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;upgrade-insecure-requests&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这是最方便快捷的，也是很有效的办法。&lt;/p&gt;
&lt;p&gt;第二种， 如果是接口，可以通过本地后端（将本地后端当成service中间层），从后端再去调用其他服务器的http请求。&lt;/p&gt;</description>
    </item>
    <item>
      <title>如何在.NET Core3.1使用log4net</title>
      <link>https://dodoro.chouxiangpai.com/archives/1752/</link>
      <pubDate>Tue, 23 Aug 2022 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1752/</guid>
      <description>&lt;h2 id=&#34;1添加log4net程序集&#34;&gt;1、添加log4net程序集&lt;/h2&gt;
&lt;p&gt;通过nuget添加，可以直接在程序集引用里搜索nuget包安装，也可以通过命令行安装，这里使用命令行：PM&amp;gt; Install-Package log4net&lt;/p&gt;
&lt;h2 id=&#34;2添加log4netconfig配置文件&#34;&gt;2、添加log4net.config配置文件&lt;/h2&gt;
&lt;p&gt;创建一个log4net.config文件，保存在项目的根目录：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;log4net&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;root&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;level &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ALL&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;appender-&lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;console&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;appender-&lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/root&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;!--File Appender--&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;appender name=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt; type=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;log4net.Appender.RollingFileAppender&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;file &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;main.log&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;appendToFile &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;rollingStyle &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Size&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;maxSizeRollBackups &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;5&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;maximumFileSize &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;25MB&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;staticLogFileName &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;layout type=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;log4net.Layout.PatternLayout&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;conversionPattern &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%date [%thread] %level %logger - %message%newline&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/layout&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/appender&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;!--Console appender--&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;appender name=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;console&amp;#34;&lt;/span&gt; type=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;log4net.Appender.ManagedColoredConsoleAppender&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;mapping&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;level &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;INFO&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;forecolor &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Green&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/mapping&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;mapping&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;level &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;WARN&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;forecolor &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Yellow&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/mapping&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;mapping&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;level &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ERROR&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;forecolor &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Red&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/mapping&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;mapping&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;level &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DEBUG&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;forecolor &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Blue&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/mapping&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;layout type=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;log4net.Layout.PatternLayout&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;conversionpattern &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%date [%thread] %-5level - %message%newline&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/layout&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/appender&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/log4net&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;3加载log4net的配置的并创建相关实例&#34;&gt;3、加载log4net的配置的并创建相关实例&lt;/h2&gt;
&lt;p&gt;这里有两种办法，&lt;strong&gt;第一种最简单&lt;/strong&gt;，这种情况适用于控制台应用程序，简单明了，直接用加载到程序集中：&lt;/p&gt;</description>
    </item>
    <item>
      <title>ABP框架能力清单</title>
      <link>https://dodoro.chouxiangpai.com/archives/1729/</link>
      <pubDate>Fri, 08 Jul 2022 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1729/</guid>
      <description>&lt;p&gt;ABP框架提供了一个稳定的架构用于构建企业级软件解决方案，它遵循了.NET和ASP.NETCore平台之上的最佳实践。它内置了基础架构、生产级别的模块、主题、工具、指南和文档，并尽可能地自动化开发细节和解法我们的重复性工作。&lt;/p&gt;
&lt;p&gt;在接下来的几个小节中，我将从架构层面介绍ABP是如何完成所有这些工作。&lt;/p&gt;
&lt;h2 id=&#34;abp架构&#34;&gt;ABP架构&lt;/h2&gt;
&lt;p&gt;ABP是一个特殊的架构，换句话说，它是一个有个性化的框架。先解释一下什么是没有个性的框架，什么是有个性的框架。&lt;/p&gt;
&lt;p&gt;正如我在搭建架构部分所述，为搭建解决方案的基础设施需要大量决策工作；比如系统架构、开发模型、技术、模式、工具和库。&lt;/p&gt;
&lt;p&gt;没有个性的框架，例如ASP.NETCore，这些决定大多由您决定。例如，您可以通过将UI层与数据访问层分离来创建分层解决方案，或者您可以通过直接从UI页面/视图访问数据库来创建单层解决方案。您可以使用任何库，只要它与ASP.NETCore兼容，并且您可以应用任何架构模式。无个性使ASP.NETCore在不同的场景中变得灵活和可用。但是，所有的这些都需要我们自己去做决策。&lt;/p&gt;
&lt;p&gt;我并不是说ASP.NETCore完全没有自己的个性想法。假定您正在构建基于HTTP规范的Web应用程序或API。它清楚地定义了应该如何开发UI和API层。它还提供了一些低级的基础设施组件，例如依赖项注入、缓存和日志记录。但是，它并没有说明您的业务代码是应该要如何组建，应该使用哪些架构模式。&lt;/p&gt;
&lt;p&gt;换句话说，ABP框架是一个有个性倾向的框架。它相信软件开发方法本质上可以更好，因此可以引导开发人员在解决方案中使用更佳的架构、模式、工具和库。 尽管ABP框架足够灵活，可以使用不同的工具和库来改变您的架构决策，但当您遵循它的实践原则时，您将获得最大的价值。请别担心，因为它为通用架构提供了良好的、行业认可的解决方案。他的架构规则将节省您的时间，提高您的生产力，并使您专注于您的业务代码而不是基础设施问题。&lt;/p&gt;
&lt;p&gt;在接下来，我将介绍ABP所支持的四种基本架构。&lt;/p&gt;
&lt;h2 id=&#34;领域驱动设计&#34;&gt;领域驱动设计&lt;/h2&gt;
&lt;p&gt;ABP的主要目标是根据整洁代码原则提供一个模型来构建易维护的解决方案。它提供了一个基于DDD模式和实践的分层架构。它提供了一个分层的启动模板、基础架构以及架构应用指南。&lt;/p&gt;
&lt;p&gt;由于ABP是一个软件框架，它专注于DDD的技术实现。本书的第3部分，实现领域驱动设计，解释了使用ABP框架构建基于DDD的最佳实践。&lt;/p&gt;
&lt;h2 id=&#34;模块化&#34;&gt;模块化&lt;/h2&gt;
&lt;p&gt;在软件开发中，模块化是一种拆分系统成独立模块的技术。最终目标是降低复杂性，提高可重用性，使不同的团队能够在不相互影响的情况下能并行处理不同的功能集。&lt;/p&gt;
&lt;p&gt;ABP构建模块化有两个主要挑战：&lt;/p&gt;
&lt;p&gt;第一个挑战是模块隔离。尽管ASP.NETCore有一些特性（例如Razor组件库）来支持模块化。但是，它仍然非常有限，因为它是一个底层通用的框架，并且仅对UI和API部分支持。另一方面，ABP框架提供了一个一致的模型和基础设施来构建完全隔离的、可重用的应用模块及数据库、领域、应用和UI层。&lt;/p&gt;
&lt;p&gt;第二个挑战是模块之间如何通信，使之成为一个统一的应用程序。ABP为模块化系统提供常见的模型，例如在模块之间共享数据库，在模块之间通过事件或API进行通信，以及模块安装。&lt;/p&gt;
&lt;p&gt;ABP提供了许多可在任何应用程序中使用的预构建模块。包括身份验证模块，它提供用户、角色和权限管理，同时也提供登录和注册页面。他们基本上都是可重用和自定义的。此外，ABP提供了模块启动模板，帮助您构建可重用的应用程序。这方面的一个例子可以在[第15章]使用模块化中详细介绍。&lt;/p&gt;
&lt;p&gt;模块化非常适合管理复杂的大型单体系统。但是，ABP也可以帮助您创建微服务解决方案。&lt;/p&gt;
&lt;h2 id=&#34;微服务&#34;&gt;微服务&lt;/h2&gt;
&lt;p&gt;微服务和分布式架构是构建可扩展系统的公认方法。它允许不同的团队开发不同的服务并独立地对服务进行单独部署和扩展。&lt;/p&gt;
&lt;p&gt;但是，构建微服务系统在团队开发、部署、微服务间通信、数据一致性、监控等方面存在一些重要挑战。&lt;/p&gt;
&lt;p&gt;微服务系统是一种将不同的学科、方法、技术和工具结合在一起来解决独特问题的解决方案。每个微服务系统都有其要求和限制。每个团队都有一定程度的专业知识、知识和技能。&lt;/p&gt;
&lt;p&gt;ABP框架从一开始就被设计为与微服务兼容。它在具有事务支持的微服务之间提供了一个用于异步通信的分布式事件总线。它还提供C#客户端代理来轻松调用远程服务的RESTAPI。&lt;/p&gt;
&lt;p&gt;所有预构建的ABP应用模块都经过设计，以便您可以将它们转换为微服务。ABP也提供了详细指南来解释如何创建微服务兼容模块。这样，您可以从模块化单体开始，然后将其转换为微服务解决方案。&lt;/p&gt;
&lt;p&gt;ABP团队准备了一个使用ABP框架构建的开源微服务参考方案。它演示了如何使用API网关、微服务间通信、分布式事件、分布式缓存、多个数据库提供程序和多个UI应用程序。它还包括在容器上运行解决方案的Kubernetes和Helm配置。详情参阅。&lt;/p&gt;
&lt;h2 id=&#34;saas多租户&#34;&gt;SaaS/多租户&lt;/h2&gt;
&lt;p&gt;软件即服务(SaaS)是一种广泛使用的架构模式。以下是多租户系统的典型特征：&lt;/p&gt;
&lt;p&gt;在租户之间共享硬件和软件资源。每个租户都有用户、角色和权限。在租户之间隔离数据库、缓存和其他资源。可以启用/禁用每个租户的应用功能。可以为每个租户自定义应用配置。&lt;/p&gt;
&lt;p&gt;ABP框架涵盖了所有这些要求甚至更多。它可以帮助您优雅地构建多租户系统，而您几乎感受不到多租户的存在。&lt;/p&gt;
&lt;p&gt;到目前为止，我已经介绍了四种ABP基本架构模式。此外，ABP还提供了启动模板来轻松创建新的解决方案。&lt;/p&gt;
&lt;h2 id=&#34;启动模板&#34;&gt;启动模板&lt;/h2&gt;
&lt;p&gt;使用ASP.NETCore自带的模板创建新解决方案时，只能获得单个项目，没有分层和依赖关系。您通常会花费大量时间来设置解决方案架构，包括安装工具和做配置基本。&lt;/p&gt;
&lt;p&gt;ABP框架提供了一个架构完善、分层清晰、预配置和生产就绪的启动解决方案模板。以下截图显示了当您运行ABP框架创建的启动模板时的初始UI：&lt;/p&gt;
&lt;p&gt;下面谈谈这个启动模板：解决方案已经做好逻辑分层。一些预构建模块，例如Account和Identity模块。已经实现了基本的登录、注册、用户和角色管理以及其他一些标准功能。预先配置好的单元测试和集成测试项目。一些管理数据库迁移以及使用HTTPAPI实用工具。&lt;/p&gt;
&lt;p&gt;ABP的启动模板带有UI框架和数据库提供者的多个选项。你可以从Angular、Blazor或MVC(RazorPages)选择一个作为UI框架，或者使用EntityFrameworkCore或MongoDB作为数据库提供者。&lt;/p&gt;
&lt;h2 id=&#34;abp基础设施&#34;&gt;ABP基础设施&lt;/h2&gt;
&lt;p&gt;ABP基于您已经了熟悉的工具和库。它没有引入新的对象关系映射器（ORM），而是使用EntityFrameworkCore。同样，它使用Serilog、AutoMapper、IdentityServer和Bootstrap，而不是自己创建类似的功能。它提供了一个解决方案集成了这些工具，并实现了常见的业务应用需求。&lt;/p&gt;
&lt;p&gt;ABP框架按照约定简化了异常处理、验证、授权、缓存、审计日志和数据库事务管理，并允许您在需要时进行精细控制。&lt;/p&gt;
&lt;p&gt;ABP与IdentityServer很好地集成，基于cookie和令牌的身份验证以及单点登录。它还提供了一个详细的、基于权限的授权系统来帮助您控制应用的权限。&lt;/p&gt;
&lt;p&gt;同时也提供了后台作业、BLOB存储、文本模板、审计日志和本地化等常见组件。&lt;/p&gt;
&lt;p&gt;在UI部分，ABP提供了完整的UI主题系统，帮助您开发无主题的模块化应用，并轻松为应用程序安装主题。它还在UI方面提供了大量功能和帮助程序，以消除重复代码。&lt;/p&gt;
&lt;h2 id=&#34;社区&#34;&gt;社区&lt;/h2&gt;
&lt;p&gt;当您在公司中搭建解决方案架构时，除了开发人员没有人会去研究它。然而，ABP拥有一个庞大而活跃的社区。他们使用相同的架构和基础设施，应用类似的最佳实践，并以类似的方式开发他们的应用程序。当您遇到基础架构问题或想要获得解决业务问题的想法或建议时，这具有很大的优势。由于ABP开发人员正在应用相同或相似的模式，因此在另一个解决方案中也更容易理解他人的代码。&lt;/p&gt;
&lt;p&gt;ABP框架自2016年以来一直存在并不断发展。截至2021年底，它在GitHub上拥有7,000多颗星、220多位贡献者、22,000多个提交、5,700个已关闭问题，以及在NuGet上超过4,000,000次下载，超过110多个专业和次要版本。我的意思是，它是一个成熟的、被接受的、值得信赖的开源项目。&lt;/p&gt;
&lt;p&gt;来自ABP核心团队和社区的贡献者，有着不断持续输出的文章，视频教程和ABP社区网站可供大家学习。&lt;/p&gt;</description>
    </item>
    <item>
      <title>ASP.NET Core应用程序配合web服务器的工作原理</title>
      <link>https://dodoro.chouxiangpai.com/archives/1719/</link>
      <pubDate>Tue, 28 Jun 2022 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1719/</guid>
      <description>&lt;p&gt;这段时间开始阅读.NET Core内部技术的书籍，发现了很多之前忽视的技术，果然还是得通过阅读，才可以加深对技术的理解。今天了解到了ASP.NET Core应用程序配合web服务器的工作原理。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;images/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20220628092554-2.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1719/images/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20220628092554-2-300x97.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Web服务器(如IIS)通过一个配置的端口与完全解耦的可执行文件通信，并将传入的请求转发给控制台应用程序。这个控制台应用程序由一个必要的HTTP模块从US进程空间生成，该HTTP模块使IIS能够支持ASP.NETCore。要将ASP.NETCore应用程序托管到其他Web服务器(如Apache或NGINX)上，必须有类似的扩展模块。&lt;/p&gt;
&lt;p&gt;这里值得注意的是，图中给出的ASP.NETCore架构与最初的架构(即2003年将ASP.NET1.x与IIS连接起来的架构)有类似之处。当时ASP.NET有自己的工作进程，通过命名管道与IIS通信。后来，ASP.NET工作进程的任务被内置的IIS工作进程(w3wp.exe)接过，从而有了应用程序池的概念。在ASP.NETCore中，两个独立的、无关的、完全解耦的可执行文件进行通信，但是ASP.NET可执行文件并不是一个多租户工作进程，而只是托管一个基本的异步服务器来处理传入请求的应用程序的一个实例。&lt;/p&gt;</description>
    </item>
    <item>
      <title>微软官方.NET 升级助手：可以将NET Core 3.1项目升级为.NET 6</title>
      <link>https://dodoro.chouxiangpai.com/archives/1717/</link>
      <pubDate>Tue, 21 Jun 2022 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1717/</guid>
      <description>&lt;p&gt;装并运行升级助手 在命令提示符下，运行以下命令安装升级助手工具:&lt;/p&gt;
&lt;p&gt;dotnet tool install -g &amp;ndash;add-source &amp;lsquo;&lt;a href=&#34;https://api.nuget.org/v3/index.json&#34;&gt;https://api.nuget.org/v3/index.json&lt;/a&gt;&amp;rsquo; &amp;ndash;ignore-failed-sources upgrade-assistant&lt;/p&gt;
&lt;p&gt;现在，你已准备好在解决方案或项目上运行该工具。让我们先分析项目的包依赖项。&lt;/p&gt;
&lt;p&gt;导航到包含项目或解决方案的目录，并运行以下命令:&lt;/p&gt;
&lt;p&gt;upgrade-assistant analyze&lt;/p&gt;
&lt;p&gt;将此页命令上的 更改为解决方案或项目文件的路径和名称。&lt;/p&gt;
&lt;p&gt;上一个命令将生成 SARIF 格式的报告，该报告基于 JSON 格式，可使用以下查看器查看:&lt;/p&gt;
&lt;p&gt;任何文本编辑器。 VS extension for SARIF Viewer for a richer experience.&lt;/p&gt;
&lt;p&gt;分析项目依赖项后，运行以下命令以开始升级项目:&lt;/p&gt;
&lt;p&gt;upgrade-assistant upgrade&lt;/p&gt;
&lt;p&gt;该工具还支持其他选项。有关完整的工具使用情况信息，请参阅 GitHub 上的 升级助手自述文件。&lt;/p&gt;</description>
    </item>
    <item>
      <title>[转]开源框架Autofac使用入门</title>
      <link>https://dodoro.chouxiangpai.com/archives/1544/</link>
      <pubDate>Fri, 22 Oct 2021 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1544/</guid>
      <description>&lt;h2 id=&#34;一autofac是什么&#34;&gt;一、Autofac是什么&lt;/h2&gt;
&lt;p&gt;说到Autofac，我们就要首先了解依赖注入（Dependency Injection，简称DI）。DI不是什么技术，而是一种设计模式，是用来降低计算机程序之间的耦合的。在.net平台，有很多依赖注入工具，比较于其他的IOC框架，如Spring.NET，Unity，Castle等等所包含的，Autofac是一款较为轻量级的、性能优异的、支持xml配置的依赖注入工具。这也是为什么我选择先学习Autofac的原因。&lt;/p&gt;
&lt;h4 id=&#34;11-依赖注入di和控制反转ioc&#34;&gt;1.1 依赖注入（DI）和控制反转（IOC）&lt;/h4&gt;
&lt;p&gt;依赖注入（Dependency Injection）DI是一种软件设计模式，用来允许我们开发松耦合代码。DI是一种很好的方式去减少软件模块之间的紧耦合关心。DI帮助更好的去管理软件中的功能更新和复杂度。DI的目的是让代码可维护。依赖注入模式使用构造器对对象初始化并提供需要的依赖给对象，也就意味着允许你从类外部注入一个依赖项。&lt;/p&gt;
&lt;p&gt;控制反转（IOC，Inversion Of Contrl）也是一种设计模式，它是对DIP(依赖倒置原则，Dependence Inversion Principle)的一种实现。IOC指的是一种框架或运行时的编程风格，用来控制程序流程。IOC意味着我们可以改变常规的控制方式。它在DIP下得以实现。许多基于.net框架的软件开发都使用IOC。IOC更多的是一个通用术语，不仅仅局限于DI。&lt;/p&gt;
&lt;h4 id=&#34;12-di和ioc在项目中起到什么作用&#34;&gt;1.2 DI和IOC在项目中起到什么作用&lt;/h4&gt;
&lt;p&gt;假设你的客户端类需要使用一个服务类组件，那么你能做的就是让你的客户知道一类IService接口而不是服务类。这样，你就可以随时改变Service类的实现而不会中断已经部署的代码。&lt;/p&gt;
&lt;h2 id=&#34;二autofac如何使用&#34;&gt;二、Autofac如何使用&lt;/h2&gt;
&lt;p&gt;首先你必须获取AutoFac，这里你可以通过各种方式加载它，我这里还是通过VS中的NuGet来加载AutoFac，不论是哪种方式，最终的目的就是将 Autofac.dll，Autofac.Configuration.dll 这两个程序集引用到你的项目中。这样在你的项目中，如果想使用AutoFac，只需添加其命名空间引用即可~　这里我用的是2.6版本的（PS：Autofac.Configuration.dll V4.1 已经没有ConfigurationSettingsReader 用法稍有改变，还没去研究）&lt;/p&gt;
&lt;h4 id=&#34;21-demo分析&#34;&gt;2.1 Demo分析&lt;/h4&gt;
&lt;p&gt;代码Demo，这里在控制台应用程序中使用，首先创建一个类&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;/// 定义一个Animal接口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IAnimal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; DogCall();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; CatCall();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后，写一个类继承此接口&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Call&lt;/span&gt;: IAnimal
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; CatCall()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;喵喵喵&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; DogCall()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;汪汪汪&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;接着，用Autofac&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Main(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;[] args)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;　　　　　　　　&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; builder = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ContainerBuilder();&lt;span style=&#34;color:#75715e&#34;&gt;//创建一个IOC容器&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;　　　　　　　　builder.RegisterType&amp;lt;Call&amp;gt;().As&amp;lt;IAnimal&amp;gt;();&lt;span style=&#34;color:#75715e&#34;&gt;//通过AS可以让Call类中通过构造函数依赖注入类型相应的接口。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;　　　　　　　　&lt;span style=&#34;color:#75715e&#34;&gt;//Build()方法生成一个对应的Container实例，这样，就可以通过Resolve解析到注册的类型实例。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;　　　　　　　　&lt;span style=&#34;color:#66d9ef&#34;&gt;using&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; container = builder.Build())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;　　　　　　　　{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;　　　　　　　　　　&lt;span style=&#34;color:#75715e&#34;&gt;//当注册的类型在相应得到的容器中可以Resolve你的Call类中所有实例。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;　　　　　　　　　　&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; call = container.Resolve&amp;lt;IAnimal&amp;gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;　　　　　　　　　　call.DogCall();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;　　　　　　　　　　call.CatCall();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;　　　　　　　　}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;　　　　　　　　Console.ReadLine();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;　　　　  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用Autofac的步骤：第一步，定义一个Container容器。第二步，创建builder，并在builder中注册类型。第三步，实例化容器。第四步，在需要使用接口的地方，通过container来解析得到一个借口的实例。&lt;/p&gt;</description>
    </item>
    <item>
      <title>关于HTTP请求头中的Remote_Addr，X-Forwarded-For，X-Real-IP值</title>
      <link>https://dodoro.chouxiangpai.com/archives/1522/</link>
      <pubDate>Tue, 17 Aug 2021 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1522/</guid>
      <description>&lt;p&gt;开发过程中，我们有时候需要获取用户的客户端机器的ip地址，在遥远的拨号上网年代，我们只需要通过很简单的Remote_Addr就能获得客户端的真是ip地址，可是随着代理服务器的普及，客户端的ip地址往往不那么容易拿到。&lt;/p&gt;
&lt;h1 id=&#34;一remote_addr&#34;&gt;一、Remote_Addr&lt;/h1&gt;
&lt;p&gt;这个值表示发出请求的远程主机的IP地址，remote_addr代表客户端的IP，但它的值不是由客户端提供的，而是服务端根据客户端的ip指定的，当你的浏览器访问某个网站时，假设中间没有任何代理，那么网站的web服务器（Nginx，Apache等）就会把remote_addr设为你的机器IP，如果你用了某个代理，那么你的浏览器会先访问这个代理，然后再由这个代理转发到网站，这样web服务器就会把remote_addr设为这台代理机器的IP。&lt;/p&gt;
&lt;h1 id=&#34;二x_forwarded_for&#34;&gt;二、x_forwarded_for&lt;/h1&gt;
&lt;p&gt;简称XFF头，它代表客户端，也就是HTTP的请求端真实的IP，只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项，正如上面所述,当你使用了代理时,web服务器就不知道你的真实IP了,为了避免这个情况,代理服务器通常会增加一个叫做x_forwarded_for的头信息,把连接它的客户端IP(即你的上网机器IP)加到这个头信息里,这样就能保证网站的web服务器能获取到真实IP。&lt;/p&gt;
&lt;p&gt;设置格式：X-Forwarded-For: 127.0.0.1, 192.168.1.1, 202.19.89.64&lt;/p&gt;
&lt;p&gt;这个设置表示请求由127.0.0.1发出，经过三层代理，第一层是192.168.1.1，第二层是202.19.89.64，而本次请求的来源IP 1.1.1.1是第三层代理。&lt;/p&gt;
&lt;h1 id=&#34;三x-real-ip&#34;&gt;三、X-Real-IP&lt;/h1&gt;
&lt;p&gt;当有多个代理时候，可以在第一个反向代理上配置“proxy_set_header X-Real-IP $remote_addr” 获取真实客户端IP；&lt;/p&gt;
&lt;h1 id=&#34;四案例分析&#34;&gt;四、案例分析&lt;/h1&gt;
&lt;p&gt;&lt;img alt=&#34;file&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1522/images/image-1629181586453.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;（一）、第一种情况&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Nginx Proxy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;202.19&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;89.64&lt;/span&gt; nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location /test {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_pass http:&lt;span style=&#34;color:#75715e&#34;&gt;//192.168.108.1;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;192.168&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;108.1&lt;/span&gt; nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location /test {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_pass http:&lt;span style=&#34;color:#75715e&#34;&gt;//192.168.108.2;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Nginx Proxy就是简单的把请求往后转发&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Nginx Backend
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;192.168&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;108.108&lt;/span&gt; nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location /test {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    default_type text/html;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    charset gbk;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$remote_addr || $http_x_forwarded_for&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nginx Backend输出客户端IP（$remote_addr）和X-Forwarded-For请求头（$http_x_forwarded_for），当访问服务时输出结果：192.168.108.108 ||&lt;/p&gt;
&lt;p&gt;1.$remote_addr代表客户端IP，当前配置的输出结果为最后一个代理服务器的IP，并不是真实客户端IP；&lt;/p&gt;
&lt;p&gt;2.在没有特殊配置情况下，X-Forwarded-For请求头不会自动添加到请求头中，即Nginx Backend的$http_x_forwarded_for输出为空。&lt;/p&gt;
&lt;p&gt;（二）、第二种情况&lt;/p&gt;
&lt;p&gt;通过添加X-Real-IP和X-Forwarded-For捕获客户端真实IP。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Nginx Proxy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;202.19&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;89.64&lt;/span&gt; nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location /test {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_set_header X-Real-IP &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;remote_addr;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_set_header X-Forwarded-For &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;proxy_add_x_forwarded_for;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_pass http:&lt;span style=&#34;color:#75715e&#34;&gt;//192.168.108.1;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;192.168&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;108.1&lt;/span&gt; nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location /test {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_set_header X-Forwarded-For &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;proxy_add_x_forwarded_for;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_pass http:&lt;span style=&#34;color:#75715e&#34;&gt;//192.168.108.2;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Nginx Backend
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;192.168&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;108.108&lt;/span&gt; nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location /test {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    default_type text/html;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    charset gbk;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$remote_addr ||$http_x_real_ip  ||$http_x_forwarded_for&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;当访问服务时，输出结果为：192.168.108.108 || 202.19.89.64 || 192.168.108.1, 192.168.108.2&lt;/p&gt;</description>
    </item>
    <item>
      <title>从WebForm到MVC，一直到Blazor</title>
      <link>https://dodoro.chouxiangpai.com/archives/1518/</link>
      <pubDate>Thu, 05 Aug 2021 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1518/</guid>
      <description>&lt;p&gt;打算下一个项目用Blazor，学习了一个下午，这是一个很不错的全栈UI框架，基于WebAssembly技术，可以让开发人员直接用C#完成js的工作。&lt;/p&gt;
&lt;p&gt;学习过程中，我脑子里闪现了自己经历的那个ASP.NET的WebForm时代，那时候我们用UserControl的ascx文件布局网页。查了下，果然是一脉相承。 &lt;a href=&#34;https://docs.microsoft.com/en-us/dotnet/architecture/blazor-for-web-forms-developers/architecture-comparison&#34;&gt;https://docs.microsoft.com/en-us/dotnet/architecture/blazor-for-web-forms-developers/architecture-comparison&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;我把消息发群里，大家开始回忆曾经用过的方法，包括ViewState，GridView，IsPostBack，masterpage，repeater，这些技术确实都是一代人的回忆。&lt;/p&gt;
&lt;p&gt;不过认真回想，微软的WwebFrom的理念是超前的， 只不过碍于当时的技术发展, 只能做成那样，后来的UI框架其实都给予它的思想。&lt;/p&gt;
&lt;p&gt;“技术会落后，思想传承”，微软的技术从WebForm到MVC，一直到一直到Blazor，使用的WebUI的组件技术一直都没有改变，果然是汇集世界一流软件工程师的公司。&lt;/p&gt;</description>
    </item>
    <item>
      <title>.NET 6 Preview 5 正式发布，并且Visual Studio 2022 Preview 1也发布了</title>
      <link>https://dodoro.chouxiangpai.com/archives/1461/</link>
      <pubDate>Fri, 18 Jun 2021 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1461/</guid>
      <description>&lt;p&gt;微软具有里程碑意义的Visual Studio 2022 Preview 1已经正式发布，虽然没有增加新功能，但是这个IDE重点支持64位。与此同时，微软也发布了.NET 6 Preview 5。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://devblogs.microsoft.com/visualstudio/visual-studio-2022-preview-1-now-available/&#34;&gt;https://devblogs.microsoft.com/visualstudio/visual-studio-2022-preview-1-now-available/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-5/&#34;&gt;https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-5/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://devblogs.microsoft.com/dotnet/announcing-net-maui-preview-5/&#34;&gt;https://devblogs.microsoft.com/dotnet/announcing-net-maui-preview-5/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;微软在曾经在4月份在官方的博客文章种宣布了VS2022将会第一次支持64位，不再局限于4GB的内存限制，通过Windows上的64位的Visual Studio，你可以打开，编辑、运行和调试非常复杂的解决方案。&lt;/p&gt;
&lt;p&gt;微软通过一个Gif视频展示64位的优势，最新版本的Visual Studio 2022可以轻松打开包含约1600个项目和大约300000个文件的解决方案。&lt;/p&gt;
&lt;p&gt;微软在6月17日的文章 Visual Studio 2022 Preview 1 now available!，关键目标是测试和调整新 64 位平台的可扩展性！这是一个巨大的变化，影响到IDE的每一个部分。微软呼吁早期采用者开发者帮助开展这项工作，称&amp;quot;我们需要您的反馈&amp;quot;。VS 2019 功能不包括在预览 1：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Web实时预览
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;仪器分析仪&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Azure &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;云服务项目支持&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;T-SQL &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;调试器&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Web负载测试和测试控制器/&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;测试代理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Azure数据湖
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Coded界面测试
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DotFuscator
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;内置&lt;/span&gt; IDE &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;集成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;智能提示的代码查找并替换&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;64 位版本Visual Studio 2022 Preview 1 三个版本的早期版本（社区、专业版和企业版） ，现在已经可以下载了：&lt;a href=&#34;https://visualstudio.microsoft.com/zh-hans/vs/preview/vs2022/&#34;&gt;https://visualstudio.microsoft.com/zh-hans/vs/preview/vs2022/&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>.NET 6 Preview 4中.NET Core的更新内容</title>
      <link>https://dodoro.chouxiangpai.com/archives/1413/</link>
      <pubDate>Tue, 08 Jun 2021 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1413/</guid>
      <description>&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;原文：&lt;/span&gt;bit.ly/&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;wFqDy9
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;作者：&lt;/span&gt;Daniel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;译者：王亮&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;.NET 6 预览版 4 现已发布，其中包括对 ASP.NET Core 的许多新改进。&lt;/p&gt;
&lt;p&gt;下面是此次预览版中 ASP.NET Core 的更新内容：&lt;/p&gt;
&lt;h2 id=&#34;1-开始使用&#34;&gt;1 开始使用&lt;/h2&gt;
&lt;p&gt;要开始使用 .NET 6 Preview 4 中的 ASP.NET Core，请安装 .NET 6 SDK[1]。&lt;/p&gt;
&lt;p&gt;如果你在 Windows 上使用 Visual Studio，我们建议安装 Visual Studio 2019 16.11 的最新预览版。如果你在 macOS 上，我们建议安装 Visual Studio 2019 for Mac 8.10 的最新预览版。&lt;/p&gt;
&lt;h2 id=&#34;2-升级一个现有的项目&#34;&gt;2 升级一个现有的项目&lt;/h2&gt;
&lt;p&gt;要将一个现有的 ASP.NET Core 应用程序从 .NET 6 Preview 3 升级到.NET 6 Preview 4。&lt;/p&gt;
&lt;p&gt;将所有 Microsoft.AspNetCore. &lt;em&gt;引用包更新为 6.0.0-preview.4.&lt;/em&gt;。&lt;/p&gt;
&lt;p&gt;更新所有 Microsoft.Extensions. &lt;em&gt;引用包更新为 6.0.0-preview.4.&lt;/em&gt;。&lt;/p&gt;
&lt;p&gt;请参阅 .NET 6 中 ASP.NET Core 的完整中断变化列表[2]。&lt;/p&gt;</description>
    </item>
    <item>
      <title>社区正式发布.NET 6 Preview4</title>
      <link>https://dodoro.chouxiangpai.com/archives/1267/</link>
      <pubDate>Wed, 26 May 2021 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1267/</guid>
      <description>&lt;p&gt;时间过得真快，.NET 5我还没有来得及研究，眼看.NET 6的正式版本马上就要来了，我一直期待这个版本，因为这是LTS版本，我们团队会迁移到这个版本上来。&lt;/p&gt;
&lt;p&gt;社区一直在不断推进.NET 6的可用性，Build 2021大会发布了Preview4，这个版本更新很大，可能与最终的版本相差不大，，正式发布RC版本是在8月份，正式发布RTM版本是在11月 ，到时后.NET正式完成.NET Framwork和.NET Core以及Mono的功能统一，还是非常值得期待的。&lt;/p&gt;
&lt;p&gt;新产品功能：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;System.Text.Json support &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; IAsyncEnumerable
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;System.Text.Json: Writable DOM Feature
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Microsoft.Extensions.Logging compile-time source generator
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;System.Linq enhancements
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Significantly improved FileStream performance &lt;span style=&#34;color:#66d9ef&#34;&gt;on&lt;/span&gt; Windows
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Enhanced Date, Time and Time Zone support
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CodeGen
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.NET Diagnostics: EventPipe &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; Mono and Improved EventPipe Performance
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IL trimming
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Single-file publishing
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CLI install of .NET &lt;span style=&#34;color:#ae81ff&#34;&gt;6&lt;/span&gt; SDK Optional Workloads
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Built-&lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; SDK version checking
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CLI Templates (dotnet &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;另外，还有.NET MAUI或多平台应用UI ：允许开发人员构建适用于Windows、MacOS、ios 和android的应用程序，共享单一代码库和模板。 ASP.NET Blazor混合应用程序：帮助开发人员构建基于Web的跨平台桌面体验，从而利用本机设备功能。 对ARM的加强支持：包括 Silicon 和ARM64支持。&lt;/p&gt;</description>
    </item>
    <item>
      <title>[转]“开源、共享、创新” 2020 中国.NET开发者大会</title>
      <link>https://dodoro.chouxiangpai.com/archives/1272/</link>
      <pubDate>Tue, 05 Jan 2021 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1272/</guid>
      <description>&lt;h2 id=&#34;2020年中国net开发&#34;&gt;2020年中国.NET开发&lt;/h2&gt;
&lt;p&gt;在2019年上海中国.NET开发者大会的基础上，2020年12月19日 继续以“开源、共享、创新” 为主题的第二届中国 .NET 开发者峰会（.NET Conf China 2020）在苏州人工智能智能产业创新中心拉开帷幕。微软云（Microsoft Azure）和葡萄城作为本次峰会白金赞助，明源云作为银牌赞助，朝夕教育作为铜牌赞助，泰链智能和递易智能作为星牌赞助，还有很多合作伙伴给予了峰会大力支持！本次大会以线下城市苏州为中心，覆盖北京、上海、深圳、广州、长沙、成都、徐州、山东、西安、武汉等地区，是中国 .NET 开发者的大聚会，今年由于疫情的特殊原因，组委会特意控制大会的参与人数为300人，加强线上直播方便全国的开发者参与，在CSDN和思否的战略媒体合作和线上大会直播支持下，线下参会人数突破了400人（含讲师，志愿者及合作伙伴），CSDN和思否线上直播累计触达突破40万人次。&lt;/p&gt;
&lt;p&gt;除了大会外，我们在会前（12月18日）安排了 .NET Conf Eve（带着大家提前了解大会细节），在大会当天（12月19日）安排了采访环节同步直播，通过采访大会讲师，合作伙伴，志愿者，观众等从不同维度报道大会盛况。第二天（12月20日）特别安排了 Blazor 及 NCF 工作坊。让对Coding感兴趣的伙伴们带上电脑，沉浸式现场开发。&lt;/p&gt;
&lt;p&gt;本次峰会完全由来自.NET技术圈开发者们的志愿者进行组织。从大家看到的精美海报，到活动现场的许多志愿者、主持人，这些都是来自对.NET 技术充满热情的优秀开发者们；尤其是那些为大家带来精彩内容的老师们，他们有时候为了PPT上的每一页内容，需要花费大量的业余时间；除了这些之外，我们还能看到许多细节，如那些设计精美的PPT、那些设计精良的文化衫、甚至还有那些小巧玲珑的贴纸图案、海报，无一不是来源于社区志愿者的精心奉献。&lt;/p&gt;
&lt;h2 id=&#34;群英集聚力求卓越&#34;&gt;群英集聚，力求卓越&lt;/h2&gt;
&lt;p&gt;来自全国各地的超过400名 .NET 开发者受邀参与这次大会，超过40万人次通过直播参与大会，来自各领域的40多位资深讲师就 .NET Core ，跨平台，微服务、K8S、机器学习、大数据、IoT、混沌工程、DevOps以及自主创新等当前最为热门的科技专题做了多场精彩绝伦的演讲，与全国的 .NET 开发者一起共享技术盛宴。如此规模的中国 .NET 开发者峰会能够成功举办离不开社区伙伴、企业伙伴和志愿者的多方努力，他们共同携手，打造了中国最具影响力的 .NET 开发者峰会。&lt;/p&gt;
&lt;h2 id=&#34;开源共享创新&#34;&gt;“开源、共享、创新”&lt;/h2&gt;
&lt;p&gt;这次大会的主题是“开源 共享 创新”， 这象征着中国 .NET 社区走向开放、走向世界、走向辉煌的未来趋势和历史使命。曾经， .NET 技术的发展只能依靠微软，而今，要依靠的不仅仅是微软，更是真正的社区力量。6年来，在微软 CEO 萨提亚·纳德拉的带领下，微软发生了巨大的变化，微软通过成立 .NET 基金会(dotnetfoundation.org)全面扶持开源项目。据 GitHub 最新发布的年度报告显示，按贡献者列出的增长最快的开源项目，用于跨语言和平台构建应用程序和网站的工具包和框架在今年有了显著的增长，全球.NET开发者500万，其中200万已经使用.NET Core, 在中国也有50万.NET开发者，.NET Core开发者也有20万。与此同时， .NET 社区在中国也发生了巨大变革，互联网大时代的一波波浪潮或许不会再滚滚而前，但产业互联网的大势已经拉开，而这意味着未来的时代将会成为 .NET 开发者们的主场，在 github/gitee 上活跃着很多中国的.NET 开源开发者组织，例如NCC、盛派开发者、Abp，龙芯.NET等。龙芯团队正式在大会上发布了龙芯.NET。&lt;/p&gt;
&lt;p&gt;本次峰会持续两天，议题涵盖：云原生应用开发、 .NET 在云服务、游戏开发、区块链、大数据、机器学习、物联网的应用等。图文直播曝光量22697人次，主题演讲视频直播高峰在线观看10万人次。&lt;/p&gt;
&lt;h2 id=&#34;大会亮点-大神云集&#34;&gt;大会亮点 大神云集&lt;/h2&gt;
&lt;p&gt;.NET 社区汇集全球富有实践经验的讲师、开源贡献者，来自微软、葡萄城、龙芯、明源云、蔚来汽车等超40位.NET领域权威技术专家齐聚苏州。大会开始前，来自苏州工业园区的领导** 进行了大会致辞，微软全渠道事业部CTO徐明强博士为我们带来《.NET,应您所想的应用开发平台》从.NET生态动力、.NET在全球影响力、中国.NET社区和.NET5的技术提升等多个方面微软近年来在.NET5和开源生态上做出的努力，微软大中华区Azure事业部总经理林家伟还带来了 远在美国的Julia Liuson 和 的大咖视频，龙芯.NET项目和JVM项目负责人敖琪在大会上正式发布了龙芯.NET, 来自日本东京的桂素伟线上直播分享了他基于K8S 复杂项目交付等。&lt;/p&gt;</description>
    </item>
    <item>
      <title>国产化系统下的.NET Core实践(Topic：NET Core Practice for Localization  Systems)</title>
      <link>https://dodoro.chouxiangpai.com/archives/1254/</link>
      <pubDate>Sun, 20 Dec 2020 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1254/</guid>
      <description>&lt;p&gt;这两三天一直在苏州，参加2020年中国.NET开发者大会，我第一次以讲师的身份参加技术大会，以前都是作为听众，这一次也是代表公司出去做技术交流，为此做了不少准备工作。&lt;/p&gt;
&lt;p&gt;我从大学就是用C#和.NET，一直默默关注C#开源社区，2010年玩过Mono，2013年采用Xamarin开发Android应用，从2019年起开始带来团队实践.NET Core项目，公司核心的产品已经迁移到.NET Core，今年以来带领团队完成国产化系统下的.NET Core项目改造。&lt;/p&gt;
&lt;p&gt;我的演讲主题是国产化系统下的.NET Core实践经验和心得，这是我们过去一年多以来的实践和心得，主要包括以下几个重点：&lt;/p&gt;
&lt;p&gt;1、国产系统现状和要求，包括CPU、操作系统和中间件的要求，如何突破目前中间件对Java的特殊保护，到底是用java重写还是迁移.NET  Core，给出实用的迁移建议；&lt;/p&gt;
&lt;p&gt;我的建议是“尽量不要重复造轮子，坚持使用DotNet”，而解决方案是如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;file&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1254/images/image-1621927132986.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;2、国产化各种准备工作，重点技术预研，特别是现有系统的各个类库对.NET  Core的支持情况，最终做出技术评估；&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;file&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1254/images/image-1621927265906.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;3、项目迁移工作，除了按照官方要求迁移之外，还需要考虑系统在各个平台的可移植情况，我们迁移过程中遇到的问题和解决办法；&lt;/p&gt;
&lt;p&gt;1）、现有系统的各个类库对.NET Core的支持情况：官方API和类库基本没有问题；重点注意第三方类库，比如Lucence.NET，Zip解析等 2）、客户迁移的要求情况：如果服务器CPU架构必须是申威，要重视；如果是龙芯可以拖一拖，但是其实可以和客户提系统支持的要求。&lt;/p&gt;
&lt;p&gt;4、项目测试，模拟各种国产CPU搭建测试环境，并对系统进行测试；&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;file&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1254/images/image-1621927402911.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;5、国产专用服务器上的系统部署实践，部署过程中的问题和解决方案。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;file&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1254/images/image-1621927432006.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;结语：开源，自由、开放的社区是创新的力量之源，这也是互联网诞生的初心。今天主持人说到会90后超过一半，还是很希望90后、00后和未来者们都知道什么是网站URL地址，都知道怎么使用搜索引擎，不要只是被困在算法和移动应用之中。&lt;/p&gt;</description>
    </item>
    <item>
      <title>安可国产化系统下的DotNet Core实践</title>
      <link>https://dodoro.chouxiangpai.com/archives/1086/</link>
      <pubDate>Sun, 27 Sep 2020 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1086/</guid>
      <description>&lt;p&gt;这两个月来带领团队实践安可国产化系统下的DotNet Core，我们积累了一些经验，这里做一下记录。&lt;/p&gt;
&lt;h2 id=&#34;1dotnet-core可以在安可下面运行吗&#34;&gt;1、DotNet Core可以在安可下面运行吗？&lt;/h2&gt;
&lt;p&gt;首先，答案是肯定的。目前除了龙芯架构的服务器不支持DotNet Core（龙芯团队已经在努力，他们预计会尽快支持DotNet Core的下一个版本），其他所有平台架构的都支持，目前我们实际客户的操作系统有：ARM64(包括其扩展Aarch64)、X64，这些服务器包括飞腾、华为鲲鹏等国产服务器。&lt;/p&gt;
&lt;h2 id=&#34;2迁移麻烦吗工作量有多大&#34;&gt;2、迁移麻烦吗？工作量有多大？&lt;/h2&gt;
&lt;p&gt;非常靠谱。DotNet兼容性做得非常好，只要是它支持的架构的服务器，都可以很好地运行。 &lt;img alt=&#34;file&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1086/images/image-1606442212707.png&#34;&gt; 唯一需要考虑的是，如果项目用到的第三方库比较多，需要逐个验证迁移工作，大部分流行的第三方库都已经支持DotNet Core。&lt;/p&gt;
&lt;h2 id=&#34;3java重写还是迁移&#34;&gt;3、Java重写还是迁移？&lt;/h2&gt;
&lt;p&gt;除非你们团队已经没有DotNet开发人员了，否则千万不要用Java重写，一方面是工作量大，另一方面是java的项目换到安可环境也是需要做很多适配工作。 而且我可以很负责任地说：DotNet Core的运行效率超级棒！几乎可以用飞快来形容。&lt;/p&gt;
&lt;h2 id=&#34;4迁移过程中有哪些经验&#34;&gt;4、迁移过程中有哪些经验？&lt;/h2&gt;
&lt;h4 id=&#34;代码经验&#34;&gt;代码经验&lt;/h4&gt;
&lt;p&gt;我们的代码几乎无缝转移过去，唯一的地方就是全文检索lucene.net，现在这个项目已经有更新，发了十几个bata版本，我认为可以用，所以升级过来了。 另外，安可要求只能用国产达梦数据库，需要做适配，还好这些数据库基本都是开源改过来的，适配不是问题，就是一些日期等细节需要主义。&lt;/p&gt;
&lt;h4 id=&#34;服务器经验&#34;&gt;服务器经验&lt;/h4&gt;
&lt;p&gt;我们第一个项目是迁移到政务系统，要求非常严格，有专用的服务器。我们先是在通用测试服务器下（Aarch64架构CPU，中标麒麟操作系统和银河麒麟操作系统），运行起来没有任何问题。后来在专用服务器下，架构和CPU都不变，但是专用服务器涉密，所以不能随意使用命令安装库，也不能更新系统库，只需要找到合适的包用专用服务器工具安装就可以，如果是系统库文件，就让厂商安装。&lt;/p&gt;
&lt;h2 id=&#34;5最大的问题是什么&#34;&gt;5、最大的问题是什么？&lt;/h2&gt;
&lt;p&gt;最大的问题是，安可要求服务器必须通过中间件安装系统，这些中间件其实就是web服务器，比如金蝶之类的，这里很崩溃，因为这些国产中间件只支持java,其实就是另外一个tomcat，我也认为他们基于开源改造。 后来我们的解决办法是，前后端分离，通过金蝶发布前端web站点，后端启动5000端口提供DotNet Core服务，这个并不违法安可要求。DotNet Core基于最开放的MIT开源协议，比java开放多了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>关于IT国产化盛宴的几点感想</title>
      <link>https://dodoro.chouxiangpai.com/archives/1083/</link>
      <pubDate>Mon, 24 Aug 2020 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1083/</guid>
      <description>&lt;p&gt;这三周来牺牲社交时间，我亲自出马、带着团队三名精干主力在“中标麒麟龙芯”下编译.Net Core 3.0、并调试程序，编译通过但Bug太多，以失败而告终，最后放弃这个平台，这不是我们的问题，这是龙芯团队的问题，他们的CPU对彻底开源的.NET支持台还很差(也许明年会好些)，不过目前我们支持“中标麒麟兆芯”，这个平台也完全符合安可要求。&lt;/p&gt;
&lt;p&gt;从我接触到的情况来看，目前最鸡血的是那些国字号相关的企业，不过如果不涉密，但大部分也只是买来应付检查，因为国产服务器真的是几乎不能用。还有一些比较聪明的单位，直接购买云国产操作系统，但是这些国产云操作系统就是一个幌子，因为它们也是跑在“洋芯片”、寄生在“洋软件”下面而已。&lt;/p&gt;
&lt;p&gt;Java的码农请别吐槽C#，两门语言都是“美帝”发明的开发语言哦，要说彻底支持符合国产要求，别忘了Java的SDK还有专利费，而且Java的拥有者Oracle告谷歌的侵权诉讼案还没结束呢，哈哈。&lt;/p&gt;
&lt;p&gt;另外，很想对那些摇着民族主义旗号大喊国产的人，有本事从应用软件到开发语言彻底国产，还有哦，wifi现在澳洲公司还在收专利费、互联网也是MIT的发明、Apache基金会的总部现在还设在美国的马里兰州……这只是一场分蛋糕大盛宴，曲终人必散，苦的是那些重复造轮子的码农，还好我们已经脱离苦海。&lt;/p&gt;</description>
    </item>
    <item>
      <title>[转]基于DDD的微服务设计和开发实战</title>
      <link>https://dodoro.chouxiangpai.com/archives/1075/</link>
      <pubDate>Tue, 16 Jun 2020 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1075/</guid>
      <description>&lt;p&gt;你是否还在为微服务应该拆多小而争论不休？到底如何才能设计出收放自如的微服务？怎样才能保证业务领域模型与代码模型的一致性？或许本文能帮你找到答案。&lt;/p&gt;
&lt;p&gt;本文是基于 DDD 的微服务设计和开发实战篇，通过借鉴领域驱动设计思想，指导微服务项目团队进行设计和开发（理论篇详见《当中台遇上 DDD，我们该如何设计微服务？》）。本文包括三部分内容：第一部分讲述领域驱动设计基本知识，包括：分层架构、服务视图、数据视图和领域事件发布和订阅等；第二部分讲述微服务设计方法、过程、模板、代码目录、设计原则等内容；最后部分以一个项目为例讲述基于 DDD 的微服务设计过程。&lt;/p&gt;
&lt;h2 id=&#34;目标&#34;&gt;目标&lt;/h2&gt;
&lt;p&gt;本文采用 DDD（领域驱动设计）作为微服务设计指导思想，通过事件风暴建立领域模型，合理划分领域逻辑和物理边界，建立领域对象及服务矩阵和服务架构图，定义符合 DDD 分层架构思想的代码结构模型，保证业务模型与代码模型的一致性。通过上述设计思想、方法和过程，指导团队按照 DDD 设计思想完成微服务设计和开发。&lt;/p&gt;
&lt;p&gt;通过领域模型和 DDD 的分层思想，屏蔽外部变化对领域逻辑的影响，确保交付的软件产品是边界清晰的微服务，而不是内部边界依然混乱的小单体。在需求和设计变化时，可以轻松的完成微服务的开发、拆分和组合，确保微服务不易受外部变化的影响，并稳定运行。&lt;/p&gt;
&lt;h2 id=&#34;适用范围&#34;&gt;适用范围&lt;/h2&gt;
&lt;p&gt;本文适用于按照 DDD 设计方法进行微服务设计和开发的项目及相关人员。&lt;/p&gt;
&lt;p&gt;以下情况不适用：&lt;/p&gt;
&lt;p&gt;“我们的目标是按期盖出一栋大楼来，不要跟我提什么方法，有这啰嗦的时间，还不如抓紧点时间搬砖，把楼给我快点盖好！”。&lt;/p&gt;
&lt;p&gt;“我的工作就是让软件运行起来，能工作一切就 OK！我不需要那么多约束，什么设计方法、扩展性、业务变化、领域模型、响应能力与我无关。别耽误工期啦！先上线再说！”。&lt;/p&gt;
&lt;p&gt;“好的软件是自己演进出来的，我们不需要设计！”。&lt;/p&gt;
&lt;p&gt;哈哈，开个玩笑啦！其实设计不会花太多时间的！&lt;/p&gt;
&lt;h2 id=&#34;正文内容&#34;&gt;正文内容&lt;/h2&gt;
&lt;p&gt;不耽误大家时间了，言归正传。 &lt;a href=&#34;images/46aa321555b55a8f11943da6f9f5d9ed.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1075/images/46aa321555b55a8f11943da6f9f5d9ed-259x300.png&#34;&gt;&lt;/a&gt; DDD 分层架构视图 DDD 分层架构包括：展现层、应用层、领域层和基础层。&lt;/p&gt;
&lt;p&gt;基于DDD的微服务设计和开发实战&lt;/p&gt;
&lt;p&gt;DDD 分层架构各层职能如下：&lt;/p&gt;
&lt;p&gt;展现层 展现层负责向用户显示信息和解释用户指令。&lt;/p&gt;
&lt;p&gt;应用层 应用层是很薄的一层，主要面向用户用例操作，协调和指挥领域对象来完成业务逻辑。应用层也是与其他系统的应用层进行交互的必要渠道。应用层服务尽量简单，它不包含业务规则或知识，只为下一层的领域对象协调任务，使它们互相协作。应用层还可进行安全认证、权限校验、分布式和持久化事务控制或向外部应用发送基于事件的消息等。&lt;/p&gt;
&lt;p&gt;领域层 领域层是软件的核心所在，它实现全部业务逻辑并且通过各种校验手段保证业务正确性。它包含业务所涉及的领域对象（实体、值对象）、领域服务以及它们之间的关系。它负责表达业务概念、业务状态以及业务规则，具体表现形式就是领域模型。&lt;/p&gt;
&lt;p&gt;基础层 基础层为各层提供通用的技术能力，包括：为应用层传递消息、提供 API 管理，为领域层提供数据库持久化机制等。它还能通过技术框架来支持各层之间的交互。&lt;/p&gt;
&lt;p&gt;服务视图 微服务内的服务视图 微服务内有 Facade 接口、应用服务、领域服务和基础服务，各层服务协同配合，为外部提供服务。 &lt;a href=&#34;images/99fd33d90786205dd4eea94ff66b7aa8.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1075/images/99fd33d90786205dd4eea94ff66b7aa8-300x158.jpg&#34;&gt;&lt;/a&gt; 基于DDD的微服务设计和开发实战&lt;/p&gt;
&lt;p&gt;1、接口服务 接口服务位于用户接口层，用于处理用户发送的 Restful 请求和解析用户输入的配置文件等，并将信息传递给应用层。&lt;/p&gt;
&lt;p&gt;2、应用服务 应用服务位于应用层。用来表述应用和用户行为，负责服务的组合、编排和转发，负责处理业务用例的执行顺序以及结果的拼装。&lt;/p&gt;
&lt;p&gt;应用层的服务包括应用服务和领域事件相关服务。&lt;/p&gt;
&lt;p&gt;应用服务可对微服务内的领域服务以及微服务外的应用服务进行组合和编排，或者对基础层如文件、缓存等数据直接操作形成应用服务，对外提供粗粒度的服务。&lt;/p&gt;
&lt;p&gt;领域事件服务包括两类：领域事件的发布和订阅。通过事件总线和消息队列实现异步数据传输，实现微服务之间的解耦。&lt;/p&gt;
&lt;p&gt;3、领域服务 领域服务位于领域层，为完成领域中跨实体或值对象的操作转换而封装的服务，领域服务以与实体和值对象相同的方式参与实施过程。&lt;/p&gt;
&lt;p&gt;领域服务对同一个实体的一个或多个方法进行组合和封装，或对多个不同实体的操作进行组合或编排，对外暴露成领域服务。领域服务封装了核心的业务逻辑。实体自身的行为在实体类内部实现，向上封装成领域服务暴露。&lt;/p&gt;
&lt;p&gt;为隐藏领域层的业务逻辑实现，所有领域方法和服务等均须通过领域服务对外暴露。&lt;/p&gt;
&lt;p&gt;为实现微服务内聚合之间的解耦，原则上禁止跨聚合的领域服务调用和跨聚合的数据相互关联。&lt;/p&gt;
&lt;p&gt;4、基础服务 基础服务位于基础层。为各层提供资源服务（如数据库、缓存等），实现各层的解耦，降低外部资源变化对业务逻辑的影响。&lt;/p&gt;
&lt;p&gt;基础服务主要为仓储服务，通过依赖反转的方式为各层提供基础资源服务，领域服务和应用服务调用仓储服务接口，利用仓储实现持久化数据对象或直接访问基础资源。&lt;/p&gt;
&lt;p&gt;微服务外的服务视图&lt;/p&gt;</description>
    </item>
    <item>
      <title>关于龙芯对.NET Core支持的一些进展</title>
      <link>https://dodoro.chouxiangpai.com/archives/1048/</link>
      <pubDate>Thu, 04 Jun 2020 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/1048/</guid>
      <description>&lt;p&gt;今天邮箱收到github的issue更新提醒，就在昨天，龙芯(loongson)的码农们已经让.NET Core 3.1的FlightFinder例子在MIPS64跑起来了，但是更复杂的程序还得继续改，预计在今年年底加入.NET 5.x（谨慎乐观）。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;images/image-1591257074861.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/1048/images/image-1591257074861-291x300.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;.NET 本身是完全开源，比Java还要开放（想想现在Google和Oracle关于Java的专利案还没结束呢），但是MS官方已经明确.NET Core和未来的版本不会支持MIPS的CPU指令集架构（龙芯就是用这个架构级），因为太小众了，要实现就得社区自己去写。&lt;/p&gt;
&lt;p&gt;龙芯的团队从去年11月份跑Hello World到现在做了不少工作，看社区里的几位工程师也很努力，最终应该会支持（大概率版本会落后），这个值得肯定。但是，对于龙芯来说，社区和生态太难了，要不是去年“安可”要求，估计也不会刺激他们去支持.NET Core。好的结局是“安可”推广成功，gov和army里无关紧要的系统都用（核心系统因为复杂度，怕是很难用上）。&lt;/p&gt;
&lt;p&gt;最最要命的是：技术发展太快了，龙芯所支持的服务器市场现在已经完全靠云计算了，这些云计算不可能采用龙芯等国产芯片，这也是为什么阿里要造出概念化的飞天国产云系统的原因——为了政策需要啊！&lt;/p&gt;
&lt;p&gt;对于科学技术，我坚信市场化和资本化是最有效的驱动力，最近的SpaceX是又一个有力佐证。努力的人很多，最后大都做了前浪。&lt;/p&gt;</description>
    </item>
    <item>
      <title>【转】.NET内存管理五大基础知识</title>
      <link>https://dodoro.chouxiangpai.com/archives/948/</link>
      <pubDate>Mon, 01 Jun 2020 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/948/</guid>
      <description>&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;以下文章来源于DotNET技术圈&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;，&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;作者RICKY&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;LEEKS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;1小对象怎么处理的&#34;&gt;1.小对象怎么处理的？&lt;/h2&gt;
&lt;p&gt;小型.NET对象被分配到小型对象堆（SOH）上。其中有3种：第0代，第1代和第2代。对象根据其寿命向上移动。&lt;/p&gt;
&lt;p&gt;将新对象放在Gen 0上。当Gen 0充满时，.NET垃圾收集器（GC）运行，处理不再需要的对象，并将其他所有内容移至Gen1。如果Gen 1充满，则GC再次运行，也可以将Gen 1中的对象移动到Gen 2中。&lt;/p&gt;
&lt;p&gt;当Gen 2变满时，将发生GC完全运行。这将清除不需要的Gen 2对象，将Gen 1对象移至Gen 2，然后将Gen 0对象移至Gen 1，最后清除所有未引用的内容。每次运行GC之后，都会压缩受影响的堆，以将仍在使用的内存保持在一起。&lt;/p&gt;
&lt;p&gt;这种代代相传的方法可确保事情高效运行-耗时的压缩过程仅在绝对必要时才会发生。&lt;/p&gt;
&lt;p&gt;注意：如果您在Gen 2中看到大量的内存，则表明内存已被保留很长时间，并且可能存在内存问题。这是内存分析工具可以派上用场的地方。&lt;/p&gt;
&lt;h2 id=&#34;2较大的对象会怎样&#34;&gt;2.较大的对象会怎样？&lt;/h2&gt;
&lt;p&gt;大于85 KB的对象被分配到大对象堆（LOH）。由于复制大块内存的开销，它们没有被压缩。当发生完整的GC时，未使用的LOH对象的地址范围将记录在可用空间分配表中。&lt;/p&gt;
&lt;p&gt;分配新对象后，将在此可用空间表中检查足以容纳该对象的地址范围。如果存在，则将对象分配到那里，如果不存在，则将对象分配到下一个可用空间。&lt;/p&gt;
&lt;p&gt;由于对象不太可能是空地址范围的确切大小，因此对象之间几乎总是会留有小块内存，从而导致碎片。如果这些块小于85 KB，则根本没有重用的可能性。因此，随着分配需求的增加，即使碎片空间仍然可用，也会保留新的段。&lt;/p&gt;
&lt;p&gt;此外，当需要分配大对象时，.NET还是倾向于将对象附加到末尾，而不是运行昂贵的Gen 2 GC。这对性能有好处，但是是导致内存碎片的重要原因&lt;/p&gt;
&lt;h2 id=&#34;3垃圾收集器可以在不同的模式下运行以优化性能&#34;&gt;3.垃圾收集器可以在不同的模式下运行以优化性能&lt;/h2&gt;
&lt;p&gt;.NET通过为GC提供多种模式来解决性能与堆效率之间的权衡问题。&lt;/p&gt;
&lt;p&gt;工作站模式为用户提供了最大的响应速度，并减少了由于GC造成的暂停。它可以作为“并发”或“非并发”运行，指的是运行GC的线程。默认值为并发，它为GC使用单独的线程，因此应用程序可以在GC运行时继续执行。&lt;/p&gt;
&lt;p&gt;服务器模式可为服务器环境提供最大的吞吐量，可伸缩性和性能。在服务器模式下，段大小和生成阈值通常比工作站模式大得多，这反映了对服务器的更高要求。&lt;/p&gt;
&lt;p&gt;服务器模式在多个线程上并行运行垃圾回收，为每个逻辑处理器分配一个单独的SOH和LOH，以防止线程相互干扰。&lt;/p&gt;
&lt;p&gt;.NET框架提供了一种交叉引用机制，因此对象仍然可以在堆之间相互引用。但是，由于应用程序响应能力不是服务器模式的直接目标，因此在GC期间，所有应用程序线程都将被挂起。&lt;/p&gt;
&lt;h2 id=&#34;4引用不足会在性能和内存效率之间折衷&#34;&gt;4.引用不足会在性能和内存效率之间折衷&lt;/h2&gt;
&lt;p&gt;弱对象引用了GC根的替代来源，使您可以保留对象，同时在GC需要时可以收集对象。它们是代码性能和内存效率之间的折衷。创建对象需要占用CPU时间，但保持加载状态需要占用内存。&lt;/p&gt;
&lt;p&gt;弱引用特别适用于大型数据结构。例如，假设您有一个允许用户浏览大型数据结构的应用程序，他们可能会返回其中的一些数据。您可以将任何强引用转换为他们浏览的结构为弱引用。如果用户返回到这些结构，则可以使用它们，但如果没有，GC可以根据需要回收内存。&lt;/p&gt;
&lt;h2 id=&#34;5对象固定可以创建在托管和非托管代码之间传递的引用&#34;&gt;5.对象固定可以创建在托管和非托管代码之间传递的引用&lt;/h2&gt;
&lt;p&gt;.NET使用一种称为GCHandle的结构来跟踪堆对象。GCHandle可用于在托管域和非托管域之间传递对象引用，.NET维护一个GCHandles表以实现此目的。GCHandle有四种类型，包括固定的，用于将对象固定在内存中的特定地址。&lt;/p&gt;
&lt;p&gt;对象固定的主要问题是它可能导致SOH碎片化。如果将对象固定在GC期间，则根据定义，该对象无法重定位。根据您使用固定的方式，它会降低压缩的效率，在堆中留下间隙。避免这种情况的最佳策略是在很短的时间内锁定，然后释放。&lt;/p&gt;</description>
    </item>
    <item>
      <title>用Windbg来分析.Net程序的dump</title>
      <link>https://dodoro.chouxiangpai.com/archives/954/</link>
      <pubDate>Mon, 01 Jun 2020 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/954/</guid>
      <description>&lt;p&gt;用Windbg来分析.Net程序的dump&lt;/p&gt;
&lt;h2 id=&#34;1-什么是windbg&#34;&gt;1. 什么是Windbg&lt;/h2&gt;
&lt;p&gt;WinDbg是微软发布的一款相当优秀的源码级(source-level)调试工具，可以用于Kernel模式调试和用户模式调试，还可以调试Dump文件。 WinDbg是微软很重要的诊断调试工具: 可以查看源代码、设置断点、查看变量, 查看调用堆栈及内存情况。 Dump文件是进程的内存镜像, 可以把程序的执行状态通过调试器保存到dump文件中&lt;/p&gt;
&lt;h2 id=&#34;2-windbg可以解决以下问题&#34;&gt;2. Windbg可以解决以下问题&lt;/h2&gt;
&lt;p&gt;◆ 内存高 ◆ CPU高 ◆ 程序异常 ◆ 程序Hang死&lt;/p&gt;
&lt;h2 id=&#34;3-使用windbg进行调试分析的两种方式&#34;&gt;3. 使用windbg进行调试分析的两种方式&lt;/h2&gt;
&lt;p&gt;使用windbg调试器attach到需要调试的进程。(会暂停进程的运行) 抓取进程的dump文件，使用windbg分析dump&lt;/p&gt;
&lt;p&gt;下载地址:&lt;a href=&#34;https://technet.microsoft.com/en-us/sysinternals/dd996900&#34;&gt;https://technet.microsoft.com/en-us/sysinternals/dd996900&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;下载之后为压缩包，将文件解压。通过dos命令来生成dump文件。下面为一条语句为示例&lt;/p&gt;
&lt;p&gt;procdump -ma -c 0 -s 3 -n 2 sqlservr.exe -o E:\dumps\&lt;/p&gt;
&lt;p&gt;这条语句的意思为：当sqkservr.exe这个进程运行时间cpu的占用超过0%，时间超过3秒，则在E:\dumps下生成一个dump文件。一直到生成2个为止。下面为命令介绍&lt;/p&gt;
&lt;p&gt;-ma 生成full dump, 即包括进程的所有内存. 默认的dump格式包括线程和句柄信息. -c 在CPU使用率到达这个阀值的时候, 生成dump文件. -s CPU阀值必须持续多少秒才抓取dump文件. -n 在该工具退出之前要抓取多少个dump文件. -o dump文件保存目录. Sqlservr.exe可替换为进程的ID&lt;/p&gt;</description>
    </item>
    <item>
      <title>看完Orchard Core的一些随感</title>
      <link>https://dodoro.chouxiangpai.com/archives/773/</link>
      <pubDate>Tue, 15 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/773/</guid>
      <description>&lt;p&gt;这个项目的框架是微软顶级工程师的杰作，太牛了，终于理解为什么各类开发IDE都是海外工程师写出来了，框架设计优美、代码精炼、扩展性超强、考虑全面。ps：国内IT软件方面至少落后欧美10年(那些把开源改改就说国产世界第一就别拿来丢脸了)，得益于开源和github，我们才有机会保持这个差距。&lt;/p&gt;
&lt;p&gt;国内对C#和.NET总是有一些误解。比如.NET Core，海外已经用得如火如荼了，社区非常活跃，并且各种新的开发理念和工具极大提高效率。我在BAT写过代码，说实话他们的软件架构理念都是实用为主，并没有从工程学角度去发展，所以只适合特点场景，但是他们垄断中国码农的话语权，导致后来者c#大都被误解。这无形中导致国内软件开发起码落后海外10年。举一个最简单例子，现在大公司也有devops，但是放到中小型公司，他们很难运用bat的这套东西，而阿里云对devops支持太差了，反观aws和azure几乎是完美支持，这里面有国情原因，也有c#被误解的原因。&lt;/p&gt;
&lt;p&gt;我可以毫无客气地说：国内对.net的误解，其实就是落后又自大的一个缩影。看看现在华为、国产软件时不时世界第一的“亩产万金”的论断。&lt;/p&gt;</description>
    </item>
    <item>
      <title>[转]C#语言历史版本特性(C# 1.0到C# 8.0汇总)</title>
      <link>https://dodoro.chouxiangpai.com/archives/758/</link>
      <pubDate>Thu, 10 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/758/</guid>
      <description>&lt;h2 id=&#34;历史版本&#34;&gt;历史版本&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;C#作为微软2000年以后.NET平台开发的当家语言，发展至今具有17年的历史，语言本身具有丰富的特性，微软对其更新支持也十分支持。微软将C#提交给标准组织ECMA，C# 5.0目前是ECMA发布的最新规范，C# 6.0还是草案阶段，C# 7.1是微软当前提供的最新规范。&lt;/p&gt;
&lt;p&gt;这里仅仅列个提纲，由于C# 5.0是具有ECMA标准规范的版本，所以选择C# 5.0作为主要版本学习，并专题学习C# 6.0,7.0版本新特性。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;C#语言规范GitHub库参见：&lt;a href=&#34;https://github.com/dotnet/csharplang&#34;&gt;https://github.com/dotnet/csharplang&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;C#语言路线图及开发中的特性参见： &lt;a href=&#34;https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md&#34;&gt;https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md&lt;/a&gt;&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;语言版本&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;发布时间&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;.NET Framework要求&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;Visual Studio版本&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;C# 1.0&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;2002.1&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;.NET Framework 1.0&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Visual Studio .NET 2002&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;C# 1.1\1.2&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;2003.4&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;.NET Framework 1.1&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Visual Studio .NET 2003&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;C# 2.0&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;2005.11&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;.NET Framework 2.0&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Visual Studio 2005&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;C# 3.0&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;2007.11&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;.NET Framework 2.0\3.0\3.5&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Visual Studio 2008&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;C# 4.0&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;2010.4&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;.NET Framework 4.0&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Visual Studio 2010&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;C# 5.0&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;2012.8&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;.NET Framework 4.5&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Visual Studio 2012\2013&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;C# 6.0&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;2015.7&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;.NET Framework 4.6&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Visual Studio 2015&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;C# 7.0&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;2017.3&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;.NET Framework 4.6.2&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Visual Studio 2017&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;C# 7.1&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;2017.6&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;.NET Framework&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Visual Studio 2017 v15.3预览版&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;C# 8.0&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;待发布&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;.NET Framework 4.7.1&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Visual Studio 2017 v15.7&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;c-10-特性&#34;&gt;C# 1.0 特性&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;第1个版本，编程语言最基础的特性。&lt;/p&gt;</description>
    </item>
    <item>
      <title>关于C#和.NET以及自己未来的一些计划</title>
      <link>https://dodoro.chouxiangpai.com/archives/760/</link>
      <pubDate>Tue, 01 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/760/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;images/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20191014143438.png&#34;&gt;&lt;img alt=&#34;微信图片_20191014143438&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/760/images/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20191014143438-300x158.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这几天把.NETCONF所有的视频都看了一遍，感叹微软的开放力度和对C#及.NET的推进力度。我写过Delphi、VB、C、C++、C#、Object-C、PHP、JAVA、Python，这一路过来总觉得太分散了，很难真正投入到推动一门语言的地步，现在看来，C#是初恋也是最爱，真不能在乱“移情别恋”了。未来最多使用Python进行一些ML（机器学习）涉及的方面的数据工作。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;images/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20191014143444.png&#34;&gt;&lt;img alt=&#34;微信图片_20191014143444&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/760/images/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20191014143444-300x167.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;针对C#和.NET我一定持续关注，而且专注于她，这是工作需要，也是自己的发展需要。&lt;/p&gt;
&lt;p&gt;1、全面梳理C#这门语言，虽然我已经写了12年C#了。&lt;/p&gt;
&lt;p&gt;实际行动：把微软的文档看一遍，把那几本经典的书读完。（2019到2020）&lt;/p&gt;
&lt;p&gt;2、应用.NET Core 3.0及未来版本。&lt;/p&gt;
&lt;p&gt;实际行动：把公司的一个项目做成兼容linux平台。（2019）&lt;/p&gt;
&lt;p&gt;3、研究Orchard Core项目。&lt;/p&gt;
&lt;p&gt;实际行动：把自己的blog都迁移过来。（2019到2020）&lt;/p&gt;
&lt;p&gt;4、研究ABP项目，顺便研究微服务架构和DDD结构。&lt;/p&gt;
&lt;p&gt;实际行动：在公司的一个项目中完成。（2019到2020）&lt;/p&gt;
&lt;p&gt;5、机器学习ML.NET研究和Python&lt;/p&gt;
&lt;p&gt;实际行动：自己建模完成一些数据分析和预测。（2019起步，长期工作）&lt;/p&gt;
&lt;p&gt;6、学习Azure、AWS技术和DevOps&lt;/p&gt;
&lt;p&gt;实际行动：考下AWS证书，并在公司一个项目中完成Azure的DevOps。（2020到2021）&lt;/p&gt;
&lt;p&gt;另外，学习nopCommerce和CSLA .NET两个开源项目的特点，吸收特长；学习Angular和Vue前端框架。&lt;/p&gt;</description>
    </item>
    <item>
      <title>.NET Core 3.0 正式公布</title>
      <link>https://dodoro.chouxiangpai.com/archives/768/</link>
      <pubDate>Wed, 25 Sep 2019 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/768/</guid>
      <description>&lt;p&gt;根据微软博客的介绍，开发者可以面向 Windows、MacOS 以及 Linux 等系统平台&lt;a href=&#34;https://dotnet.microsoft.com/download/dotnet-core/3.0&#34;&gt;下载 .NET Core 3.0&lt;/a&gt; ：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://dotnet.microsoft.com/download/dotnet-core/3.0&#34;&gt;.NET Core 3.0 SDK 与运行时&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://snapcraft.io/dotnet-sdk&#34;&gt;Snap 安装程序&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hub.docker.com/_/microsoft-dotnet-core&#34;&gt;Docker 镜像&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;此外， &lt;a href=&#34;https://devblogs.microsoft.com/aspnet/asp-net-core-and-blazor-updates-in-net-core-3-0/&#34;&gt;ASP .NET Core 3.0&lt;/a&gt;  与  &lt;a href=&#34;https://devblogs.microsoft.com/dotnet/announcing-ef-core-3-0-and-ef-6-3-general-availability/&#34;&gt;EF Core 3.0&lt;/a&gt;  也已经一同发布。 &lt;a href=&#34;https://devblogs.microsoft.com/visualstudio/dot-net-core-support-in-visual-studio-2019-version-16-3/&#34;&gt;Visual Studio 2019 16.3&lt;/a&gt;  与  &lt;a href=&#34;https://devblogs.microsoft.com/visualstudio/visual-studio-2019-for-mac-version-8-3/&#34;&gt;Visual Studio for Mac 8.3&lt;/a&gt;  亦同时发布，且需要更新才能确保 .NET Core 3.0 与 Visual Studio 的协同使用。.NET Core 3.0 为 Visual Studio 2019 16.3 中的组成部分，开发者可以选择直接升级至 Visual Studio 2019 16.3，从而立刻获取 .NET Core。&lt;/p&gt;
&lt;p&gt;感谢所有为 .NET Core 3.0 做出贡献的朋友们！此次最新版本的发布源自数百位团队成员的努力，也包括技术社区的重大贡献。&lt;/p&gt;
&lt;p&gt;发行说明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/dotnet/core/tree/master/release-notes/3.0&#34;&gt;.NET Core 3.0 发行说明&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;.NET Core 2.2 -&amp;gt; 3.0 API 的区别&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/dotnet/core/blob/master/release-notes/3.0/3.0.0/3.0.0-contrib.md&#34;&gt;.NET Core 3.0 贡献者名单&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/dotnet/core/releases/tag/v3.0.0&#34;&gt;GitHub 发行版&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/dotnet/core/issues/3430&#34;&gt;关于 .NET Core 3.0 的 GitHub 问题解答&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;30-版本开发者需要了解什么&#34;&gt;3.0 版本，开发者需要了解什么？&lt;/h2&gt;
&lt;p&gt;在深入探究 .NET Core 3.0 中的全部新功能之前，我们首先需要强调几项关键性的改进与指导内容。以下是整理出的要点清单：&lt;/p&gt;</description>
    </item>
    <item>
      <title>[转]SignalR Core 尝鲜-A developer&#39;s tour of SignalR Core Alpha</title>
      <link>https://dodoro.chouxiangpai.com/archives/728/</link>
      <pubDate>Fri, 19 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/728/</guid>
      <description>&lt;p&gt;几个月前，SignalR Core 团队发布了一个非官方版本的 ASP.NET Core SignalR。为此，开发人员有机会了解其工作原理以及 ASP.NET SignalR 与 Signal Core 新架构之间的区别。&lt;/p&gt;
&lt;p&gt;SignalR Core 中移除了哪些特性 通过对比两个版本的 SignalR 可以发现，新版本不再支持一些重要的特性。首先是移除了对 jQuery 和其他第三方类库的依赖，因为新版本的 JavaScript 客户端是使用 TypeScript 开发的。其次是自动连接后的消息重放功能，移除该功能主要是出于性能方面的考虑。服务器需要为每一个连接维护一个缓冲区，用于保存消息，以便后续重新发送。当客户端断开连接，可以尝试重新恢复连接，然后将未发送的消息发送给客户端。可以想象，如果有很多客户端断开连接，而且每个客户端都发送大量的消息，对于服务器来说是个很大的负担。另一个被 SignalR 团队移除特性是多 Hub 端点，所以，在新版本里，每个连接只有一个 Hub。&lt;/p&gt;
&lt;p&gt;新版本的 SignalR Core 不再支持横向扩展（Scale Out）模型，原因是 MessageBus 被当成了横向扩展的“万灵丹”，但它实际上只支持Azure Service Bus、Redis 和 SQL Server。在实际的协作场景当中（客户端到客户端），随着客户端和消息数量的增长，通过以上三种方式进行横向扩展会有瓶颈问题。&lt;/p&gt;
&lt;p&gt;不过，我认为，移除横向扩展功能这一决定有点太过激进，因为在某些场景下，MessageBus 仍然十分有用。例如，在将 SignalR 作为一个广播服务器时，它可以控制发送消息的数量。而在 SignalR Core 的 alpha 版本中，开发者可以根据实际情况选择是否进行横向扩展，如业务需求、系统约束或基础设施，这种设计更加“可插拔”。SignalR Core 团队提供了一个使用 Redis 进行横向扩展的示例。其他扩展方式可能会被包含在 SignalR Core 的最终版中。&lt;/p&gt;
&lt;p&gt;最后一个被移除的功能是多服务器间的双向复制（backplane），因为这个功能会在服务器场生成太多的流量。ASP.NET SignalR 通过 MessageBus 在服务器间复制每一个消息，因为客户端无法直接连接到服务器场，而现在，SignalR 使用粘性会话来避免在所有服务器间复制消息。这样一来，SignalR Core 就可以知道哪个客户端连接到了哪台服务器上。&lt;/p&gt;
&lt;p&gt;SignalR Core 中增加了哪些新特性 现在让我们来看一下 SignalR Core 带来了哪些新的特性。首先是使用了二进制协议来发送和接收消息。在 ASP.NET SignalR 中只能使用 JSON 格式的文本来发送和接收消息，而现在则可以使用二进制协议，该二进制协议基于MessagePack序列化格式，比 JSON 更快、体积更小。&lt;/p&gt;</description>
    </item>
    <item>
      <title>关于.NET Core情况</title>
      <link>https://dodoro.chouxiangpai.com/archives/723/</link>
      <pubDate>Wed, 17 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/723/</guid>
      <description>&lt;p&gt;这几天终于抽出空啦看微软的Build 2019，看到.NET Core 3.0及相关技术的详细介绍，并且了解.NET的未来规划，感叹微软的伟大。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;images/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20190717093004.png&#34;&gt;&lt;img alt=&#34;微信图片_20190717093004&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/723/images/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20190717093004-300x166.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;上图是.NET Core的web开发部分。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;images/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20190717092956.png&#34;&gt;&lt;img alt=&#34;微信图片_20190717092956&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/723/images/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20190717092956-300x166.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;上图是.NET 平台大统一设计。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;images/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20190717093000.png&#34;&gt;&lt;img alt=&#34;微信图片_20190717093000&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/723/images/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20190717093000-300x163.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;上图是.NET未来的Roadmap。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;这就叫做技术领域的一统江湖。二十年前很多人嘲笑Windows的垄断和Microsoft的不开源（现在依然有老古董如此认为），如今，Sun寄人篱下并且靠着Java专利法残喘苟活。我一直觉得微软汇聚的是软件世界最优秀的工程师，这些人要是投身开源代码，那是很恐怖的，短短不到5年时间，微软现在成为开源代码贡献最大的公司。&lt;/p&gt;
&lt;p&gt;如今.NET Core 在海外若日中天，当国内经济持续下滑，人力成本持续提高，你们就会想到用.NET Core了，一个公司只需要三名码农就可以搞定后端、前端、移动开发。不过很可惜，公司的人力部门都听CTO的，而这群Java养出来的没落贵族是不会自己变革的。 ​​​​&lt;/p&gt;</description>
    </item>
    <item>
      <title>[转]WebAssembly 和 Blazor：解决了一个存在十年的老问题</title>
      <link>https://dodoro.chouxiangpai.com/archives/731/</link>
      <pubDate>Fri, 12 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/731/</guid>
      <description>&lt;p&gt;本文要点 WebAssembly 是一种新的客户端技术，可以在所有现代浏览器（包括移动浏览器）中实现近乎原生的性能，而且不需要插件。 许多语言，包括 C、C#、Go 和 Rust，都可以编译成面向基于栈的 WebAssembly 虚拟机的代码。 .NET 代码可以在任何地方运行，包括浏览器内部。 Blazor 是一个客户端库，它在 WebAssembly 上使用.NET 来支持借助 Razor 模板使用 C# 编写的单页应用程序。 Blazor 支持代码重用和将遗留代码移植到现代 Web 应用程序的能力。 在 2019 年 4 月中旬，微软悄悄地推出了一个年轻的框架，从“一切皆有可能”的实验阶段过渡到“我们致力于实现这一目标”的预览版。这个框架名为Blazor，因为它在浏览器中运行，并利用了一个名为 Razor 的模板系统或“视图引擎”，促成了这个.NET 开发人员几乎放弃了的场景。它不仅允许开发人员使用 C# 构建客户端代码（不需要 JavaScript），还允许开发人员在没有插件的情况下在浏览器中运行现有的.NET 标准 DLL。&lt;/p&gt;
&lt;p&gt;Blazor 有两种托管模式。本文主要关注客户端版本。你可以阅读“Blazor 服务器端托管模型”了解更多关于服务器端版本的信息。&lt;/p&gt;
&lt;p&gt;Silverlight 的希望 在任何地方运行.NET 的梦想始于 2006 年，当时有一个名为“Windows Presentation Foundation/Everywhere（WPF/E）”的应用程序框架以 Silverlight 的形式向公众发布。第一个版本支持通过 WPF 引入的声明性用户界面，即可扩展应用程序标记语言（Extensible Application Markup Language，简称 XAML）。该平台提供了对 UI 元素的细粒度控制，并提供了自己的文档对象模型（DOM），可以通过 JavaScript 访问。&lt;/p&gt;
&lt;p&gt;当 Silverlight 2 在 2008 年发布时，它通过一个作为浏览器插件运行的公共语言运行时（CLR）实现.NET 的完全支持，从而加快了采用速度。开发人员可以使用任何.NET 语言来构建 Web 应用程序，利用成熟的数据绑定模式，如 Model-View-ViewMode（MVVM），并使用 REST 或 Windows Communication Foundation（WCF）客户端与 Web API 通信。看起来，.NET 开发人员可以摆脱 JavaScript 的束缚，不用再担心跨浏览器测试，而是专注于一个具有公共代码库的平台来交付他们的应用程序。&lt;/p&gt;</description>
    </item>
    <item>
      <title>.NET Core 3.0 Preview 5发布</title>
      <link>https://dodoro.chouxiangpai.com/archives/634/</link>
      <pubDate>Tue, 28 May 2019 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/634/</guid>
      <description>&lt;p&gt;今天我们非常高兴发布 .NET Core 3.0 Preview 5，它包含了新的Json serializer，支持发布单执行文件，并且更新到新的runtime roll-forward，BCL也做了一些改动。&lt;/p&gt;
&lt;p&gt;目前可以下载.NET Core 3.0 Preview 5安装到Windows, macOS and Linux.另外，ASP.NET Core和EF Core也发布了。&lt;/p&gt;
&lt;p&gt;具体英文地址：&lt;a href=&#34;https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0-preview-5/&#34;&gt;https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0-preview-5/&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>领域驱动设计实现之路</title>
      <link>https://dodoro.chouxiangpai.com/archives/628/</link>
      <pubDate>Mon, 20 May 2019 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/628/</guid>
      <description>&lt;p&gt;2004年，Eric Evans出版《领域驱动设计——软件核心复杂性应对之道》（简称《领域驱动设计》），10年之后，我们有了《实现领域驱动设计》。DDD将一个软件系统的核心业务功能集中在一个核心域里面，其中包含了实体、值对象、领域服务、资源库和聚合等概念。在此基础上，DDD提出了一套完整的支撑这样的核心领域的基础设施。此时，DDD已经不再是“面向对象进阶”那么简单了，而是演变成了一个系统工程。&lt;/p&gt;
&lt;p&gt;领域，即是一个组织的业务开展方式，业务价值便体现在其中。长久以来，我们程序员都是很好的技术型思考者，我们总是擅长从技术的角度来解决项目问题。但是，一个软件系统是否真正可用是通过它所提供的业务价值体现出来的。因此，与其每天钻在那些永远也学不完的技术中，何不将我们的关注点向软件系统所提供的业务价值方向思考思考，这也正是DDD所试图解决的问题。在DDD中，代码就是设计本身，你不再需要那些繁文缛节的并且永远也无法得到实时更新的设计文档。编码者与领域专家再也不需要翻译才能理解对方所表达的意思。DDD有战略设计和战术设计之分。战略设计主要从高层“俯视”我们的软件系统，帮助我们精准地划分领域以及处理各个领域之间的关系；而战术设计则从技术实现的层面教会我们如何具体地实施DDD。&lt;/p&gt;
&lt;h1 id=&#34;ddd之战略设计&#34;&gt;DDD之战略设计&lt;/h1&gt;
&lt;p&gt;DDD的战略设计主要包括领域/子域、通用语言、限界上下文和架构风格等概念。&lt;/p&gt;
&lt;h2 id=&#34;1领域和子域domainsubdomain&#34;&gt;1、领域和子域（Domain/Subdomain）&lt;/h2&gt;
&lt;p&gt;领域驱动设计关注点应该放在如何设计领域模型上，以及对领域模型的划分。&lt;/p&gt;
&lt;p&gt;领域的概念：一个电商网站的领域包含了产品名录、订单、发票、库存和物流的概念。领域的划分是将一个大的领域划分成若干个子域。通常会将一个大型的软件系统拆分成若干个子系统。这种划分有可能是基于架构方面的考虑，也有可能是基于基础设施的。DDD对系统的划分是基于领域的，即基于业务。第一个问题，哪些概念应该建模在哪些子系统里面？第二个问题是，各个子系统之间的应该如何集成？如何解决？答案是：限界上下文和上下文映射图。&lt;/p&gt;
&lt;h2 id=&#34;2限界上下文bounded-context&#34;&gt;2、限界上下文（Bounded Context）&lt;/h2&gt;
&lt;p&gt;在一个领域/子域中，我们会创建一个概念上的领域边界，在这个边界中，任何领域对象都只表示特定于该边界内部的确切含义。这样边界便称为限界上下文。限界上下文和领域具有一对一的关系。将一个限界上下文中的所有概念，包括名词、动词和形容词全部集中在一起，我们便为该限界上下文创建了一套通用语言。通用语言是一个团队所有成员交流时所使用的语言，业务分析人员、编码人员和测试人员都应该直接通过通用语言进行交流。&lt;/p&gt;
&lt;p&gt;上文中的各个子域之间的集成问题，是限界上下文之间的集成问题。防腐层负责与外部服务提供方打交道，还负责将外部概念翻译成自己的核心领域能够理解的概念。当然，防腐层只是限界上下文之间众多集成方式的一种，另外还有共享内核、开放主机服务等，具体细节请参考 《实现领域驱动设计》原书。限界上下文之间的集成关系也可以理解为是领域概念在不同上下文之间的映射关系，因此，限界上下文之间的集成也称为上下文映射图。&lt;/p&gt;
&lt;h2 id=&#34;3架构风格architecture&#34;&gt;3、架构风格（Architecture）&lt;/h2&gt;
&lt;p&gt;DDD并不要求采用特定的架构风格，因为它是对架构中立的。可以采用传统的三层式架构，也可以采用REST架构和事件驱动架构等。但是在《实现领域驱动设计》中，作者比较推崇事件驱动架构和六边形（Hexagonal）架构。在六边形架构中，已经不存在分层的概念，所有组件都是平等的。这主要得益于软件抽象的好处，即各个组件的之间的交互完全通过接口完成，而不是具体的实现细节。Robert C. Martin：抽象不应该依赖于细节，细节应该依赖于抽象。&lt;/p&gt;
&lt;p&gt;采用六边形架构的系统中存在着很多端口和适配器的组合。端口表示的是一个软件系统的输入和输出，而适配器则是对每一个端口的访问方式。&lt;/p&gt;
&lt;h1 id=&#34;ddd之战术设计&#34;&gt;DDD之战术设计&lt;/h1&gt;
&lt;p&gt;战略设计为我们提供一种高层视野来审视我们的软件系统，而战术设计则将战略设计进行具体化和细节化，它主要关注的是技术层面的实施，也是对我们程序员来得最实在的地方。&lt;/p&gt;
&lt;h2 id=&#34;1领域对象&#34;&gt;1、领域对象&lt;/h2&gt;
&lt;p&gt;领域对象能够准确地表达出业务意图，但多数时候却是充满getter和setter的领域对象，此时的领域对象已经不是领域对象了，而是Martin Fowler所称之为的贫血对象。.NET里面很好地支持非贫血对象。&lt;/p&gt;
&lt;h2 id=&#34;2实体vs值对象entity-vs-value-object&#34;&gt;2、实体vs值对象（Entity vs Value Object）&lt;/h2&gt;
&lt;p&gt;软件系统中实体表示那些具有生命周期并且会在其生命周期中发生改变的东西；而值对象则表示起描述性作用的并且可以相互替换的概念。同一个概念，在一个软件系统中被建模成了实体，但是在另一个系统中则有可能是值对象。&lt;/p&gt;
&lt;h2 id=&#34;3聚合aggregate&#34;&gt;3、聚合（Aggregate）&lt;/h2&gt;
&lt;p&gt;聚合是DDD中最难理解的概念 ，聚合中所包含的对象之间具有密不可分的联系，他们是内聚在一起的。比如一辆汽车（Car）包含了引擎（Engine）、车轮 （Wheel）和油箱（Tank）等组件，缺一不可。一个聚合中可以包含多个实体和值对象，因此聚合也被称为根实体。聚合是持久化的基本单位，它和资源库具有一一对应的关系。&lt;/p&gt;
&lt;h2 id=&#34;4领域服务domain-service&#34;&gt;4、领域服务（Domain Service）&lt;/h2&gt;
&lt;p&gt;领域概念放在实体上不合适，放在值对象上也不合适，领域服务本来就是来处理这种场景的。比如对密码进行加密，可以创建一个 PasswordEncryptService来专门负责此事。&lt;/p&gt;
&lt;h2 id=&#34;5资源库repository&#34;&gt;5、资源库（Repository）&lt;/h2&gt;
&lt;p&gt;资源库用于保存和获取聚合对象，资源库与DAO相似。但资源库和DAO存在显著区别。DAO只是对数据库的一层很薄的封装，而资源库则更加具有领域特征。另外，所有的实体都可以有相应的DAO，但并不是所有的实体都有资源库，只有聚合才有相应的资源库。资源库分为两种，一种是基于集合的，一种是基于持久化的。顾名思义，基于集合的资源库具有编程语言中集合的特征。&lt;/p&gt;
&lt;h2 id=&#34;6领域事件domain-event&#34;&gt;6、领域事件（Domain Event）&lt;/h2&gt;
&lt;p&gt;《领域驱动设计》中并没有提到领域事件，领域事件是最近几年才加入DDD生态系统的。微服务（Micro Service）的架构中，整个系统被分成了很多个轻量的程序模块，他们之间的数据一致性并不容易通过事务一致性完成，领域事件便可以用于处理上述问题，此时最终一致性取代了事务一致性，通过领域事件的方式达到各个组件之间的数据一致性。&lt;/p&gt;</description>
    </item>
    <item>
      <title>.NET Core 3.0-preview3 发布</title>
      <link>https://dodoro.chouxiangpai.com/archives/632/</link>
      <pubDate>Wed, 06 Mar 2019 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/632/</guid>
      <description>&lt;p&gt;.NET Core 3.0 Preview 3已经发布，框架和ASP.NET Core有许多有趣的更新。这是最重要的更新列表。 下载地址 :https://aka.ms/netcore3download 。&lt;/p&gt;
&lt;p&gt;.NET Core 3.0的更新：&lt;/p&gt;
&lt;p&gt;C＃中对索引和范围的更多支持&lt;/p&gt;
&lt;p&gt;支持.NET Standard 2.1。以.NET Standard项目文件为目标，并将netstandard2.1指定为目标框架。完整的.NET Framework不支持.NET Standard 2.1。&lt;/p&gt;
&lt;p&gt;F＃4.6和dotnet fsi命令。可以使用F＃4.6和dotnet fsi命令的预览。FSI代表F＃互动。&lt;/p&gt;
&lt;p&gt;AssemblyDependencyResolver和resolver事件。从给定路径加载依赖程序集（之前不可能），解析程序事件可帮助我们更好地处理动态加载的本机依赖项。&lt;/p&gt;
&lt;p&gt;Windows Forms应用程序的高DPI。最后，微软将Windows Forms应用程序推向了当今时代。96DPI不再适用，并且可以构建高DP Windows窗体应用程序。&lt;/p&gt;
&lt;p&gt;​&lt;/p&gt;
&lt;p&gt;ASP.NET Core 3.0的更新：&lt;/p&gt;
&lt;p&gt;Razor组件的改进。现在2个项目合并成单个项目模板，Razor组件支持端点路由和预渲染，Razor组件可以托管在Razor类库中。还改进了事件处理和表单和验证支持。&lt;/p&gt;
&lt;p&gt;运行时编译。它在ASP.NET Core 3.0模板中被禁用，但现在可以通过向项目添加特殊的NuGet包来打开它。&lt;/p&gt;
&lt;p&gt;Worker Service 模板。需要编写Windows服务还是Linux守护进程？现在我们有了Worker Service 模板。&lt;/p&gt;
&lt;p&gt;gRPC模板。与谷歌一起构建的gRPC是一种流行的远程过程调用（RPC）框架。此版本的ASP.NET Core在ASP.NET Core上引入了第一等的gRPC支持。&lt;/p&gt;
&lt;p&gt;Angular模板使用Angular 7. Angular SPA模板现在使用Angular 7，在第一次稳定释放之前，它将被Angular 8替换。&lt;/p&gt;
&lt;p&gt;SPA-s的身份验证。Microsoft通过此预览为单页应用程序添加了现成的身份验证支持。&lt;/p&gt;
&lt;p&gt;SignalR与端点路由集成。小变化 - 现在使用端点路由定义SingalR路由。&lt;/p&gt;
&lt;p&gt;SignalR Java客户端支持长轮询。即使在不支持或不允许WebSocket的环境中，SignalR Java客户端现在也可以使用。&lt;/p&gt;</description>
    </item>
    <item>
      <title>终于决定了，将业余的大部分时间投入给C#开源世界</title>
      <link>https://dodoro.chouxiangpai.com/archives/562/</link>
      <pubDate>Fri, 14 Nov 2014 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/562/</guid>
      <description>&lt;p&gt;昨天.NET已经宣布正式开源，而我的信念更加坚定了：将业余的大部分时间投入给C#开源世界。&lt;/p&gt;
&lt;p&gt;之前一直诟病于C#和.NET只属于微软的产品，现在完全不一样了，我自己的下一步计划：&lt;/p&gt;
&lt;p&gt;一、学习计划&lt;/p&gt;
&lt;p&gt;1、重新把前几年的项目进行一次全面梳理，把核心和精华的部分留下；&lt;/p&gt;
&lt;p&gt;2、重新全面系统完整地把最新的.NET框架学习一边，并且结合大的开源项目研究，目标是基于国外开源系统改造出非常好用的系统；&lt;/p&gt;
&lt;p&gt;3、将手头上关于.NET和C#的图书做一遍梳理，包括电子版的；&lt;/p&gt;
&lt;p&gt;4、持续跟进最新的关于Mono和.NET开源方面的资讯；&lt;/p&gt;
&lt;p&gt;二、工作计划&lt;/p&gt;
&lt;p&gt;1、将目前公司的项目做好梳理、未未来的跨平台打好基础；&lt;/p&gt;
&lt;p&gt;2、专心研究nopcommerce（电商）项目，并且基于它搭建一个云、端、移动app、网店一体化的电商项目（时间可能会很长），这个项目会为未来二次开源做准备；&lt;/p&gt;
&lt;p&gt;3、专心研究CSLA .NET，这个是.NET的一个典范，而且包含了所有平台的样例，这是跨平台的先驱；&lt;/p&gt;
&lt;p&gt;4、专心研究Orchard（cms）项目，并且基于它搭建一个云、端、移动app的公司企业网站系统，这个项目也会为未来开源做准备。&lt;/p&gt;
&lt;p&gt;将慢慢地把cms和电商项目融入公司，打造一支技术能力强的团队。&lt;/p&gt;</description>
    </item>
    <item>
      <title>微软正式MIT协议将开源.NET框</title>
      <link>https://dodoro.chouxiangpai.com/archives/557/</link>
      <pubDate>Thu, 13 Nov 2014 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/557/</guid>
      <description>&lt;p&gt;今天是C#程序员狂欢的日子，这真的是一门非常非常优雅的很棒的编程语言。&lt;/p&gt;
&lt;p&gt;“Scott Guthrie宣布微软正式将开源.NET框架，使用MIT协议开源，让它在Linux和OS X系统上也能够运行。开发商们将能够在全球三个最大的操作系统上使用.NET框架了。”&lt;/p&gt;
&lt;p&gt;这将是计算机软件行业载入史册的一天，.NET平台终于兑现它对世界的承诺，全面支持所有平台，我坚信这是安德鲁和mono老大的英明推动下、当然也是在时代的发展驱动下的结果，太棒了！&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;images/2000.jpg&#34;&gt;&lt;img alt=&#34;2000&#34; loading=&#34;lazy&#34; src=&#34;https://dodoro.chouxiangpai.com/archives/557/images/2000-300x157.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>.NET Framework发展简历</title>
      <link>https://dodoro.chouxiangpai.com/archives/452/</link>
      <pubDate>Thu, 08 Aug 2013 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/452/</guid>
      <description>&lt;p&gt;.NET Framework1.0版本是在2002年正式发布的，当时获得了世界软件界的极大瞩目，影响深远，比尔盖茨说这是为未来10年的战略做准备，现在看来，微软的这个产品获得了巨大成功。&lt;/p&gt;
&lt;p&gt;2005年，微软发布了.NET Framework2.0,这个版本是迄今为止最重要的一个版本，2.0为C#引入了范型和公共语言运行时。.NET 3.0版本是基于2.0的运行时的，引入了WPF和XAML语言，还有一项伟大的技术WCF。.NET3.5则引入了C#3.0，并且支持LINQ语言（一种全新的方式来检索数据）和Lambda表达式。.NET4.0是继2.0之后的一个重要版本，引入了动态语言和并行编程。&lt;/p&gt;
&lt;p&gt;.NET Framework4.5是基于4.0版本的更新，主要有下面这些更新：&lt;/p&gt;
&lt;p&gt;1、异步变成方式，在C#5.0中，异步编程变得更加简单；&lt;/p&gt;
&lt;p&gt;2、引入了Windows Store Apps；&lt;/p&gt;
&lt;p&gt;3、增强了数据访问方式，主要是Entity Framework5.0的发布；&lt;/p&gt;
&lt;p&gt;4、增强了WPF和江MVC升级到了4.0；&lt;/p&gt;</description>
    </item>
    <item>
      <title>[转]C#中的委托,匿名方法和Lambda表达式</title>
      <link>https://dodoro.chouxiangpai.com/archives/457/</link>
      <pubDate>Thu, 08 Aug 2013 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/457/</guid>
      <description>&lt;h2 id=&#34;一简介&#34;&gt;一、简介&lt;/h2&gt;
&lt;p&gt;在.NET中，委托，匿名方法和Lambda表达式很容易发生混淆。我想下面的代码能证实这点。下面哪一个First会被编译？哪一个会返回我们需要的结果？即Customer.ID=5.答案是6个First不仅被编译，并都获得正确答案，且他们的结果一样。如果你对此感到困惑，那么请继续看这篇文章。&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;&lt;/th&gt;
					&lt;th&gt;&lt;code&gt;class&lt;/code&gt; &lt;code&gt;Customer&lt;/code&gt;  &lt;code&gt;{&lt;/code&gt;      &lt;code&gt;public&lt;/code&gt; &lt;code&gt;int&lt;/code&gt; &lt;code&gt;ID {&lt;/code&gt; &lt;code&gt;get``;&lt;/code&gt; &lt;code&gt;set``; }&lt;/code&gt;      &lt;code&gt;public&lt;/code&gt; &lt;code&gt;static&lt;/code&gt; &lt;code&gt;bool&lt;/code&gt; &lt;code&gt;Test(Customer x)&lt;/code&gt;      &lt;code&gt;{&lt;/code&gt;          &lt;code&gt;return&lt;/code&gt; &lt;code&gt;x.ID == 5;&lt;/code&gt;      &lt;code&gt;}&lt;/code&gt;  &lt;code&gt;}&lt;/code&gt;  &lt;code&gt;...&lt;/code&gt;  &lt;code&gt;List&amp;lt;Customer&amp;gt; custs =&lt;/code&gt; &lt;code&gt;new&lt;/code&gt; &lt;code&gt;List&amp;lt;Customer&amp;gt;();&lt;/code&gt;  &lt;code&gt;custs.Add(``new&lt;/code&gt; &lt;code&gt;Customer() { ID = 1 });&lt;/code&gt;  &lt;code&gt;custs.Add(``new&lt;/code&gt; &lt;code&gt;Customer() { ID = 5 });&lt;/code&gt;  &lt;code&gt;custs.First(``new&lt;/code&gt; &lt;code&gt;Func&amp;lt;Customer,&lt;/code&gt; &lt;code&gt;bool``&amp;gt;(``delegate``(Customer x) {&lt;/code&gt; &lt;code&gt;return&lt;/code&gt; &lt;code&gt;x.ID == 5; }));&lt;/code&gt;  &lt;code&gt;custs.First(``new&lt;/code&gt; &lt;code&gt;Func&amp;lt;Customer,&lt;/code&gt; &lt;code&gt;bool``&amp;gt;((Customer x) =&amp;gt; x.ID == 5));&lt;/code&gt;  &lt;code&gt;custs.First(``delegate``(Customer x) {&lt;/code&gt; &lt;code&gt;return&lt;/code&gt; &lt;code&gt;x.ID == 5; });&lt;/code&gt;  &lt;code&gt;custs.First((Customer x) =&amp;gt; x.ID == 5);&lt;/code&gt;  &lt;code&gt;custs.First(x =&amp;gt; x.ID == 5);&lt;/code&gt;  &lt;code&gt;custs.First(Customer.Test);&lt;/code&gt;&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;二什么是委托&#34;&gt;&lt;strong&gt;二、什么是委托？&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;现在你定义一个处理用户订单的购物车ShoppingCart类。管理层决定根据数量，价格等给客人折扣。做为其中的一部分，他们已经实现了处理订单时你要考虑一方面。不用考虑过多，你简单声明一个变量来保存有“吸引力的折扣”(magicDisCount)，然后实现逻辑。&lt;/p&gt;</description>
    </item>
    <item>
      <title>[转]Emgu cv中的SIFT算法实现</title>
      <link>https://dodoro.chouxiangpai.com/archives/299/</link>
      <pubDate>Thu, 29 Nov 2012 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/299/</guid>
      <description>&lt;p&gt;SIFT算法大家都比较熟悉，网上的版本很多，刚开始接触时我主要研究的是C++，因为相对于C#，基于OPEN CV C++的SIFT算法资料更多，但是由于想要实现较为理想的界面效果，最终还是放弃了使用C++转而使用C#。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;C#中SIFT算法主要分为三种：&lt;/p&gt;
&lt;p&gt;1）脱离Emgu cv平台，完全手动实现所有SIFT算法函数，这样的程序虽然实现有些困难，但是完全可借助已有的C++程序做更改，而且这样做最大的好处就是对SIFT算法的原理有更深的理解。&lt;/p&gt;
&lt;p&gt;2）实现时使用少量Emgu cv函数（例如影像的读取，灰度值获得等），但是大部分工作还是依赖于.net平台自行完成。&lt;/p&gt;
&lt;p&gt;3）基本上程序完全借助于Emgu cv提供的接口，核心函数完全由Emgu cv提供。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;前两类程序资源较多，大家也很容易下载，第三类程序资源相对较少，因此我今天简单为大家介绍第三类算法的实现方法，首先回顾一下SIFT算法计算步骤：&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;1. 尺度空间极值检测：搜索所有尺度上的图像位置。通过高斯微分函数来识别潜在的对于尺度和旋转不变的兴趣点。&lt;/p&gt;
&lt;p&gt;2. 关键点定位：在每个候选的位置上，通过一个拟合精细的模型来确定位置和尺度。关键点的选择依据于它们的稳定程度。&lt;/p&gt;
&lt;p&gt;3. 方向确定：基于图像局部的梯度方向，分配给每个关键点位置一个或多个方向。所有后面的对图像数据的操作都相对于关键点的方向、尺度和位置进行变换，从而提供对于这些变换的不变性。&lt;/p&gt;
&lt;p&gt;4. 关键点描述：在每个关键点周围的邻域内，在选定的尺度上测量图像局部的梯度。这些梯度被变换成一种表示，这种表示允许比较大的局部形状的变形和光照变化。&lt;/p&gt;
&lt;p&gt;使用Emgu cv实现上述步骤非常简单，程序如下：&lt;/p&gt;
&lt;p&gt;//确定匹配图像&lt;/p&gt;
&lt;p&gt;Bitmap bt1 = new Bitmap(@&amp;ldquo;C:\Users\GAOXIANG\Desktop\111.jpg&amp;rdquo;); Bitmap bt2 = new Bitmap(@&amp;ldquo;C:\Users\GAOXIANG\Desktop\222.jpg&amp;rdquo;);&lt;/p&gt;
&lt;p&gt;//将图像转为Emgu cv的处理格式&lt;/p&gt;
&lt;p&gt;Image&amp;lt;Gray, byte&amp;gt; img1 = new Image&amp;lt;Gray, byte&amp;gt;(bt1); Image&amp;lt;Gray, byte&amp;gt; img2 = new Image&amp;lt;Gray, byte&amp;gt;(bt2);&lt;/p&gt;
&lt;p&gt;//使用Emgu cv探测图片特征点&lt;/p&gt;
&lt;p&gt;SIFTDetector sift = new SIFTDetector(); var f1 = sift.DetectFeatures(img1, null); var f2 = sift.DetectFeatures(img2, null);&lt;/p&gt;
&lt;p&gt;到此已经获得了两张相片的特征点f1,f2,接下来就是将相互匹配的特征点相连：&lt;/p&gt;
&lt;p&gt;for (int i = 0; i &amp;lt; f1.Length; i++) { double[] dist = new double[f2.Length]; int n = 0; int index = 0; for (int j = 0; j &amp;lt; f2.Length; j++) {&lt;/p&gt;</description>
    </item>
    <item>
      <title>HttpContext.Current用法,.ashx文件中使用Session,在非Web项目中使用HttpContext.Current</title>
      <link>https://dodoro.chouxiangpai.com/archives/29/</link>
      <pubDate>Mon, 21 May 2012 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/29/</guid>
      <description>&lt;p&gt;在类库项目（或者其他非Web项目中）有时候需要HttpContext.Current这个方法，我们发现在类里面添加了引用“using System.Web;”之后还是不行，其实解解这个问题很简单，只需要在该项目的“引用”中添加System.Web这个引用就可以了。 另外值得注意的是，在非Web项目中使用HttpContext.Current.Cache、HttpContext.Current.Session等的时候，最好进行判断HttpContext.Current是否为空： if (HttpContext.Current != null &amp;amp;&amp;amp; HttpContext.Current.Session != null) { string test = HttpContext.Current.Session[&amp;ldquo;Session&amp;rdquo;].ToString(); } 这是因为有些情况下Session或者Cache等会被截断，比如在.ashx文件中，默认情况下就会截断Session。当然也可以通过设置在.ashx文件中使用Session，但是为了安全，最后进行判断。 如果要在.ashx文件中使用Session，那么要先引用“using System.Web.SessionState;”，然后继承接口“IRequiresSessionState”，下面是一个例子： using System; using System.Data; using System.Web; using System.Collections; using System.Web.Services; using System.Web.Services.Protocols; using System.Web.SessionState; namespace Lemon.Life.WebData {/// 演示“在.ashx中使用Session” [WebService(Namespace = &amp;ldquo;&lt;a href=&#34;http://tempuri.org/%22&#34;&gt;http://tempuri.org/&amp;quot;&lt;/a&gt;)] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class Xml : IHttpHandler, IRequiresSessionState { public void ProcessRequest(HttpContext context) { context.Response.ContentType = &amp;ldquo;text/plain&amp;rdquo;; context.Session[&amp;ldquo;Test&amp;rdquo;] = &amp;ldquo;Test&amp;rdquo;; string test = context.Session[&amp;ldquo;Test&amp;rdquo;].ToString(); context.Response.Write(&amp;ldquo;Hello World&amp;rdquo;); } public bool IsReusable { get { return false;} } } }&lt;/p&gt;</description>
    </item>
    <item>
      <title>.NET的Windows模拟身份验证,远程网络传输文件</title>
      <link>https://dodoro.chouxiangpai.com/archives/27/</link>
      <pubDate>Sat, 21 May 2011 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/27/</guid>
      <description>&lt;p&gt;在开发过程中，常常遇到这样的问题：文件，包括图片和文件上传到服务器，而Web服务器和文件服务器不是同一个，而且不在同一个域里面，那么针对于.NET应该如何处理这样的问题呢？ 可能很多高手一下子就知道如何解决，但是我确实是经过了一番努力才弄明白，下面就结束如何使用.NET的Windows模拟身份验证。 1、首先引用两个名称空间&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;using&lt;/span&gt; System.Security.Principal;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;using&lt;/span&gt; System.Runtime.InteropServices;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;2、其次定义好模拟权限的调用方法&lt;/p&gt;
&lt;h1 id=&#34;region-权限模拟&#34;&gt;region 权限模拟&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; LOGON32_LOGON_INTERACTIVE = &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; LOGON32_PROVIDER_DEFAULT = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;[DllImport(&amp;#34;advapi32.dll&amp;#34;, CharSet = CharSet.Auto)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extern&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; dwLogonType, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; dwLogonProvider, &lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; IntPtr phToken);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;[DllImport(&amp;#34;advapi32.dll&amp;#34;, CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extern&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; DuplicateToken(IntPtr hToken, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; impersonationLevel, &lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; IntPtr hNewToken);&amp;lt;summary&amp;gt;&lt;span style=&#34;color:#75715e&#34;&gt;/// 验证用户，并生成WindowsIdentity 实例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/summary&amp;gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; WindowsIdentity GetIdentity(String userName, String domain, String password)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IntPtr token = IntPtr.Zero;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IntPtr tokenDuplicate = IntPtr.Zero;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; token) == &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (DuplicateToken(token, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; tokenDuplicate) == &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; WindowsIdentity(tokenDuplicate);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; WindowsImpersonationContext GetContext()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WindowsIdentity identity = &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WindowsImpersonationContext impersonationContext = &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;identity = &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;.IsNullOrEmpty(user) ? &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt; : GetIdentity(user, &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;, pwd);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 使用用户凭证进行用户模拟&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;impersonationContext = (identity == &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;) ? &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt; : identity.Impersonate();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; impersonationContext;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#endregion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;3、在调用身份模拟的函数中使用&lt;/p&gt;</description>
    </item>
    <item>
      <title>设置Session永不过期,Session不过期</title>
      <link>https://dodoro.chouxiangpai.com/archives/31/</link>
      <pubDate>Sat, 21 May 2011 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/31/</guid>
      <description>&lt;p&gt;很多时候为了需要，必须使用Session，但是Session过期问题一直困扰很多人，我也是。通过网上的搜索，发现了可以通过两种方式了设置，但是只有一个可以永不过期。 保持Session的方法： （1）、设Session.timeout=-1，或小于0的数。这种方法肯定是不行的，session计算时间以分钟为单位，必须是大于等于1的整数。 （2）、设Session.timeout=99999。这种同样不行，Session有最大时间限制。 其实，Session最大值为24小时，也就是说你最大可以Session.timeout=1440，1441都是不可以有。 所以想通过设Session.timeout的过期时间让Session永不过期是不可能的。写到Cookies里是比较好的方法，但是Cookie非常的危险，如果在外面的电脑很容易被别人劫持，不安全！ 那么有没有一种方法可以保持Session呢，可以使用一种办法，就是在要保持session的页里设隐藏iframe 这个Iframe每隔一段时间刷新一次这个Iframe页面就可以了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>.NET内核揭秘</title>
      <link>https://dodoro.chouxiangpai.com/archives/23/</link>
      <pubDate>Fri, 21 May 2010 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/23/</guid>
      <description>&lt;p&gt;这两年来，越来越多的国内软件企业开始深入.NET底层开发，我也接到了不少企业的深度.NET培训邀约，在培训课程方面也有较为成熟的积累。决定动笔写作《.NET内核揭秘》（暂定名）一书。目前大致蓝图如下： 1. 对象里面到底装的是什么&amp;ndash;揭秘.NET类型封装 议题：程序构造的历史；代码段与数据段；对象、数据成员与函数成员；.NET对象到底有多大；.NET对象布局；简单值类型；string揭秘；数组揭秘….. 2. 程序运行之来龙去脉 &amp;ndash;揭秘CLR虚拟机执行系统 议题：JIT编译如何进行；系统如何加载类型；堆栈模型；如何使用应用程序域隔离代码；异常如何层层抛出….. 3. 对象的前生后世 &amp;ndash;揭秘.NET类型继承 议题：子类从父类继承了什么；子类与父类之间的类型关联；为什么可以将子类看作一个父类；静态类型与动态类型…… 4. 不要调用我，让我来调用你 &amp;ndash;揭秘.NET多态机制 议题：callvirt如何调用虚方法；虚方法表上都有什么；虚表指针什么时候使用；虚方法效率到底有多低…. 5. 数据与代码的博弈 &amp;ndash;揭秘.NET委托调用 议题：委托如何实现动态调用；委托类型内部构造；委托调用的效率；异步委托调用…… 6 托管对象的生与死 &amp;ndash;揭秘.NET垃圾收集 议题：垃圾收集器如何分配内存；垃圾收集器如何构造对象图；垃圾收集器如何搬移内存；垃圾收集器如何更新托管引用；垃圾收集器的性能到底如何….. 7. 插上元数据的翅膀 &amp;ndash; 揭秘.NET反射机制 议题：元数据是什么；元数据在哪里；如何反射类型；反射类型内部是什么；反射的效率到底有多低；反射的边界在哪里….. 8. 运行时泛型的算盘 &amp;ndash;揭秘.NET泛型实现 议题：泛型类型到底是什么；泛型类型与元数据；泛型类型到底如何实例化；泛型的约束与效率….. 如果这些问题是各位面临.NET所困惑的，我希望在本书中能够解答大家的疑惑。印象中有些读者对《.NET框架程&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#实现代理访问网络资源,源代码实现,WebClient篇</title>
      <link>https://dodoro.chouxiangpai.com/archives/83/</link>
      <pubDate>Fri, 21 May 2010 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/83/</guid>
      <description>&lt;p&gt;很多公司都使用代理上网，这样当然是有原因的，因为要对公司员工访问网络进行监视，但是这很令开发人员郁闷，因为在程序中访问网络资源是需要自己设置代理认证的，我们公司就是这样的。幸亏不要紧，因为C#提供了针对访问网络资源代理的设置，今天来讲解WebClient代理问题。下面是一个实现的例子： private static string GetHtml(string url, EncodingType type, bool isByProxy) { WebClient webClient = new WebClient();//创建WebClient实例myWebClient if (isByProxy) { //创建代理服务器设置对象的实例 System.Net.WebProxy wp = new System.Net.WebProxy(&amp;ldquo;ISASRV:80&amp;rdquo;);//代理名称很端口，要根据你的情况来设置 //代理服务器需要验证 wp.BypassProxyOnLocal = false; //用户名密码，要根据你的情况来设置 wp.Credentials = new NetworkCredential(&amp;ldquo;UserName&amp;rdquo;, &amp;ldquo;PWD&amp;rdquo;, &amp;ldquo;hold&amp;rdquo;); //将代理服务器设置对象赋予全局设定 GlobalProxySelection.Select = wp; //获取或设置用于对向Internet 资源的请求进行身份验证的网络凭据。 webClient.Credentials = CredentialCache.DefaultCredentials; } byte[] pagedata = webClient.DownloadData(url);//先获取二进制的资源 }&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#语言编程常用知识介绍</title>
      <link>https://dodoro.chouxiangpai.com/archives/73/</link>
      <pubDate>Fri, 21 May 2010 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/73/</guid>
      <description>&lt;p&gt;1)decimal，即十进制类型，是一种高精度、128位数据类型，它所表示的范围从大约1.0*10^-28到7.9*102^28的28至29位有效数字，注意该精度是以位数(digits)而不是以小数位(decimal places)来表示的。 2)decimal类型的变量在赋值时要在值后面加m下标，否则将被编译器当作double类型处理。 3)System.delegate 代表，引用类型，用于指向一个方法，定义方法：delegate int MyDelegate(); 4)多维数组定义一例：int[,] a=new int[,]{{1,2,3},{4,5,6}} 5)多维数组定义另一例：int[][] b=new int[3][];b[0]=new int[]{1,2,3};b[1]=new int[]{1,2,3,4,5,6};b[2]=new int[]{1,2,3,4,5,6,7,8,9}; 6)可以在变量名前面加上@，这主要是为了在与其他语言交互时避免冲突，一般情况下不推荐使用。 7)变量有以下以种：静态变量、非静态变量、数组元素、值能数、引用参数、输出参数、局部参数。 8)常量const修饰符有：new,public,protected,internal,private。 9)隐式枚举类型允许把十进制整数0转换为任何枚举类型，对应其他的整数则不存在这种隐式转换。 10)显式转换有可能丢失信息或导致异常抛出。 11)常量1.0默认为double类型，若要使用float型，可写成1.0f，即在数值后面加个f。 12)在逻辑表达式的求值过程中，不是所有的逻辑操作符都被执行，这种情况称为“短路”。 13)一般来说每个switch项都以break,goto case,goto default结束，但实际上任何一种不导致“遍历”的结构都是允许的。 14)C#中提供了析构函数，用于专门释放被占用的系统资源;析构函数的名称为“&lt;del&gt;类名”，它不接收任何参数，不返回值，不能被继承；C#提供垃圾收集器帮助我们解决释放资源的工作。 15) 方法修饰符可以是：new,public,protected,internal,private,static,virtual,sealed, override,abstract,extern。对于使用了abstract,extern修饰符的方法，方法的执行体仅仅只有一个简单的分号。其他的方法执行体应包含调用该方法所要执行的语句。 16)方法参数四种类型：值类型（不需修饰符）、引用类型（以ref修饰符声明）、输出类型（以out修饰符声明）、数组型类型（以params修饰符声明） 17)如果方法的形参表中包含了数组型参数，那么它必须在参数表中位于最后。另外，参数只允许是一维数组。比如：string[],string[][]类型都可以作为数组型参数，而string[,]则不能。最后，数组型参数不能再有ref和out修饰符。 18)静态方法只能访问类中的静态成员。 19)操作符重载方法：在定义类方法时，在方法名称后面加上“[空格]operator[空格][具体的操作符]”，如以下方法：public static Player operator ++(Player p){method body&amp;hellip;} 20)可重载的操作符：+,-,!,&lt;/del&gt;,++,&amp;ndash;,true,false,*,/,%,&amp;amp;,,^,&amp;laquo;,&amp;raquo;,==,!=,&amp;gt;,&amp;lt;,&amp;gt;=,&amp;lt;=。注：这里列出的操作符之间用“,”隔开。 21)不可重载的操作符：=,&amp;amp;&amp;amp;,,?:,new,typeof,sizeof,is 22)域的修饰符：new,public,protected,internal,private,static,readonly 23) 属性的修饰符：new,public,protected,internal,private,static,virtual,sealed, override,abstract，以上修饰符中，static,virtual,override,abstract不能同时使用。 24)事件的修饰符：new,public,protected,internal,private,static,virtual,sealed, override,abstract，以上修饰符中，static,virtual,override,abstract不能同时使用。 25)构造函数和析构函数不能被继承。 26)在派生类中覆盖基类中的方法时，在方法前面加上new关键字可关闭编译器的警告。 27)base关键字主要是为派生类调用基类成员提供一个简写的方法。 28)C#中的多态性有两种：编译时的多态性和运行时的多态性；编译时的多态性是通过重载实现的，运行时的多态性是通过虚成员实现的；编译时的多态性为我们提供了运行速度快的特点，而运行时的多态性则带来了高度的灵活和抽象的特点。 29)方法在使用了virtual修饰符之后，不允许再有static,abstract或override修饰符。 30)在派生类中重新定义基类的虚方法时，要求方法名称、返回值类型、参数表中的参数个数、类型、顺序都必须与基类中的虚方法完全一致。 31)在派生类中声明对虚方法的重载，要求在声明中加上override关键字，而且不能有new,static或virtual修饰符。 32)抽象类只能作为其他类的基类，不能被实例化。 33)只能在抽象类中声明抽象方法，抽象方法不包含具体的实现内容，不能再使用static或virtual修饰符，不能出现{}，如：public abstract void speak(); 34)抽象类中的抽象方法在派生类中不能使用base关键字来进行访问。 35)可以利用抽象方法来重载基类的虚方法，这时基类中的虚方法的执行代码这被“拦截”了。 36)密封类（使用sealed修饰符的类）不能被其他类继承。 37)将方法密封可防止方法所在的类的派生类对该方法重载。 38)不是类的每个成员方法都可以作为密封方法，密封方法必须对基类的虚方法进行重载，提供具体的实现方法。 39)和类的成员方法一样，我们也可以定义属性的重载、虚属性、抽象属性、以及密封属性的概念。 40)接口仅可以使用下列修饰符：new,public,protected,internal,private。 41)接口的成员可以是属性、方法、事件和索引指示器。 42)C#中类继承只允许单继承，但接口允许多继承，多个父接口之间用“,”隔开，被继承的接口应该是可以访问的，如从private类型和internal类型的接口中继承就是不允许的。 43)接口成员的默认访问方式是public，接口成员不能包含任何修饰符。 44)由于接口允许多继承，所以要注意接口成员的是否有二义性。 45)显式接口成员只能通过接口调用。 46)显式接口成员执行体不能使用任何访问修饰符。 47)使用private,protected和static修饰符的成员不能参与实现接口映射。 48)如果不显式地重新实现接口，派生类就无法改变从基类中继承来的接口映射。但是，当一个接口方法被映射到类的一个虚方法时，派生类就可以重载这个虚方法，并且改变这个接口的实现。 49)继承了接口实现的类可以对接口进行重实现。 50)有关接口的几个概念：显式接口成员执行体、 50) 各个流：Stream,BinaryReader,BinaryWriter,File,Directory,FileStream, TextReader,TextWriter,StringReader,StringWriter,StreamReader,StreamWriter, BufferedStream,MemoryStream,NetworkStream;对网络文件进行操作使用IsolatedStorage类处理，不用流。&lt;/p&gt;</description>
    </item>
    <item>
      <title>什么是.NET框架？</title>
      <link>https://dodoro.chouxiangpai.com/archives/21/</link>
      <pubDate>Fri, 21 May 2010 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/21/</guid>
      <description>&lt;p&gt;&lt;strong&gt;1、.NET框架的定义&lt;/strong&gt; 按照微软官方的说法：.NET框架是支持生成并且运行下一代应用程序和 XML Web Services 的内部 Windows 组件。也就是说，.NET框架是windows的一部分，只要是运行在windows操作系统下的程序都可以得到.NET框架的支持。其实微软的下一代windows平台（Vista和windows 7都支持.NET框架）。 &lt;strong&gt;2、.NET框架要实现的梦想&lt;/strong&gt; .NET框架是为了实现下列目标： （1）、提供一个一致的面向对象的编程环境，而无论对象代码是在本地存储和执行，还是在本地执行但在 Internet 上分布，或者是在远程执行的。 （2）、提供一个将软件部署和版本控制冲突最小化的代码执行环境。 （3）、提供一个可提高代码（包括由未知的或不完全受信任的第三方创建的代码）执行安全性的代码执行环境。 （4）、提供一个可消除脚本环境或解释环境的性能问题的代码执行环境。 （5）、 使开发人员的经验在面对类型大不相同的应用程序（如基于 Windows 的应用程序和基于 Web 的应用程序）时保持一致。 （6）、按照工业标准生成所有通信，以确保基于 .NET框架的代码可与任何其他代码集成。 &lt;strong&gt;3、.NET框架的组成部分&lt;/strong&gt; .NET框架具有两个主要组件：&lt;strong&gt;公共语言运行库&lt;/strong&gt;和 &lt;strong&gt;.NET框架类库&lt;/strong&gt;。 对于一个刚刚学习.NET（无论是VB还是C#），接触的就是.NET框架类库，对于公共语言运行库只需要一般了解即可。 （1）、公共语言运行库是 .NET框架的基础。 您可以将运行库看作一个在执行时管理代码的代理，它提供内存管理、线程管理和远程处理等核心服务，并且还强制实施严格的类型安全以及可提高安全性和可靠性的其他形式的代码准确性。事实上，代码管理的概念是运行库的基本原则。 （2）、.NET框架类库 .NET 框架的另一个主要组件是类库，它是一个综合性的面向对象的可重用类型集合，您可以使用它开发多种应用程序，这些应用程序包括传统的命令行或图形用户界面 (GUI) 应用程序，也包括基于 ASP.NET 所提供的最新创新的应用程序（如 Web 窗体和 XML Web Services）。&lt;/p&gt;</description>
    </item>
    <item>
      <title>学习C#编程语言的几个阶段</title>
      <link>https://dodoro.chouxiangpai.com/archives/75/</link>
      <pubDate>Fri, 21 May 2010 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/75/</guid>
      <description>&lt;p&gt;很多人在自己的简历里都写着精通C#编程语言，可是现实中真的有那么多高手吗？下面是李建忠（《Microsoft .NET框架程序设计》作者）对学习C#语言达到的境界的几个层次： 1. 基本运用C#语法，在各种工具和示例代码的支持下，完成一些基本程序任务 2. 熟练掌握面向对象与组件构造，知其然亦知其所以然，完成一般小规模信息管理类软件项目开发任务 3. 深入理解CLR内核机制，对各种类型与.NET平台机制的优缺点、适用场合、效率有清晰把握，能够完成技术复杂度比较高的项目。 4. 能够游刃有余把握松耦合原则,精准运用各种语言构造，架构大型软件项目。 5. 能够站在计算机抽象、系统和历史发展的高度来理解和把握编程语言 个人觉得自己只能够是出于2到3这个阶段。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Visual Studio常用快捷键</title>
      <link>https://dodoro.chouxiangpai.com/archives/19/</link>
      <pubDate>Mon, 25 May 2009 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/19/</guid>
      <description>&lt;p&gt;窗口快捷键 Ctrl+W,W: 浏览器窗口 Ctrl+W,S: 解决方案管理器 Ctrl+W,C: 类视图 Ctrl+W,E: 错误列表 Ctrl+W,O: 输出视图 Ctrl+W,P: 属性窗口 Ctrl+W,T: 任务列表 Ctrl+W,X: 工具箱 Ctrl+W,B: 书签窗口 Ctrl+W,U: 文档大纲 Ctrl+D,B: 断点窗口 Ctrl+D,I: 即时窗口 Ctrl+Tab: 活动窗体切换 Ctrl+Shift+N: 新建项目 Ctrl+Shift+O: 打开项目 Ctrl+Shift+S: 全部保存 Shift+Alt+C: 新建类 Ctrl+Shift+A: 新建项&lt;/p&gt;
&lt;p&gt;编辑快捷键 Shift+Alt+Enter: 切换全屏编辑 Ctrl+B,T / Ctrl+K,K: 切换书签开关 Ctrl+B,N / Ctrl+K,N: 移动到下一书签 Ctrl+B,P: 移动到上一书签 Ctrl+B,C: 清除全部标签 Ctrl+I: 渐进式搜索 Ctrl+Shift+I: 反向渐进式搜索 Ctrl+F: 查找 Ctrl+Shift+F: 在文件中查找 F3: 查找下一个 Shift+F3: 查找上一个 Ctrl+H: 替换 Ctrl+Shift+H: 在文件中替换 Alt+F12: 查找符号(列出所有查找结果) Ctrl+Shift+V: 剪贴板循环 Ctrl+左右箭头键: 一次可以移动一个单词 Ctrl+上下箭头键: 滚动代码屏幕，但不移动光标位置。 Ctrl+Shift+L: 删除当前行 Ctrl+M,M: 隐藏或展开当前嵌套的折叠状态 Ctrl+M,L: 将所有过程设置为相同的隐藏或展开状态 Ctrl+M,P: 停止大纲显示 Ctrl+E,S: 查看空白 Ctrl+E,W: 自动换行 Ctrl+G: 转到指定行 Shift+Alt+箭头键: 选择矩形文本 Alt+鼠标左按钮: 选择矩形文本 Ctrl+Shift+U: 全部变为大写 Ctrl+U: 全部变为小写&lt;/p&gt;</description>
    </item>
    <item>
      <title>提高.NET性能的十大方法</title>
      <link>https://dodoro.chouxiangpai.com/archives/16/</link>
      <pubDate>Fri, 22 May 2009 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/16/</guid>
      <description>&lt;p&gt;&lt;strong&gt;第一、返回多个数据集&lt;/strong&gt; 　　如果你是用动态的SQL语句来返回多个数据集，那我建议你用存储过程来替代动态的SQL语句。是否把业务逻辑写到存储过程中，这个有点争议。但是我认为，把业务逻辑写到存储过程里面可以限制返回结果集的大小，减小网络数据的流量，在逻辑层也不用在过滤数据，这是一个好事情。 用SqlCommand对象的ExecuteReader方法返回一个强类型的业务对象，再调用NextResult方法来移动数据集指针来定位数据集。示例一演示了一个返回多个ArrayList强类型对象的例子。只从数据库中返回你需要的数据可以大大的减小你的服务器所耗用的内存。 第二、对数据进行分页 一个好的解决方案是写一个分页的存储过程，例子2是一个用于对Northwind数据库orders表的分页存储过程。你只需要传当前页码，每页显示的条数两个参数进来，存储过程会返回相应的结果。 在服务器端，我专门写了一个分页的控件来处理数据的分页，在这里，我用了第一个方法，在一个存储过程里面返回了两个结果集：数据记录总数和要求的结果集。 返回的记录总数取决于要执行查询，例如，一个where条件可以限制返回的结果集的大小。因为在分页界面中必须要根据数据集记录的大小来计算总的页数，所以必须要返回结果集的记录数。例如，如果一共有1000000条记录，如果用where条件就可以过滤成只返回1000条记录，存储过程的分页逻辑应该知道返回那些需要显示的数据。 &lt;strong&gt;第三、使用连接池&lt;/strong&gt; 要用连接池优化，有两条规则，第一，打开连接，处理数据，然后关闭连接。如果你必须在每次请求中多次打开或关闭连接，这好过一直打开一个边接，然后把它传到各个方法中。第二，用相同的连接字符串（或者用相同的用户标识，当你用集成认证的时候）。如果你没有用相同的连接字符串，如你用基于登录用户的连接字符串，这将不能利用连接池的优化功能。如果你用的是集成的论证，因为用户很多，所以你也不能充分利用连接池的优化功能。.NET CLR提供了一个数据性能计数器，它在我们需要跟踪程序性能特性的时候非常有用，当然也包括连接池的跟踪了。 无论你的应用程序什么时候要连在另一台机子的资源，如数据库，你都应该重点优化你连资源所花的时间，接收和发送数据的时间，以及往返回之间的次数。优化你的应用程序中的每一个处理点（process hop），它是提高你的应用的性能的出发点。 应用程序层包含与数据层连接，传送数据到相应的类的实例以及业务处理的逻辑。例如，在Community Server中，要组装一个Forums或者Threads集合，然后应用业务逻辑，如授权，更重要的，这里要完成缓存逻辑。 &lt;strong&gt;第四、充分利用ASP.NET缓存机制&lt;/strong&gt; 如果你的组件是要在Asp.net应用程序中运行，你只要把System.Web.dll引用到你的项目中就可以了。然后用HttpRuntime.Cache属性就可访问Cache了（也可以通过Page.Cache或HttpContext.Cache访问）。 有以下几条缓存数据的规则。第一，数据可能会被频繁的被使用，这种数据可以缓存。第二，数据的访问频率非常高，或者一个数据的访问频率不高，但是它的生存周期很长，这样的数据最好也缓存起来。第三是一个常常被忽略的问题，有时候我们缓存了太多数据，通常在一台X86的机子上，如果你要缓存的数据超过800M的话，就会出现内存溢出的错误。所以说缓存是有限的。换名话说，你应该估计缓存集的大小，把缓存集的大小限制在10以内，否则它可能会出问题。在Asp.net中，如果缓存过大的话也会报内存溢出错误，特别是如果缓存大的DataSet对象的时候。 &lt;strong&gt;第五、预请求缓存&lt;/strong&gt; 虽然Cache设计成用来保存某段时间的数据，而预请求缓存只是保存某个时期的某个请求的内容。如果某个请求的访问频率高，而且这个请求只需要提取，应用，修改或者更新数据一次。那么就可以预缓存该请求。我们举个例子来说明。 在CS的论坛应用程序中，每一个页面的服务器控件都要求得到用于决定它的皮肤（skin）的自定义的数据，以决定用哪个样式表及其它的一些个性化的东西。这里面的某些数据可能要长时间的保存，有些时间则不然，如控件的skin数据，它只需要应用一次，而后就可以一直使用。 要实现预请求缓存，用Asp.net 的HttpContext类，HttpContext类的实例在每一个请求中创建，在请求期间的任何地方都可以通过HttpContext.Current属性访问。HttpContext类有一个Items集合属性，在请求期间所有的对象和数据都被添加到这个集合中缓存起来。和你用Cache缓存访问频率高数据一样，你可以用HttpContext.Items缓存那些每个请求都要用到的基础数据。它背后的逻辑很简单：我们向HttpContext.Items中添加一个数据，然后再从它里面读出数据。 &lt;strong&gt;第六、后台处理优化&lt;/strong&gt; 你只要简单的把下面的这一行代码复制到你的页面中就可以实现了：&amp;lt;%@ PageOutputCache VaryByParams=”none” Duration=”60” %&amp;gt; 你就可以有效的利用第一次请求里生成的页面输出缓存内容，60秒后重新生成一道页面内容。这种技术其实也是运用一些低层的Cache API来实现。用页面输出缓存有几个参数可以配置，如上面所说的VaryByParams参数，该参数表示什么时候触发重输出的条件，也可以指定在Http Get或Http Post 请求模式下缓存输出。例如当我们设置该参数为VaryByParams=”Report”的时候，default.aspx?Report=1或者default.aspx?Report=2请求的输出都会被缓存起来。参数的值可以是多个用分号隔开参数。 许多人都没有意识到当用页面输出缓存的时候，asp.net也会生成HTTP头集（HTTP Header）保存在下游的　　虽然用页面输出缓存不提高你的应用程序性能，但是它能减少了从的服务器中加载已缓存页面内容的次数。当然，这仅限于缓存匿名用户可以访问的页面。因为一旦页面被缓存后，就不能再执行授权操作了。 &lt;strong&gt;第八、 用IIS6.0的Kernel Caching&lt;/strong&gt; 如果你的应用程序没用运行在IIS6.0(windows server 2003)中，那么你就失去了一些很好的提高应用程序性能的方法。在第七个方法中，我讲了用页面输出缓存提高应用程序的性能的方法。在IIS5.0中，当一个请求到来到IIS后，IIS会把它转给asp.net，当应用了页面输出缓存时，ASP.NET中的HttpHandler会接到该请求，HttpHandler从缓存中把内容取出来并返回。 &lt;strong&gt;第九、 用Gzip压缩数据&lt;/strong&gt; 除非你的CPU占用率太高了，才有必要用提升服务器性能的技巧。用gzip压缩数据的方法可以减少你发送到服务端的数据量，也可以提高页面的运行速度，同时也减少了网络的流量。怎么样更好的压缩数据取决于你要发送的数据，还有就是客户端的浏览器支不支持（IIS把用gzip压缩后的数据发送到客户端，客户端要支持gzip才能解析，IE6.0和Firefox都支持）。这样你的服务器每秒能多响应一些请求，同样，你也减少了发送响应的数据量，也就能多发送一些请求了。 好消息，gzip压缩已经被集成在IIS6.0中了，它比IIS5.0中gzip更好。不幸的是，在IIS6.0中启用gzip压缩，你不能在IIS6.0的属性对话中设置。IIS开发团队把gzip压缩功能开发出来了，但他们却忘了在管理员窗口中让管理员能很方便的启用它。要启用gzip压缩，你只能深入IIS6.0的xml配置文件中修改它的配置。 &lt;strong&gt;第十、 合理选择服务器控件的ViewState&lt;/strong&gt; ViewState是asp.net中的一个特性，它用于把生成页面要用的一状态值保存在一个隐藏域中。当页面被回传到服务器时，服务器要解析，校验和应用ViewState中的数据以还原页面的控件树。ViewState是一个非常有用的特性，它能持久化客户端的状态而不用cookie或者服务器的内存。大部分的服务器控件都是用ViewState来持久化那些在页面中与用户交互的元素的状态值。例如，用以保存用于分页的当前页的页码。 用ViewState会带来一些负面的影响。首先，它加大的服务器的响应和请求的时间。其次，每次回传时都增加了序列化和反序列化数据的时间。最后，它还消耗了服务器更多的内存。&lt;/p&gt;</description>
    </item>
    <item>
      <title>.NET框架简单介绍</title>
      <link>https://dodoro.chouxiangpai.com/archives/14/</link>
      <pubDate>Thu, 21 May 2009 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/14/</guid>
      <description>&lt;p&gt;我第一次接触.NET是在大一暑假（2005年），那时候学校有自己专门的网站，也是用ASP.NET开发的，而且全部由学生来管理开发，刚开始仅仅是出于对网站和编程的兴趣（当然也是为了能够谋求一个勤工助学的岗位）。 那个夏天很热，不过参加培训的地方很舒服，在一个大教室里，有空调。那时候对于网站开发、项目开发和.NET都是第一次。第一次接触css，第一次接触html，第一次接触C#，第一次接触.NET框架，第一次接触IIS，第一次接触项目概念&amp;hellip; 之前我自学过面向对象，对“类、对象、继承、多态”这些概念是懵懵懂懂的，培训之后也还是一知半解。 什么是.NET？这个问题解释太多了，我还是引用微软官方的解释： “.NET 是 Microsoft 的用以创建 XML Web 服务（下一代软件）平台，该平台将信息、设备和人以一种统一的、个性化的方式联系起来 “借助于 .NET 平台，可以创建和使用基于 XML 的应用程序、进程和 Web 站点以及服务，它们之间可以按设计、在任何平台或智能设备上共享和组合信息与功能，以向单位和个人提供定制好的解决方案 “.NET 是一个全面的产品家族，它建立在行业标准和 Internet 标准之上，提供开发（工具）、管理（服务器）、使用（构造块服务和智能客户端）以及 XML Web 服务体验（丰富的用户体验）。.NET 将成为您今天正在使用的 Microsoft 应用程序、工具和服务器的一部分，同时，新产品不断扩展 XML Web 的服务能力以满足您的所有业务需求。” 历史永远记住这一刻，美国时间2000年6月22日，全球IT界为之关注。 后来又学习C++，学习MFC，综合MFC和.NET框架，然后又看了侯捷先生的文章，终于对于框架编程有了比较深的理解，所以后来学习JavaScript框架等等都可以站在一个高度上理解了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>.NET程序员重点学习和积累的技术要点</title>
      <link>https://dodoro.chouxiangpai.com/archives/11/</link>
      <pubDate>Thu, 21 May 2009 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/11/</guid>
      <description>&lt;p&gt;我知道，一个人的生命是有限的，而工作时间更加有限（我的价值观是工作和事业是为了让生活更好）。基于此，我现在只能在有限的时间里做有限的事情，下面是自己对自己的规划： 一、职业规划 首先，踏踏实实做一个技术人员，在工作总学习和提高自己；然后，能够凭借自己的能力做到项目开发经理；最后，要么能够在企业里做管理层，要么回学校讲课，无论如何最好能够出一本技术书籍。 二、深入学习的技术 1、最重要的：C#和ASP.NET技术，JQuery技术，设计模式，面向对象技术，css和页面布局技术，网站架构技术（squid，memcached等），SQL Sever数据库技术； 2、其次的：PHP技术，Linux技术、MySQL技术； 3、最为基础和技术提高的：C语言技术，数据结构，算法技术，计算机技术（cpu，内存，IO等和程序设计相关的技术）。 三、最值得我去深入研究的技术 以下这些技术是我必须要去深入研究的，而且要花功夫研究： 1、C#语言、.NET框架、C语言； 2、数据结构、面向对象、设计模式、软件工程； 3、Memcached、JQuery(相当于JavaScript)、css。&lt;/p&gt;</description>
    </item>
    <item>
      <title>c# params,params用法,代码</title>
      <link>https://dodoro.chouxiangpai.com/archives/77/</link>
      <pubDate>Thu, 21 May 2009 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/77/</guid>
      <description>&lt;p&gt;在C#语言里，params 关键字可以指定在参数数目可变处采用参数的方法参数。 把数组作为参数的一个关键字，目的是做出如 a(parm1,parm2.parm3,&amp;hellip;.parmn) ，这样调用方式的函数，也就是同一种类型的不定个数参数列表，如果声明时没用parms关键字就如下调用，实际上是一样的 a(new type[]{parm1,parm2.parm3,&amp;hellip;.parmn}); 在方法声明中的 params 关键字之后不允许任何其他参数，并且在方法声明中只允许一个 params 关键字，下面是具体示例代码： using System; public class MyClass { public static void UseParams(params int[] list) { for (int i = 0 ; i &amp;lt; list.Length; i++) { Console.WriteLine(list[i]); } Console.WriteLine(); } public static void UseParams2(params object[] list) { for (int i = 0 ; i &amp;lt; list.Length; i++) { Console.WriteLine(list[i]); } Console.WriteLine(); } static void Main() { UseParams(1, 2, 3); UseParams2(1, &amp;lsquo;a&amp;rsquo;, &amp;ldquo;test&amp;rdquo;); // An array of objects can also be passed, as long as // the array type matches the method being called. int[] myarray = new int[3] {10,11,12}; UseParams(myarray); } }&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#基础学习：深入理解什么是委托</title>
      <link>https://dodoro.chouxiangpai.com/archives/69/</link>
      <pubDate>Thu, 21 May 2009 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/69/</guid>
      <description>&lt;p&gt;深入理解什么是委托 委托就是函数指针，先定义了一个委托，然后将它的实例指向某个特定的方法(函数)，通过这个委托的实例就可以调用其方法。 1、要想使得委托可以工作，必须有定义好的方法(函数)，这是一种方式； 2、可以通过匿名方法来作为委托参数的一个代码块。 匿名方法其实就是在实例化委托的时候给委托定义了代码块，可以实现某些功能，再调用委托的时候就可以直接使用这些代码块了。 注意：匿名方法不能跳转到外部，外部也不能跳转到匿名方法；匿名方法内部不能访问安全代码，也不能在外部使用ref和out参数。 深入理解集合 在C#中应该能够灵活地使用数组列表、字典和集合，这样才可以获取程序的最佳性能。最主要的有下面这些：集合；数组列表；栈；队列；有序列表；字典。集合大都可以通过语句来实现访问： forreach(string item in Items) { writeline(item); } 1、数组列表(ArrayList) 常用的方法Add,Insert,RemoveAt,AddRange。 2、Stack类 适合于处理应用程序使用完后就删除的临时数据项，先进后出。 3、Queue类 和Stack差不多，只不过是先进先出。 4、SortedList类 在使用SortedList类的时候，每一项都会指定一个用于引用改项的标识键。可以通过GetKeyList()和GetValueList()来获取键和值。 5、字典和散列 字典和散列总是会跟HashTable联系起来。 深入理解泛型 引入泛型最大的好处就是避免大量的装箱和拆箱操作，而且能够简化大量代码。&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#常用函数列表(二)</title>
      <link>https://dodoro.chouxiangpai.com/archives/79/</link>
      <pubDate>Thu, 21 May 2009 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/79/</guid>
      <description>&lt;p&gt;11、string str=Request.QueryString[&amp;ldquo;变量&amp;rdquo;]; 用超链接传送变量。如在任一页中建超链接href=&amp;ldquo;Edit.aspx?fbid=&amp;ldquo;23&amp;quot;点击.在Edit.aspx页中取值：String str=Request.QueryString[&amp;ldquo;fdid&amp;rdquo;]; 12、DOC对象.CreateElement(&amp;ldquo;新建节点名&amp;rdquo;); 创建XML文档新节点 13、父节点.AppendChild(子节点)； 将新建的子节点加到XML文档父节点下 14、 父节点.RemoveChild(节点); 删除节点 15、Response Response.Write(&amp;ldquo;字串&amp;rdquo;)；Response.Write(变量)；向页面输出。Response.Redirect(&amp;ldquo;URL地址&amp;rdquo;）； 跳转到URL指定的页面 16、char.IsWhiteSpce(字串变量，位数)&amp;ndash;逻辑型 查指定位置是否空字符；如：string str=&amp;ldquo;中国人&amp;quot;Response.Write(char.IsWhiteSpace(str,2));//结果为：True, 第一个字符是0位，2是第三个字符。 17、char.IsPunctuation(&amp;lsquo;字符&amp;rsquo;) &amp;ndash;逻辑型 查字符是否是标点符号如：Response.Write(char.IsPunctuation(&amp;lsquo;A&amp;rsquo;)); //返回：False 18、(int)&amp;lsquo;字符&amp;rsquo; 把字符转为数字，查代码点，注意是单引号。如：Response.Write((int)&amp;lsquo;中&amp;rsquo;); //结果为中字的代码：20013 19、(char)代码 把数字转为字符，查代码代表的字符。如：Response.Write((char)22269); //返回“国”字。 20、 Trim() 清除字串前后空格&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#最常用函数</title>
      <link>https://dodoro.chouxiangpai.com/archives/71/</link>
      <pubDate>Thu, 21 May 2009 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/71/</guid>
      <description>&lt;p&gt;以下是我们在开发过程中最为常用的一些函数： 1、DateTime 数字型 System.DateTime currentTime=new System.DateTime(); 1.1 取当前年月日时分秒 currentTime=System.DateTime.Now; 1.2 取当前年 int 年=currentTime.Year; 1.3 取当前月 int 月=currentTime.Month; 1.4 取当前日 int 日=currentTime.Day; 1.5 取当前时 int 时=currentTime.Hour; 1.6 取当前分 int 分=currentTime.Minute; 1.7 取当前秒 int 秒=currentTime.Second; 1.8 取当前毫秒 int 毫秒=currentTime.Millisecond; （变量可用中文） 2、Int32.Parse(变量) Int32.Parse(&amp;ldquo;常量&amp;rdquo;) 字符型转换 转为32位数字型 3、 变量.ToString() 字符型转换 转为字符串 12345.ToString(&amp;ldquo;n&amp;rdquo;); //生成 12,345.00 12345.ToString(&amp;ldquo;C&amp;rdquo;); //生成 ￥12,345.00 12345.ToString(&amp;ldquo;e&amp;rdquo;); //生成 1.234500e+004 12345.ToString(&amp;ldquo;f4&amp;rdquo;); //生成 12345.0000 12345.ToString(&amp;ldquo;x&amp;rdquo;); //生成 3039 (16进制) 12345.ToString(&amp;ldquo;p&amp;rdquo;); //生成 1,234,500.00% 4、变量.Length 数字型 取字串长度： 如： string str=&amp;ldquo;中国&amp;rdquo; int Len = str.Length ; //Len是自定义变量， str是求测的字串的变量名 5、System.Text.Encoding.Default.GetBytes(变量) 字码转换 转为比特码 如：byte[] bytStr = System.Text.Encoding.Default.GetBytes(str); 然后可得到比特长度： len = bytStr.Length; 6、System.Text.StringBuilder(&amp;quot;&amp;quot;) 字符串相加，（+号是不是也一样？） 如：System.Text.StringBuilder sb = new System.Text.StringBuilder(&amp;quot;&amp;quot;); sb.Append(&amp;ldquo;中华&amp;rdquo;); sb.Append(&amp;ldquo;人民&amp;rdquo;); sb.Append(&amp;ldquo;共和国&amp;rdquo;); 7、变量.Substring(参数1,参数2); 截取字串的一部分，参数1为左起始位数，参数2为截取几位。 如：string s1 = str.Substring(0,2); 8、String user_IP=Request.ServerVariables[&amp;ldquo;REMOTE_ADDR&amp;rdquo;].ToString(); 取远程用户IP地址 9、穿过代理服务器取远程用户真实IP地址： if(Request.ServerVariables[&amp;ldquo;HTTP_VIA&amp;rdquo;]!=null){ string user_IP=Request.ServerVariables[&amp;ldquo;HTTP_X_FORWARDED_FOR&amp;rdquo;].ToString(); }else{ string user_IP=Request.ServerVariables[&amp;ldquo;REMOTE_ADDR&amp;rdquo;].ToString(); } 10、 Session[&amp;ldquo;变量&amp;rdquo;]; 存取Session值； 如，赋值： Session[&amp;ldquo;username&amp;rdquo;]=&amp;ldquo;小布什&amp;rdquo; 取值： Object objName=Session[&amp;ldquo;username&amp;rdquo;]; String strName=objName.ToString(); 清空： Session.RemoveAll();&lt;/p&gt;</description>
    </item>
    <item>
      <title>委托用法,C#源代码</title>
      <link>https://dodoro.chouxiangpai.com/archives/81/</link>
      <pubDate>Thu, 21 May 2009 00:00:00 +0000</pubDate>
      <guid>https://dodoro.chouxiangpai.com/archives/81/</guid>
      <description>&lt;p&gt;1、委托的概念 委托是C#一个非常重要的概念，也是很有用的，因为委托和事件结合起来使用可以完成很多功能（委托是事件的基础），而且可以通过委托来实现函数的匿名方法（通过将委托与命名方法或匿名方法关联，可以实例化委托）。 C#的委托类似于 C++ 中的函数指针；但是，委托是类型安全和可靠的。 2、委托的用法 委托类型声明的格式如下： public delegate void TestDelegate(string message);delegate 关键字用于声明一个引用类型，该引用类型可用于封装命名方法或匿名方法。 为了与命名方法一起使用，委托必须用具有可接受签名的方法进行实例化。有关方法签名中允许的方差度的更多信息，请参见委托中的协变和逆变。为了与匿名方法一起使用，委托和与之关联的代码必须一起声明。 3、实现代码 下面用C#代码来说明如何使用委托（参考自微软msdn）：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;using&lt;/span&gt; System;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Declare delegate -- defines required signature:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;delegate&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; SampleDelegate(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MainClass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Regular method that matches signature:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; SampleDelegateMethod(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Main()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Instantiate delegate with named method:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SampleDelegate d1 = SampleDelegateMethod;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Instantiate delegate with anonymous method:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SampleDelegate d2 = &lt;span style=&#34;color:#66d9ef&#34;&gt;delegate&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Invoke delegate d1:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;d1(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Invoke delegate d2:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;d2(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34; World&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
  </channel>
</rss>
