<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>技术 on 冯威的博客</title><link>https://fwhyy.com/categories/%E6%8A%80%E6%9C%AF/</link><description>Recent content in 技术 on 冯威的博客</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Sat, 08 Aug 2026 10:34:00 +0800</lastBuildDate><atom:link href="https://fwhyy.com/categories/%E6%8A%80%E6%9C%AF/atom.xml" rel="self" type="application/rss+xml"/><item><title>一次 MySQL 8 UPDATE 子查询慢 SQL 的优化过程</title><link>https://fwhyy.com/2026/08/optimizing-mysql-8-update-subquery-slow-sql/</link><pubDate>Sat, 08 Aug 2026 10:34:00 +0800</pubDate><guid>https://fwhyy.com/2026/08/optimizing-mysql-8-update-subquery-slow-sql/</guid><description>&lt;p&gt;本文为 AI 整理。&lt;/p&gt;
&lt;p&gt;最近排查了一条 MySQL 8 的 &lt;code&gt;UPDATE&lt;/code&gt; SQL。表的数据量不算特别大，主表约 30 万行，关联表约 1 万多行，但会导致死锁&lt;/p&gt;
&lt;p&gt;这个问题比较典型，记录一下排查过程。&lt;/p&gt;
&lt;h2 id="1-原始-sql"&gt;1. 原始 SQL&lt;/h2&gt;
&lt;p&gt;业务逻辑很简单：根据关联表中的某个父级 ID 找到一批业务 ID，再更新主表对应记录。&lt;/p&gt;
&lt;p&gt;为了脱敏，SQL 简化如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;main_table&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;已处理&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ObjectID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;related_id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;relation_table&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParentObjectID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;xxx&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;最开始的执行计划大致是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;UPDATE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;main_table
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;type = index
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rows = 309000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;DEPENDENT SUBQUERY
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;relation_table
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;type = ALL
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rows = 12000
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里有两个明显的问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;主表扫描约 30 万行；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;子查询是 &lt;code&gt;DEPENDENT SUBQUERY&lt;/code&gt;，而且关联表还是 &lt;code&gt;ALL&lt;/code&gt; 全表扫描。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也就是说，MySQL 会扫描主表大量记录，并反复执行关联子查询。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="2-第一轮优化给子查询加联合索引"&gt;2. 第一轮优化：给子查询加联合索引&lt;/h2&gt;
&lt;p&gt;查询条件是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParentObjectID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;同时还需要返回：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;related_id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;因此增加联合索引：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INDEX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;idx_parent_related&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;relation_table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ParentObjectID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;related_id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;索引顺序很重要：&lt;/p&gt;</description></item><item><title>生产环境 MySQL Lock wait timeout exceeded 排查实战</title><link>https://fwhyy.com/2026/08/troubleshooting-mysql-lock-wait-timeout-exceeded-in-production/</link><pubDate>Wed, 05 Aug 2026 15:39:00 +0800</pubDate><guid>https://fwhyy.com/2026/08/troubleshooting-mysql-lock-wait-timeout-exceeded-in-production/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;案例背景&lt;/strong&gt;：某业务系统在执行单条数据删除时频繁报错 &lt;code&gt;Lock wait timeout exceeded&lt;/code&gt;，初步怀疑是数据量过大导致超时，经排查实为&lt;strong&gt;锁竞争&lt;/strong&gt;问题。本文完整记录从现象到根因的排查过程，以及 MySQL 8.0 下的适配方案，供参考。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一问题现象"&gt;一、问题现象&lt;/h2&gt;
&lt;p&gt;业务系统调用删除接口时返回异常：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Message: DELETE FROM d_xxx 
WHERE ObjectID=&amp;#39;57736651-819e-4f9c-acb9-ceef7c49a2ef&amp;#39;

InnerException: Lock wait timeout exceeded; try restarting transaction
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;关键特征&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SQL 是&lt;strong&gt;单条精确删除&lt;/strong&gt;（&lt;code&gt;WHERE ObjectID = 'xxx'&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;堆栈显示为业务表单删除（&lt;code&gt;RemoveFormData&lt;/code&gt; → &lt;code&gt;RemoveSubFormData&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;超时时间约 50 秒（MySQL 默认 &lt;code&gt;innodb_lock_wait_timeout&lt;/code&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="二初步判断不是数据量问题"&gt;二、初步判断：不是数据量问题&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;误判点&lt;/th&gt;
					&lt;th&gt;实际情况&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;DELETE&lt;/code&gt; 语句&lt;/td&gt;
					&lt;td&gt;单条精确删除，扫描行数极少&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;超时时间&lt;/td&gt;
					&lt;td&gt;如果是数据量大，应该是执行时间长；但这里是&lt;strong&gt;等待锁&lt;/strong&gt;的时间长&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;结论&lt;/strong&gt;：这是典型的 &lt;strong&gt;InnoDB 锁等待超时&lt;/strong&gt;，即当前事务需要获取的行锁/间隙锁被其他事务持有，等待超过阈值后被强制回滚。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="三排查流程step-by-step"&gt;三、排查流程（Step by Step）&lt;/h2&gt;
&lt;h3 id="step-1定位活跃事务"&gt;Step 1：定位活跃事务&lt;/h3&gt;
&lt;p&gt;通过 &lt;code&gt;INNODB_TRX&lt;/code&gt; 查看当前未提交的事务：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trx_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trx_mysql_thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trx_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trx_started&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TIMESTAMPDIFF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SECOND&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trx_started&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trx_idle_seconds&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INNODB_TRX&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trx_state&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;RUNNING&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trx_started&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;发现&lt;/strong&gt;：存在一个已运行数分钟甚至数小时的 &lt;code&gt;RUNNING&lt;/code&gt; 事务，线程 ID 为 &lt;code&gt;xxx&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="step-2确认阻塞关系mysql-57-写法"&gt;Step 2：确认阻塞关系（MySQL 5.7 写法）&lt;/h3&gt;
&lt;p&gt;在 MySQL 5.7 中，可通过以下 SQL 确认谁阻塞了谁：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trx_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;waiting_trx_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trx_mysql_thread_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;waiting_thread&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trx_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;blocking_trx_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trx_mysql_thread_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;blocking_thread&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INNODB_LOCK_WAITS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INNODB_TRX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trx_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blocking_trx_id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INNODB_TRX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trx_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;requesting_trx_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="-step-3mysql-80-的坑"&gt;⚠️ Step 3：MySQL 8.0 的坑&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;如果使用的是 MySQL 8.0&lt;/strong&gt;，执行上述 SQL 会报错：&lt;/p&gt;</description></item><item><title>聊聊最近的 Vibe Coding 经历</title><link>https://fwhyy.com/2026/07/recent-vibe-coding-experience/</link><pubDate>Mon, 27 Jul 2026 08:50:00 +0800</pubDate><guid>https://fwhyy.com/2026/07/recent-vibe-coding-experience/</guid><description>&lt;p&gt;&lt;img src="https://img.fwhyy.com/%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_cfc9d8fa-7388-4997-8d38-4a3ef041a5b0.webp" alt="" loading="lazy" decoding="async"&gt;

最近花了很大精力在 Vibe Coding 上，当然也做出了不少东西，时间被 token 占据着，公众号也断更了一段时间。&lt;/p&gt;
&lt;p&gt;最近一个很大的感触是使用 AI ，思维方式得转过来。第一步是&amp;quot;相信它能&amp;quot;，不信就不会去试，不试就永远停留在浅层用法；第二步是探索，在探索中碰到&amp;quot;不能&amp;quot;；碰到不能时多问一句：是模型真不行，还是我方法不对？换个提示、拆下任务、补点上下文，很多&amp;quot;不能&amp;quot;其实是&amp;quot;还不会用&amp;quot;。如此反复。&lt;/p&gt;
&lt;p&gt;还记得春节前我有一个功能的想法，在网页 Chat 模式下沟通几轮得到一个原型界面，还是会安排开发人员去进行最终的实现。&lt;/p&gt;
&lt;p&gt;春节期间，我决定得要自己动手去实践，于是我找了个中转站充了 50 块，客户端使用 Claude Code，接中转站的模型，就开始了 Vibe Coding 之旅。&lt;/p&gt;
&lt;p&gt;开发了一个研发内部使用的平台，将需求、任务、待办、缺陷管理起来，后面还陆续加入了文档中心、分享中心等功能。&lt;/p&gt;
&lt;p&gt;研发管理类的工具有很多，为什么还要自己去重复造轮子呢？&lt;/p&gt;
&lt;p&gt;原因很简单，要想使用 AI 给团队内部提效、要想利用 AI 给客户带来价值，就必须要对 AI 有深入的了解才行。去真正做出一些东西，才可以更好的了解。&lt;/p&gt;
&lt;p&gt;我自认为对开发非常了解，对研发内部的管理业务也很清楚，理论上来说，应该很容易借助 AI 的能力把这个系统给开发完成，但其中还是碰到了很多的问题。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;中转站的模型能力时好时坏，有时候还会碰到直接挂掉&lt;/li&gt;
&lt;li&gt;UI 一致性的问题：同样的 Tab 切换，在不同的功能模块都自成一个体系&lt;/li&gt;
&lt;li&gt;有时候只是想问一下情况或者让分析一些内容，但话音刚落，AI 马上就开始改代码，就像是一个初级程序员一样，特别喜欢直接上手改代码&lt;/li&gt;
&lt;li&gt;添加新功能，之前的功能给改坏了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因为要做的是一个需要持续迭代的软件系统，不是一个 Demo，所以并不是说一句话让 AI 生成一个开盲盒式的系统就完事了，需要提前做很多很多的准备。&lt;/p&gt;
&lt;p&gt;比如，以下内容需要沉淀到文档里面：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;前后端都需要使用什么技术栈；&lt;/li&gt;
&lt;li&gt;数据库的设计、接口的定义；&lt;/li&gt;
&lt;li&gt;每个功能模块的描述，业务目的是什么，以及该怎么去实现。&lt;/li&gt;
&lt;li&gt;每次 AI 修改完代码，修改了什么内容？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2026/20260720151323.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;开始的时候会先做静态页的 UI 原型，包括布局和一些交互，慢慢调到比较满意之后，再让 AI 把它转换成前端的代码。等整个系统的结构差不多构建起来之后，这个就弃用了，直接让 AI 基于现有的 UI 风格进行新功能的开发。&lt;/p&gt;
&lt;p&gt;一种有效的方法是，当一个事情反复沟通才能达到效果，我会让 AI 对多轮对话进行总结，有些规则可以沉淀到 CLAUDE.md 、AGENTS.md 中，有些是沟通话术的问题，我后续可以进行调整。&lt;/p&gt;
&lt;p&gt;中转站前后换了好几个，最后的结论还是买正版吧。中转站质量掺水不说，而且还极其不稳定。现在模型能力越来越强，不管是用国内的还是国外的，比如 K3、GLM 5.2、DeepSeek V4 或者 GPT 5.6 来做开发，都没有任何问题。&lt;/p&gt;
&lt;p&gt;从 3 月 11 号开始，我的主力工具就是 codex 了。从开始的 Plus 到后来使用 Pro，目前 Pro 的额度也渐渐变得不够用了，好在 Tibo 经常会进行重置。&lt;/p&gt;
&lt;p&gt;到现在，仅在 Codex 上的 token 消耗量已经接近 200 亿了。下面就说说这 200 亿的 token 都做了些什么。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2026/20260726175607.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;1、AI 员工平台&lt;/p&gt;
&lt;p&gt;起初是想将内部的一些问数场景，知识库场景，利用 AI 来提升一些效率。后来跟 ChatGPT 聊着聊着，就萌生了直接做一个平台的想法。&lt;/p&gt;
&lt;p&gt;GPT 告诉我，AI 员工也是一个员工，企业需要给他提供相应的办公环境、知识技能培训等等。我觉得这个思路不错，所以就按照员工和企业这两个维度来构建这个平台。&lt;/p&gt;</description></item><item><title>从 Vibe Coding 到 Harness Engineering</title><link>https://fwhyy.com/2026/05/from-vibe-coding-to-harness-engineering/</link><pubDate>Sat, 16 May 2026 16:05:00 +0800</pubDate><guid>https://fwhyy.com/2026/05/from-vibe-coding-to-harness-engineering/</guid><description>&lt;p&gt;春节之后一直在深度 Vibe Coding 做一些事情。将最近收集的资料整理后，在 Codex 中使用 baoyu-slide-deck 这个 skill 生成了一组 ppt 图片。&lt;/p&gt;
&lt;p&gt;Vibe Coding 现在应该都或多或少尝试过，但都停留在爱简单沟通几轮，做出一个 Demo ，至于效果怎么样，在代码写完之前是不知道的，就像是开盲盒。&lt;/p&gt;
&lt;p&gt;所以很多人就觉得 Vide Coding 只能做些示例，还不能上生产。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2026/20260720160441.webp" alt="Pasted image 20260720160441" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Vibe 也经历了一些不同的阶段，从提示词、到上下文，再到现在的 Harness Engineering 。&lt;/p&gt;
&lt;p&gt;简单来说，我们不只是给模型上下文，而是要为 Agent 构建一整套可执行、可验证、可恢复、可追溯的工程系统。&lt;/p&gt;
&lt;p&gt;这也是我理解的 Vibe Coding。&lt;/p&gt;
&lt;p&gt;它不应该只是“凭感觉让 AI 写代码”。在生产环境里，它必须是工程化的：人负责表达目标、拆解任务、定义边界和验收标准，Agent 负责搜索代码、生成实现、运行测试和提交变更。&lt;/p&gt;
&lt;p&gt;真正的难点，不是让 AI 写出代码，而是让它在复杂代码库里写对代码。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2026/20260720160500.webp" alt="Pasted image 20260720160500" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;新项目相对容易一些，可以从第一天就按 Agent-Native 的方式建设：目录清晰、规则稳定、测试可执行、文档结构化。&lt;/p&gt;
&lt;p&gt;历史项目会更难。几十万行代码里有大量隐性知识：哪些字段有单位约束，哪些链路不能乱改，哪些历史实现只是当时留下的反模式。对 Agent 来说，没被写进代码库、文档、规则和测试里的知识，就等于不存在。&lt;/p&gt;
&lt;p&gt;所以 Harness 的核心价值，是把团队经验外部化。Rules 告诉 Agent 标准是什么，Skills 告诉 Agent 怎么做，Wiki 告诉 Agent 系统是什么样，Changes 记录 Agent 做了什么。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2026/20260720160515.webp" alt="Pasted image 20260720160515" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;再配合需求分析、编码实现、评审、单测、CI、部署验证等，AI 产出才可能从“看起来能跑”，变成“质量可控”。&lt;/p&gt;
&lt;p&gt;模型能力决定上限，工程能力决定下限。模型越强，越需要更好的上下文、更严格的约束和更完整的验证闭环。&lt;/p&gt;
&lt;p&gt;对研发团队来说，核心竞争力正在迁移。未来重要的不只是会写代码，而是会设计一个让 Agent 稳定工作的系统。&lt;/p&gt;
&lt;p&gt;谁能把需求讲清楚、把边界定清楚、把规则写清楚、把验证做清楚，谁就更可能真正把 AI 变成生产力。&lt;/p&gt;</description></item><item><title>从养一只“小龙虾”开始，理解 OpenClaw 的本质</title><link>https://fwhyy.com/2026/03/starting-from-raising-a-crayfish-understanding-the-essence-of-openclaw/</link><pubDate>Wed, 11 Mar 2026 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2026/03/starting-from-raising-a-crayfish-understanding-the-essence-of-openclaw/</guid><description>&lt;p&gt;和去年的 DeepSeek 一样，今年龙虾（OpenClaw）火爆全网了。最近也养了一只。介绍怎么安装之前先了解下龙虾到底是什么。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="一概念openclaw-到底是什么"&gt;一、概念：OpenClaw 到底是什么&lt;/h2&gt;
&lt;p&gt;OpenClaw 是一个把大模型能力“接到消息入口”的开源 Agent 框架。&lt;/p&gt;
&lt;p&gt;它不是单纯聊天，而是让 AI 通过 IM 渠道持续接收任务、调用工具、回传结果。能干活是和之前 AI Chat 最大的区别。&lt;/p&gt;
&lt;h2 id="二为什么说是养虾呢"&gt;二、为什么说是“养”虾呢？&lt;/h2&gt;
&lt;p&gt;之所以说是养，首先需要提供生长环境，其次给它饲料。&lt;/p&gt;
&lt;p&gt;那么什么是环境呢？我们自己的 PC 电脑（Mac Mini 或其他）、或者一个云主机，这个是环境。有了环境安装上龙虾之后，还不能使用，因为还需要饲料。&lt;/p&gt;
&lt;p&gt;Token 就是饲料，饲料分好坏，进口厂家有 OpenAI、Anthropic、Google ，国产的有 GLM、MiniMax、Kimi 等。&lt;/p&gt;
&lt;p&gt;饲养人的方式方法以及饲料的好坏都决定着龙虾的成长。&lt;/p&gt;
&lt;h2 id="三发展历程"&gt;三、发展历程&lt;/h2&gt;
&lt;p&gt;OpenClaw 的发展非常快。从 25 年 11 月到现在，短短几个月的时间，现在 GitHub 上的 Star 数已经 32 万了。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2026/202603191718298.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;OpenClaw 是奥地利开发者 Peter Steinberger 利用周末时间搞出来的，估计他当时也没想到会这么火爆。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2025 年 11 月：OpenClaw 诞生，当时的名字还叫 ClawdBot ,并使龙虾作为图标&lt;/li&gt;
&lt;li&gt;2026 年 1 月 27：因 ClawdBot 的 Clawd 的发音和 Claude 类似，收到了Anthropic 的商标警告，被迫改名为 Moltbot&lt;/li&gt;
&lt;li&gt;2026 年 1 月 30：再次改名为 OpenClaw ，这个名字一直沿用到现在&lt;/li&gt;
&lt;li&gt;2026 年 2 月 14：创始人 Peter 加入 OpenAI ，项目移交开源基金会运营。OpenAI 赞助但项目保持独立。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="四技术架构"&gt;四、技术架构&lt;/h2&gt;
&lt;p&gt;下面用数字员工的概念来帮助理解 OpenClaw 的架构，假设我们部门来了一个数字员工，怎样才能让他能正常干活呢？&lt;/p&gt;
&lt;h3 id="1-核心大脑与调度中枢gateway--pi-agent"&gt;1. 核心大脑与调度中枢（Gateway &amp;amp; Pi Agent）&lt;/h3&gt;
&lt;p&gt;数字员工本质上是一个“能思考+能执行”的系统。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gateway（网关）：相当于“调度中枢”，负责统一接收任务、管理运行状态，以及定时触发任务。&lt;/li&gt;
&lt;li&gt;Pi Agent（推理引擎）：相当于“思考引擎”，通过一个循环机制不断工作：&lt;strong&gt;接收任务 → 拆解规划 → 调用工具 → 检查结果 → 继续下一步&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-沟通渠道与执行载体channels--nodes"&gt;2. 沟通渠道与执行载体（Channels &amp;amp; Nodes）&lt;/h3&gt;
&lt;p&gt;数字员工需要能接任务，也需要能有环境去执行任务。&lt;/p&gt;</description></item><item><title>推荐两个 Obsidian 插件</title><link>https://fwhyy.com/2026/03/recommend-two-obsidian-plugins/</link><pubDate>Mon, 09 Mar 2026 21:54:00 +0800</pubDate><guid>https://fwhyy.com/2026/03/recommend-two-obsidian-plugins/</guid><description>&lt;p&gt;最近，深入究了下 Obsidian 的使用，体验上提升了不少。主要涉及下面的两个插件。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="dataview-插件"&gt;Dataview 插件&lt;/h2&gt;
&lt;p&gt;Obsidian 其实有一个数据库的功能，可以对一些数据进行汇总筛选。但 Dataview 插件的功能还是要强大很多。&lt;/p&gt;
&lt;p&gt;年初听脱不花和马伯庸的对谈，提到了写日记，我计划在 2026 年也效仿下，于是我在 Obsidian 的日记模板中添加一个栏目：今天发生了什么？每天发生的流水账就记录在这个下面。&lt;/p&gt;
&lt;p&gt;但有个问题，我怎么方便看每天都发生了什么呢？于是就用到了 Dataview 。&lt;/p&gt;
&lt;p&gt;创建了一个新的笔记，名字叫：今天发生了什么？ 这个笔记的内容是一段脚本：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;span class="lnt"&gt;50
&lt;/span&gt;&lt;span class="lnt"&gt;51
&lt;/span&gt;&lt;span class="lnt"&gt;52
&lt;/span&gt;&lt;span class="lnt"&gt;53
&lt;/span&gt;&lt;span class="lnt"&gt;54
&lt;/span&gt;&lt;span class="lnt"&gt;55
&lt;/span&gt;&lt;span class="lnt"&gt;56
&lt;/span&gt;&lt;span class="lnt"&gt;57
&lt;/span&gt;&lt;span class="lnt"&gt;58
&lt;/span&gt;&lt;span class="lnt"&gt;59
&lt;/span&gt;&lt;span class="lnt"&gt;60
&lt;/span&gt;&lt;span class="lnt"&gt;61
&lt;/span&gt;&lt;span class="lnt"&gt;62
&lt;/span&gt;&lt;span class="lnt"&gt;63
&lt;/span&gt;&lt;span class="lnt"&gt;64
&lt;/span&gt;&lt;span class="lnt"&gt;65
&lt;/span&gt;&lt;span class="lnt"&gt;66
&lt;/span&gt;&lt;span class="lnt"&gt;67
&lt;/span&gt;&lt;span class="lnt"&gt;68
&lt;/span&gt;&lt;span class="lnt"&gt;69
&lt;/span&gt;&lt;span class="lnt"&gt;70
&lt;/span&gt;&lt;span class="lnt"&gt;71
&lt;/span&gt;&lt;span class="lnt"&gt;72
&lt;/span&gt;&lt;span class="lnt"&gt;73
&lt;/span&gt;&lt;span class="lnt"&gt;74
&lt;/span&gt;&lt;span class="lnt"&gt;75
&lt;/span&gt;&lt;span class="lnt"&gt;76
&lt;/span&gt;&lt;span class="lnt"&gt;77
&lt;/span&gt;&lt;span class="lnt"&gt;78
&lt;/span&gt;&lt;span class="lnt"&gt;79
&lt;/span&gt;&lt;span class="lnt"&gt;80
&lt;/span&gt;&lt;span class="lnt"&gt;81
&lt;/span&gt;&lt;span class="lnt"&gt;82
&lt;/span&gt;&lt;span class="lnt"&gt;83
&lt;/span&gt;&lt;span class="lnt"&gt;84
&lt;/span&gt;&lt;span class="lnt"&gt;85
&lt;/span&gt;&lt;span class="lnt"&gt;86
&lt;/span&gt;&lt;span class="lnt"&gt;87
&lt;/span&gt;&lt;span class="lnt"&gt;88
&lt;/span&gt;&lt;span class="lnt"&gt;89
&lt;/span&gt;&lt;span class="lnt"&gt;90
&lt;/span&gt;&lt;span class="lnt"&gt;91
&lt;/span&gt;&lt;span class="lnt"&gt;92
&lt;/span&gt;&lt;span class="lnt"&gt;93
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 获取所有日记文件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#34;30_日记&amp;#34;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2026&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;desc&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 获取当前日期（用于判断是否在最近一周内）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sevenDaysAgo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 遍历每篇日记
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sections&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/\n## /&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;section&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;sections&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;section&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;今天发生了什么？&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 提取该部分内容
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sectionContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;section&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^今天发生了什么？\n/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;/\n## .*$/s, &amp;#39;&amp;#39;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sectionContent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 解析日期
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dateMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/(\d{4})-(\d{2})-(\d{2})/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;displayDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;shortDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;weekday&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isRecent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dateMatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dateMatch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;dateMatch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dateMatch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;weekdays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;周日&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;周一&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;周二&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;周三&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;周四&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;周五&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;周六&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;weekday&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;weekdays&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getDay&lt;/span&gt;&lt;span class="p"&gt;()];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;displayDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dateMatch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dateMatch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dateMatch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;shortDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dateMatch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dateMatch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dateMatch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 判断是否在最近7天内
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;isRecent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;sevenDaysAgo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 计算字数（中文字符）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wordCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sectionContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/[^\u4e00-\u9fa5]/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 构建完整的 callout 内容
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 最近7天用 + (默认展开)，其他用 - (默认折叠)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expandSymbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isRecent&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;+&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;-&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;calloutContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sb"&gt;`&amp;gt; [!note]&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;expandSymbol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; 📝 [[&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;|&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;displayDate&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;]]&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;weekday&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="sb"&gt;` · &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;weekday&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;\n`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;calloutContent&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sb"&gt;`&amp;gt;\n`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 处理内容段落
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paragraphs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sectionContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\n\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;para&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;paragraphs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;para&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;para&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;calloutContent&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sb"&gt;`&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;\n`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;calloutContent&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sb"&gt;`&amp;gt;\n`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 底部信息栏
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;calloutContent&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sb"&gt;`&amp;gt; ---\n`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;calloutContent&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sb"&gt;`&amp;gt; &amp;lt;small&amp;gt;📊 &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;wordCount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; 字 · 🕐 &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;shortDate&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;&amp;lt;/small&amp;gt;\n`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;calloutContent&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sb"&gt;`&amp;gt; &amp;lt;div style=&amp;#34;text-align: right; margin-top: 5px;margin-bottom: 5px;&amp;#34;&amp;gt;&amp;lt;a href=&amp;#34;#&amp;#34; class=&amp;#34;diary-link&amp;#34; data-path=&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;&amp;#34; style=&amp;#34;color: var(--text-accent); text-decoration: none; font-size: 0.9em;&amp;#34;&amp;gt;📄 打开完整日记 →&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 一次性输出整个 callout
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;dv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;calloutContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 为所有链接添加点击事件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.diary-link&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-initialized&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-initialized&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-path&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;openLinkText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;dv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;注意代码块需要加上 dataviewjs&lt;/p&gt;</description></item><item><title>Obsidian 同步最终还是选择了Git</title><link>https://fwhyy.com/2026/02/obsidian-ultimately-chose-git-for-synchronization/</link><pubDate>Thu, 12 Feb 2026 18:05:00 +0800</pubDate><guid>https://fwhyy.com/2026/02/obsidian-ultimately-chose-git-for-synchronization/</guid><description>&lt;p&gt;第一次使用 Obsidian 是在 2022 年，这是翻阅之前的文章 [[Obsidian 初体验]] 才知道的，这几年主要是在电脑上使用，移动端因为同步问题用的非常少。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;之前也尝试过 Syncthing、坚果云等方案，但总有不好用的地方。一旦体验不佳，慢慢就不再使用，移动端也随之成了摆设，浪费了不少时间。&lt;/p&gt;
&lt;p&gt;最近又折腾了下 Obsidian 的 Git 插件，虽然也有点麻烦，但它是适合我的。&lt;/p&gt;
&lt;p&gt;下面介绍下怎么配置和使用。&lt;/p&gt;
&lt;h2 id="环境"&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PC 端：Mac&lt;/li&gt;
&lt;li&gt;移动端：安卓&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="使用的插件和工具"&gt;使用的插件和工具&lt;/h2&gt;
&lt;p&gt;1、PC 端 Git 插件&lt;/p&gt;
&lt;p&gt;2、移动端：GitSync、Termux&lt;/p&gt;
&lt;h2 id="pc-端配置步骤"&gt;PC 端配置步骤&lt;/h2&gt;
&lt;p&gt;1、在 Gitee（也可以使用 GitHub） 上创建存放 Obsidian 的仓库&lt;/p&gt;
&lt;p&gt;2、在 Obsidian 的根目录添加 .gitignore 文件，内容如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;.obsidian/
.stfolder/
.stfolder.*

# 忽略系统文件
.DS_Store
Thumbs.db
desktop.ini

# 忽略备份文件
*.bak
*.tmp

# 特殊配置：保留核心插件配置（可选）
# Ignore Smart Environment folder
.smart-env
.trash/

node_modules/
.obsidian-git-log.txt
*.swp
.directory
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;3、PC 端的 Obsidian 安装 Git 插件&lt;/p&gt;
&lt;p&gt;4、将笔记仓库推送到 Gitee，并在 Obsidian 中安装 Git 插件并进行配置，主要设置了打开仓库时自动拉取（pull）最新的笔记。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2026/202602111746650.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="移动端配置步骤"&gt;移动端配置步骤&lt;/h2&gt;
&lt;p&gt;1、移动端安装 Obsidian、Termux、GitSync。&lt;/p&gt;
&lt;p&gt;2、在手机 documents 目录中创建 obsidian-mobile 目录。&lt;/p&gt;
&lt;p&gt;3、在 Gitee 生成个人访问令牌，Gitee → 设置 → 私人令牌 → 生成新令牌，必须勾选 projects 权限（用于仓库操作）。令牌生成出来后需要及时复制保存，否则窗口关闭后就无法查看了。&lt;/p&gt;
&lt;p&gt;4、有了令牌后笔记仓库的地址如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;https://oauth2:令牌@gitee.com/xxxx/obsidian-sync.git
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5、在 Termux 中进入到 obsidian-mobile 目录，执行以下命令拉取笔记仓库&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git clone https://oauth2:令牌@gitee.com/xxxx/obsidian-sync.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;6、打开移动端的 Obsidian ，选择 obsidian-mobile/obsidian-sync 目录作为 vault 的目录，设置完后，就能看到笔记内容了。&lt;/p&gt;</description></item><item><title>AI 时代其实对人的要求更高了</title><link>https://fwhyy.com/2026/02/the-ai-era-actually-has-higher-requirements-for-people/</link><pubDate>Mon, 02 Feb 2026 10:00:00 +0800</pubDate><guid>https://fwhyy.com/2026/02/the-ai-era-actually-has-higher-requirements-for-people/</guid><description>&lt;p&gt;最近项目里发生了一件特别有意思的事，非常值得复盘。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;项目经理给一位开发同学布置了一个功能模块，按理说难度不大。考虑到现在 AI 编程工具这么强，项目经理估计很快就能搞定。结果呢？这位同学整整搞了一天还没弄完。&lt;/p&gt;
&lt;p&gt;项目经理很纳闷，问他：“你没用 AI 协助吗？”&lt;/p&gt;
&lt;p&gt;开发同学一脸苦笑：“用了啊。就是因为用了 AI，我才搞到现在。”&lt;/p&gt;
&lt;p&gt;原来，他把需求扔给 AI 后，AI 产出了代码和运行结果，这位开发同学又花了大量时间逐项核对。&lt;/p&gt;
&lt;p&gt;最后算下来，效率反倒不如纯手写。&lt;/p&gt;
&lt;p&gt;这位同事的问题，在于他依然以“写代码”的思维使用 AI，而不是以“验收结果”的思维。&lt;/p&gt;
&lt;p&gt;当我们自己写代码时，脑子里是有完整逻辑的，写出来的每一行都心里有数。但当 AI 生成代码时，对我们来说是一个“黑盒”。&lt;/p&gt;
&lt;p&gt;我们需要从执行者转变为架构师视角。&lt;/p&gt;
&lt;p&gt;在上面这个场景里，我们如果转变思路，把自己当成一个架构师，把 AI 当成负责编码的程序员。会发生什么？&lt;/p&gt;
&lt;p&gt;试想一下，如果你给一位开发派活，你会只说一句“帮我做个登录功能”吗？肯定不会。因为你知道一句话需求会导致最后做出来的东西可能完全偏离了方向。&lt;/p&gt;
&lt;p&gt;那要怎么做呢？&lt;/p&gt;
&lt;p&gt;我们会写详细的规格说明书和接口文档，明确交付标准。然后将这些告诉开发，要按照这些要求来写代码。&lt;/p&gt;
&lt;p&gt;对 AI 也是一样。&lt;/p&gt;
&lt;p&gt;结合这个案例，我认为要提高 AI 协作效率，必须做好以下几点：&lt;/p&gt;
&lt;p&gt;1、边界&lt;/p&gt;
&lt;p&gt;告诉 AI 目标是什么、哪些要做、哪些不能做。只有当 AI 清楚知道“要做什么”并且“什么不能做”时，才能正确执行任务。&lt;/p&gt;
&lt;p&gt;2、任务拆解&lt;/p&gt;
&lt;p&gt;不要把一个大需求直接丢给 AI。正确的做法是拆解。把大任务拆成一个个独立的、可验证的小的任务。&lt;/p&gt;
&lt;p&gt;任务越小，AI 犯错概率越低，检查的成本也越低。&lt;/p&gt;
&lt;p&gt;3、反馈&lt;/p&gt;
&lt;p&gt;当 AI 给出的结果有问题时，我们要能快速识别，并及时提供反馈。&lt;/p&gt;
&lt;p&gt;如何才能快速识别？&lt;/p&gt;
&lt;p&gt;这就需要我们掌握架构知识和底层原理，所以说 AI 帮我们提升效率的同时，我们自己的能力也需要提升才能更高效地配合。&lt;/p&gt;
&lt;p&gt;好的反馈能让 AI 一次性修正错误，避免陷入无效的反复沟通。这不仅省钱（省 Token），还能让 AI 尽可能少地产生幻觉。&lt;/p&gt;
&lt;p&gt;4、上下文&lt;/p&gt;
&lt;p&gt;AI 和人一样，需要上下文。&lt;/p&gt;
&lt;p&gt;一个新人进入团队，需要熟悉工作环境、使用的工具、项目的情况、文档、代码库等，这些就是上下文；上下文越充分，就越容易上手。&lt;/p&gt;
&lt;p&gt;5、目标&lt;/p&gt;
&lt;p&gt;我们做项目，客户的真实诉求是什么？挖得越深，就会越顺利，可以在后期避免很多不必要的返工。&lt;/p&gt;
&lt;p&gt;指挥 AI 干活，也需要让 AI 知道我们的目标和意图是什么，只有这样，产出才不会有偏差，有时甚至有惊喜。&lt;/p&gt;
&lt;p&gt;6、验收标准&lt;/p&gt;
&lt;p&gt;把任务指派给 AI，必须让 AI 知道什么叫“做完了”。&lt;/p&gt;
&lt;p&gt;不要小看这个“做完了”，很多时候，项目经理和开发的理解都不一样，开发认为代码写完就算是做完了，项目经理要对最终的业务负责，考虑的更全面。&lt;/p&gt;
&lt;p&gt;首先我们要明确这个标准，再告诉 AI。否则，如果我们自己都不清楚验收标准，AI 就不可能产出符合要求的结果。&lt;/p&gt;</description></item><item><title>Agent Skills 全景指南：从概念机制到实战开发</title><link>https://fwhyy.com/2026/01/a-comprehensive-guide-to-agent-skills-from-conceptual-mechanisms-to-practical-development/</link><pubDate>Fri, 23 Jan 2026 09:01:00 +0800</pubDate><guid>https://fwhyy.com/2026/01/a-comprehensive-guide-to-agent-skills-from-conceptual-mechanisms-to-practical-development/</guid><description>&lt;p&gt;最近，Agent Skills 彻底火了。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;很多人第一次听到 Skills，会觉得“这不就是一堆 Markdown 吗？”我一开始也这么想。但当你把它放进 Agent 的运行方式里，再对比 Prompt、MCP、Function Calling 这些概念，你会发现：Skills 解决的不是“模型会不会”，而是“怎么让模型稳定、可复用、可分发地把事做完”。&lt;/p&gt;
&lt;p&gt;在这篇文章里，我将从概念到实战，带你彻底搞懂 Skills。&lt;/p&gt;
&lt;h2 id="一什么是-skills它从何而来"&gt;一、什么是 Skills？它从何而来？&lt;/h2&gt;
&lt;p&gt;简单来说，Skills 就是供大模型使用的技能包。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Skills 里面包含做事的方法（流程、规范、检查点），以及可选的资源（模板、脚本、参考资料等）。&lt;/li&gt;
&lt;li&gt;目标不是让模型“临场表现更好”，而是让同一类任务在不同时间、不同输入、不同人使用时，都能得到稳定的结果。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如：团队新来了一个开发工程师。为了让他按团队要求开展工作，通常会告知：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这件事的目标和流程是什么（SOP）&lt;/li&gt;
&lt;li&gt;要用到什么工具（Scripts/MCP）&lt;/li&gt;
&lt;li&gt;有什么参考模板和素材（References/Assets）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这就是 Skills。它让 Agent 具备了“专业知识”和“稳定做事的方法”。&lt;/p&gt;
&lt;p&gt;Skills 最早由 Anthropic 在 2025 年 10 月中旬随 Claude Code 推出。两个月后（12 月 18 日），Agent Skills 被作为开放标准发布。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills?utm_source=chatgpt.com"&gt;https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills?utm_source=chatgpt.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2026/202601230643573.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="二skillsmcpagentfunction-calling-的关系"&gt;二、Skills、MCP、Agent、Function Calling 的关系&lt;/h2&gt;
&lt;p&gt;之前写过 MCP 和 Function Calling 相关的文章：&lt;/p&gt;
&lt;p&gt;《[[MCP 和 Function Calling：概念]]》&lt;/p&gt;
&lt;p&gt;《[[MCP 和 Function Calling：示例]]》&lt;/p&gt;
&lt;p&gt;这些和新的 Skills，关系是什么呢？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Function Calling：这是最底层的能力，相当于人的“手”。它让 AI 知道自己能“拿杯子”、“按开关”，是连接外部世界的基础接口。&lt;/li&gt;
&lt;li&gt;MCP：这是一种标准协议，定义通用通信架构和数据格式（类似于 USB 标准）。Function Calling 可视为 MCP 生态下的一种具体功能实现形式。&lt;/li&gt;
&lt;li&gt;Skills：这是业务逻辑和流程，相当于“脑子里的知识”。它教 AI 如何使用 MCP 里的工具去完成一个复杂的任务（比如写一篇符合你风格的文章）。它解决的是“流程”问题。&lt;/li&gt;
&lt;li&gt;Agent：Agent 是位于最上层的“大脑”或“协调者”。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可以这么理解，不一定准确：Agent 是工人、Function Calling 是工人具备使用工具的能力，比如会用锤子等、 MCP 是一个多功能腰带，有各种标准的卡口用来放不同类型的工具、Skills 可以是这些工具的使用说明书，也可以是怎么用工具造房子的施工图纸。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2026/202601230655772.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="三核心机制"&gt;三、核心机制&lt;/h2&gt;
&lt;p&gt;Skills 的核心机制，我认为就两件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;让 Agent 能“找到该用哪个技能”&lt;/li&gt;
&lt;li&gt;让 Agent 能“只在需要时加载需要的部分”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Agent 启动时不会把所有技能全文塞进上下文窗口，而是先扫描技能包，读取每个技能的少量元信息（名称和描述，描述尤为重要）。&lt;/p&gt;
&lt;p&gt;当用户提出需求后，Agent 会用这些元信息做匹配，判断要不要触发某个技能。这也是为什么 Skills 的 &lt;code&gt;description&lt;/code&gt; 写得好不好，直接决定“命中率”。&lt;/p&gt;</description></item><item><title>自研 MySQL 数据迁移工具：比 pt-archiver 快 10 倍的秘密</title><link>https://fwhyy.com/2026/01/self-developed-mysql-data-migration-tool-secrets-that-are-10-times-faster-than-pt-explorer/</link><pubDate>Fri, 16 Jan 2026 14:00:00 +0800</pubDate><guid>https://fwhyy.com/2026/01/self-developed-mysql-data-migration-tool-secrets-that-are-10-times-faster-than-pt-explorer/</guid><description>&lt;p&gt;在上一篇文章《[[使用 pt-archiver 迁移 mysql 数据]]》中，我介绍了使用 Percona Toolkit 工具集中的 &lt;code&gt;pt-archiver&lt;/code&gt; 进行历史数据归档的方法。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;code&gt;pt-archiver&lt;/code&gt; 功能强大且成熟，但在某些特定场景下，它的性能表现并不尽如人意。&lt;/p&gt;
&lt;p&gt;例如，当我尝试将 200 万行历史数据迁移到一个已经包含 500 万行数据的归档表中时，&lt;code&gt;pt-archiver&lt;/code&gt; 的速度非常慢。最根本的原因有两个：&lt;/p&gt;
&lt;p&gt;1、是因为它在插入数据时，目标表的索引在持续更新，随着表越来越大，索引维护的开销也呈指数级增长。&lt;/p&gt;
&lt;p&gt;2、pt-archiver 在批量执行时拼接的 SQL 并非是多值 SQL，而是多条 Insert 语句的拼接。而多值 SQL 的执行效率要远超多条 Insert 语句的拼接。&lt;/p&gt;
&lt;p&gt;为了解决这个问题，我借助 AI 的能力编写了一个 Python 工具（&lt;code&gt;data_migrate&lt;/code&gt;），通过先删索引-批量插入-重建索引的策略，实现了性能的飞跃。&lt;/p&gt;
&lt;h2 id="核心思路"&gt;核心思路&lt;/h2&gt;
&lt;p&gt;1、&lt;strong&gt;迁移前&lt;/strong&gt;：把原表和目标表上除主键和查询字段相关之外的索引先保存到 json 文件中，然后删除。&lt;/p&gt;
&lt;p&gt;2、&lt;strong&gt;迁移中&lt;/strong&gt;：使用 &lt;code&gt;INSERT INTO ... VALUES (...), (...), ...&lt;/code&gt; 这种多值 SQL 的方式进行批量写入。因为没有索引的负担，目标表写入速度和原表的删除速度都非常快。&lt;/p&gt;
&lt;p&gt;3、&lt;strong&gt;迁移后&lt;/strong&gt;：一次性重建所有索引。MySQL 重建索引是经过优化的（排序后批量构建），比逐行维护快得多。&lt;/p&gt;
&lt;p&gt;此外，针对复杂的筛选条件（例如 &lt;code&gt;WHERE id IN (SELECT ...)&lt;/code&gt;），引入了快照表机制，避免在循环分页中反复执行昂贵的子查询。&lt;/p&gt;
&lt;p&gt;快照表逻辑很简单，就是先将需要过滤的 id 查询出来存到一个临时表中，再通过临时表中的 id 进行过滤。&lt;/p&gt;
&lt;h2 id="工具实现"&gt;工具实现&lt;/h2&gt;
&lt;p&gt;这个工具使用 Python 编写，基于 &lt;code&gt;PyMySQL&lt;/code&gt; 驱动。主要包含以下几个模块：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;migrator.py&lt;/code&gt;: 核心迁移控制器。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;index_manager.py&lt;/code&gt;: 负责智能地删除和恢复索引。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;db_manager.py&lt;/code&gt;: 数据库连接池管理。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="1智能索引优化"&gt;1、智能索引优化&lt;/h3&gt;
&lt;p&gt;这是性能提升的关键。在 &lt;code&gt;IndexManager&lt;/code&gt; 类中，实现了 &lt;code&gt;drop_indexes&lt;/code&gt; 和 &lt;code&gt;restore_indexes&lt;/code&gt; 方法。&lt;/p&gt;
&lt;p&gt;值得注意的是，我们不能无脑删除所有索引。如果迁移的 &lt;code&gt;WHERE&lt;/code&gt; 条件依赖某个索引（例如按 &lt;code&gt;create_time&lt;/code&gt; 过滤），删掉它会导致源表查询变慢。因此，我加入了一个简单的逻辑：&lt;strong&gt;解析 WHERE 子句，保留查询所需的索引&lt;/strong&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# data_migrate/tools/data_migrate/index_manager.py 部分代码&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;drop_indexes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;table_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indexes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keep_columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;删除索引并持久化到文件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; :param keep_columns: 需要保留的列名列表（字符串列表），如果索引包含这些列，则不删除
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;indexes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 持久化索引信息到文件，防止程序中断丢失&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;backup_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;table_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_indexes_backup.json&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;backup_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indexes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ensure_ascii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;索引备份已保存至: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;backup_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;保存索引备份失败: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;，将跳过索引删除操作以保证安全。&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 过滤需要删除的索引&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;indexes_to_drop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;indexes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;should_drop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;keep_columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 检查索引列是否包含在保留列表中&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# idx[&amp;#39;columns&amp;#39;] 是 [&amp;#34;`col1`&amp;#34;, &amp;#34;`col2`&amp;#34;] 格式&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;columns&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;clean_col&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;`&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;clean_col&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;keep_columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34; -&amp;gt; 保留表 &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;table_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 的索引 &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;，因为涉及查询列 &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;clean_col&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;should_drop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_drop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;indexes_to_drop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;indexes_to_drop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;表 &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;table_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 没有需要删除的索引（所有索引均被保留或无索引）。&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;正在删除表 &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;table_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 的 &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indexes_to_drop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 个索引以加速写入...&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db_manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;indexes_to_drop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sql&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ALTER TABLE `&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;table_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;` DROP INDEX `&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34; -&amp;gt; 删除索引: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;删除索引 &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 失败: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="2批量读写与事务控制"&gt;2、批量读写与事务控制&lt;/h3&gt;
&lt;p&gt;为了减少网络交互和事务开销，我使用了 &lt;code&gt;executemany&lt;/code&gt; 进行批量插入。&lt;/p&gt;</description></item><item><title>使用 pt-archiver 迁移 mysql 数据</title><link>https://fwhyy.com/2026/01/using-pt-archiver-to-migrate-mysql-data/</link><pubDate>Tue, 13 Jan 2026 16:43:00 +0800</pubDate><guid>https://fwhyy.com/2026/01/using-pt-archiver-to-migrate-mysql-data/</guid><description>&lt;p&gt;在软件系统中，随着业务增长，有些表数据量会越来越大，为了提升性能，会将表进行拆分。这就需要定时将数据从源表迁移到目标表。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;通常使用一个 sql 语句就能实现数据的迁移：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;insert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;into&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t_business_finished&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t_business&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t_business&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;但这种操作在数据量很大时速度很慢，资源消耗也比较大。&lt;/p&gt;
&lt;p&gt;后来发现 pt-archiver 这个工具可以做这个事情。pt-archiver 有下面几个优点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;支持分批（chunk）读取和写入，避免一次性加载大量数据导致内存溢出或锁表。&lt;/li&gt;
&lt;li&gt;可以通过 &lt;code&gt;--limit&lt;/code&gt; 控制每次处理的行数，配合 &lt;code&gt;--txn-size&lt;/code&gt; 控制事务大小。&lt;/li&gt;
&lt;li&gt;支持 &lt;code&gt;--sleep&lt;/code&gt; ，避免对生产库造成过大的压力。&lt;/li&gt;
&lt;li&gt;可以通过 &lt;code&gt;--progress&lt;/code&gt; 来查看进度。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下面就简单说下 pt-archiver 是怎么使用的，因为我测试的环境 mysql 是使用 docker 构建的，下面示例中 pt-archiver 也是使用 docker 的方式运行。&lt;/p&gt;
&lt;p&gt;1、拉取镜像&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker pull percona/percona-toolkit:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;2、如果是企业内网，不能拉取镜像，就将镜像保存为 tar 文件，赋值到内网服务器 load 即可&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 外网服务器进行保存&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker save -o percona-toolkit.tar percona/percona-toolkit:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 拷贝到内网后load&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker load -i percona-toolkit.tar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;3、执行下面命令就可以进行数据的迁移：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;--rm --network test_net percona/percona-toolkit:latest pt-archiver --source h=172.66.5.7,P=3306,u=root,p=123456,D=test,t=t_user --dest h=172.66.5.7,P=3306,u=root,p=123456,D=test,t=t_user_bak --where &amp;#34;1=1&amp;#34; --limit 10 --progress 10 --txn-size 10 --sleep 1 --no-delete --statistics --why-quit --header
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&amp;ndash;network：设置和数据库的容器在一个网络中&lt;/li&gt;
&lt;li&gt;&amp;ndash;source 源表相关配置
&lt;ul&gt;
&lt;li&gt;h：数据库的容器 IP&lt;/li&gt;
&lt;li&gt;P：数据库的容器内部端口&lt;/li&gt;
&lt;li&gt;u：数据库用户名&lt;/li&gt;
&lt;li&gt;p：数据库密码&lt;/li&gt;
&lt;li&gt;D：数据库名称&lt;/li&gt;
&lt;li&gt;t：表名&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;ndash;dest：目标表相关配置&lt;/li&gt;
&lt;li&gt;&amp;ndash;where：从源表获取数据的 where 条件&lt;/li&gt;
&lt;li&gt;&amp;ndash;limit：每次获取数据的条数&lt;/li&gt;
&lt;li&gt;&amp;ndash;progress 10：每处理 10 行就向终端输出一条进度信息&lt;/li&gt;
&lt;li&gt;&amp;ndash;txn-size 10：每 10 行组成一个事务，提交一次&lt;/li&gt;
&lt;li&gt;&amp;ndash;sleep 1：每批提交后暂停 1 秒，降低负载。&lt;/li&gt;
&lt;li&gt;&amp;ndash;no-delete：只复制，不删除源表数据&lt;/li&gt;
&lt;li&gt;&amp;ndash;statistics：结束后打印总计行数、耗时、吞吐量等汇总&lt;/li&gt;
&lt;li&gt;&amp;ndash;why-quit：如果提前退出，告知原因&lt;/li&gt;
&lt;li&gt;&amp;ndash;header：进度信息前打印表头&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;执行效果如下：&lt;/p&gt;</description></item><item><title>MySQL高可用：InnoDB Cluster 部署详解</title><link>https://fwhyy.com/2025/09/mysql-high-availability-innodb-cluster-deployment-details/</link><pubDate>Mon, 15 Sep 2025 09:07:00 +0800</pubDate><guid>https://fwhyy.com/2025/09/mysql-high-availability-innodb-cluster-deployment-details/</guid><description>&lt;p&gt;最近公众号有人留言：为啥使用 ProxySQL 而不使用 InnoDB Cluster ？&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;其实使用什么方案，根据实际情况进行权衡利弊即可，如果先部署了 MGR ，想在此基础之上完善高可用，添加 ProxySQL 比较方便。如果新部署一个高可用环境，直接使用 InnoDB Cluster 也可以，InnoDB Cluster 也是依赖 MGR 。&lt;/p&gt;
&lt;p&gt;下面将从零开始，来讲解怎么通过 Docker Compose 来部署 MySQL InnoDB Cluster，让你能够快速搭建一套完整的高可用数据库系统。&lt;/p&gt;
&lt;h2 id="什么是-mysql-innodb-cluster"&gt;什么是 MySQL InnoDB Cluster&lt;/h2&gt;
&lt;h3 id="核心概念"&gt;核心概念&lt;/h3&gt;
&lt;p&gt;MySQL InnoDB Cluster是 MySQL 官方提供的高可用解决方案，它基于以下三个核心组件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MySQL Group Replication：提供数据复制和故障检测，这个就是前面文章中提到的 MGR&lt;/li&gt;
&lt;li&gt;MySQL Router：提供透明的路由和负载均衡&lt;/li&gt;
&lt;li&gt;MySQL Shell：提供集群管理和监控功能&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="架构优势"&gt;架构优势&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;自动故障检测和转移&lt;/li&gt;
&lt;li&gt;强一致性数据复制&lt;/li&gt;
&lt;li&gt;透明的读写分离&lt;/li&gt;
&lt;li&gt;简化的管理操作&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="架构图"&gt;架构图&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202509150900083.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="开始部署"&gt;开始部署&lt;/h2&gt;
&lt;p&gt;为了测试方便，在一台服务器上使用 docker compose 部署多个服务节点。&lt;/p&gt;
&lt;h3 id="启动-mysql-节点"&gt;启动 mysql 节点&lt;/h3&gt;
&lt;p&gt;1、在服务器上创建一个目录 mysql-innodb-cluster ，目录中按照下图进行目录和文件的创建。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202509150901491.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2、docker-compose.yml 文件内容如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;span class="lnt"&gt;50
&lt;/span&gt;&lt;span class="lnt"&gt;51
&lt;/span&gt;&lt;span class="lnt"&gt;52
&lt;/span&gt;&lt;span class="lnt"&gt;53
&lt;/span&gt;&lt;span class="lnt"&gt;54
&lt;/span&gt;&lt;span class="lnt"&gt;55
&lt;/span&gt;&lt;span class="lnt"&gt;56
&lt;/span&gt;&lt;span class="lnt"&gt;57
&lt;/span&gt;&lt;span class="lnt"&gt;58
&lt;/span&gt;&lt;span class="lnt"&gt;59
&lt;/span&gt;&lt;span class="lnt"&gt;60
&lt;/span&gt;&lt;span class="lnt"&gt;61
&lt;/span&gt;&lt;span class="lnt"&gt;62
&lt;/span&gt;&lt;span class="lnt"&gt;63
&lt;/span&gt;&lt;span class="lnt"&gt;64
&lt;/span&gt;&lt;span class="lnt"&gt;65
&lt;/span&gt;&lt;span class="lnt"&gt;66
&lt;/span&gt;&lt;span class="lnt"&gt;67
&lt;/span&gt;&lt;span class="lnt"&gt;68
&lt;/span&gt;&lt;span class="lnt"&gt;69
&lt;/span&gt;&lt;span class="lnt"&gt;70
&lt;/span&gt;&lt;span class="lnt"&gt;71
&lt;/span&gt;&lt;span class="lnt"&gt;72
&lt;/span&gt;&lt;span class="lnt"&gt;73
&lt;/span&gt;&lt;span class="lnt"&gt;74
&lt;/span&gt;&lt;span class="lnt"&gt;75
&lt;/span&gt;&lt;span class="lnt"&gt;76
&lt;/span&gt;&lt;span class="lnt"&gt;77
&lt;/span&gt;&lt;span class="lnt"&gt;78
&lt;/span&gt;&lt;span class="lnt"&gt;79
&lt;/span&gt;&lt;span class="lnt"&gt;80
&lt;/span&gt;&lt;span class="lnt"&gt;81
&lt;/span&gt;&lt;span class="lnt"&gt;82
&lt;/span&gt;&lt;span class="lnt"&gt;83
&lt;/span&gt;&lt;span class="lnt"&gt;84
&lt;/span&gt;&lt;span class="lnt"&gt;85
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mysql1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mysql:8.0.39&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mysql1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mysql1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;unless-stopped&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;rootpass123&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;TZ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Asia/Shanghai&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mysql-cluster-net&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./node1/conf:/etc/mysql/conf.d:ro&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./node1/data:/var/lib/mysql&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./node1/log:/var/log/mysql&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;3310:3306&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mysql2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mysql:8.0.39&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mysql2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mysql2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;unless-stopped&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;rootpass123&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;TZ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Asia/Shanghai&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mysql-cluster-net&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./node2/conf:/etc/mysql/conf.d:ro&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./node2/data:/var/lib/mysql&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./node2/log:/var/log/mysql&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;3311:3306&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mysql3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mysql:8.0.39&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mysql3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mysql3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;unless-stopped&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;rootpass123&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;TZ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Asia/Shanghai&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mysql-cluster-net&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./node3/conf:/etc/mysql/conf.d:ro&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./node3/data:/var/lib/mysql&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./node3/log:/var/log/mysql&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;3312:3306&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mysql-router&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mysql/mysql-router:8.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mysql-router&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;unless-stopped&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mysql1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mysql2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mysql3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mysql-cluster-net&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./router/data:/tmp/mysqlrouter&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;6446:6446&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 读写端口 (RW)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;6447:6447&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 只读端口 (RO)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;6448:6448&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 管理端口 (X Protocol RW)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;6449:6449&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 管理端口 (X Protocol RO)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mysql1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3306&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;clusteradmin&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;clusterpass123&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_CREATE_ROUTER_USER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; --conf-use-sockets
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; --conf-bind-address 0.0.0.0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; --conf-base-port 6446&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mysql-cluster-net&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;bridge&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mysql-cluster-net&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;router 节点说明：&lt;/p&gt;</description></item><item><title>MySQL高可用：ProxySQL读写分离+MGR</title><link>https://fwhyy.com/2025/09/mysql-high-availability-proxysql-readwrite-separationmgr/</link><pubDate>Wed, 03 Sep 2025 16:46:00 +0800</pubDate><guid>https://fwhyy.com/2025/09/mysql-high-availability-proxysql-readwrite-separationmgr/</guid><description>&lt;p&gt;MGR 解决了高可用的问题，但如果数据库访问量大，特别是读多写少的场景，就需要读写分离架构了了，在 MGR 的基础上，前面加上 ProxSQL 就可以实现读写分离。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202509030651178.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;应用程序只和 ProxySQL 打交道&lt;/li&gt;
&lt;li&gt;ProxySQL 做为应用和 MGR 集群中间的一个桥梁，让应用对 MGR 的变化没有感知&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="组件说明"&gt;组件说明&lt;/h2&gt;
&lt;h3 id="mgr"&gt;MGR&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;mysql-master: 主节点 (Primary)，处理写操作&lt;/li&gt;
&lt;li&gt;mysql-slave-1: 从节点 (Secondary)，处理读操作&lt;/li&gt;
&lt;li&gt;mysql-slave-2: 从节点 (Secondary)，处理读操作&lt;/li&gt;
&lt;li&gt;配置为单主模式 (Single-Primary Mode)&lt;/li&gt;
&lt;li&gt;实现自动故障转移和数据同步&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="proxysql"&gt;ProxySQL&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;端口 6033: MySQL 协议接口，应用连接端口&lt;/li&gt;
&lt;li&gt;端口 6032: 管理接口，用于配置和监控&lt;/li&gt;
&lt;li&gt;端口 6080: Web 管理界面 (可选)&lt;/li&gt;
&lt;li&gt;提供读写分离、连接池、查询路由功能，可以对 mysql 的每个节点进行健康检查，进行故障转移，发现主节点出现故障，会将新的强求转移到新的主&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="proxysql-安装和配置"&gt;ProxySQL 安装和配置&lt;/h2&gt;
&lt;p&gt;在《MySQL高可用-使用Docker部署MGR》中介绍了 MGR 的安装部署，在此基础之上继续来安装 ProxySQL。&lt;/p&gt;
&lt;p&gt;1、修改 docker-compose.yml 文件，添加 proxysql 节点。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;proxysql&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;proxysql/proxysql:2.6.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;proxysql&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;proxysql&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;proxysql-data:/var/lib/proxysql&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./proxysql-config/proxysql.cnf:/etc/proxysql.cnf&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./proxysql-init-scripts:/etc/proxysql&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;6033:6033&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;6032:6032&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mysql-mgr-network&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mysql-master&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mysql-slave-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;mysql-slave-2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;CMD&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;mysql&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-P&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;6032&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-u&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-padmin&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-e&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;SELECT 1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;10s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;5s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;/proxysql-config/proxysql.cnf：proxysql 的配置文件&lt;/li&gt;
&lt;li&gt;/proxysql-config/proxysql.cnf：proxysql 初始化脚本所在的目录，可以直接配置为 ./proxysql-init-scripts:/docker-entrypoint-initdb.d ，则会在容器启动时执行。上面是将目录中的文件映射到容器内部，后续需要手动执行。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2、volumes 中映射的文件和目录内容，点击查看原文查看。&lt;/p&gt;</description></item><item><title>MySQL高可用-MGR运维常见问题和注意事项</title><link>https://fwhyy.com/2025/08/mysql-high-availability-mgr-operation-and-maintenance-common-problems-and-precautions/</link><pubDate>Wed, 13 Aug 2025 09:45:00 +0800</pubDate><guid>https://fwhyy.com/2025/08/mysql-high-availability-mgr-operation-and-maintenance-common-problems-and-precautions/</guid><description>&lt;p&gt;MySQL 的高可用可以选择 MGR 方案，部署 MGR 很简单，可以参考《MySQL高可用-使用Docker部署MGR》，但在运行过程中，如果出现问题，如何快速解决？需要持续学习和实践。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;下面我以实际用到的和我搜集到的一些资料来说说 MGR 在运维过程中的常见问题和注意事项。&lt;/p&gt;
&lt;h2 id="部署前注意事项"&gt;部署前注意事项&lt;/h2&gt;
&lt;h3 id="硬件和环境要求"&gt;硬件和环境要求&lt;/h3&gt;
&lt;p&gt;1、网络要求&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;低延迟网络：MGR 对网络延迟敏感，建议延迟 &amp;lt; 5ms 。因为 MGR 基于 Paxos 变种的共识算法，每提交一次事务至少跨网两次（prepare&amp;gt;ack&amp;gt;commit）。&lt;/li&gt;
&lt;li&gt;稳定带宽：确保有足够的带宽支持数据同步，建议 ≥ 1Gbps 。全量 recovery、大事务或 DDL 时会产生突发流量，带宽不足会导致 flow-control 触发，集群整体降速&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2、服务器配置&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CPU：建议多核 CPU，至少4核以上&lt;/li&gt;
&lt;li&gt;内存：充足内存，建议 ≥ 16GB&lt;/li&gt;
&lt;li&gt;存储：使用 SSD 存储，确保足够 IOPS，考虑使用 RAID 10 而非 RAID 5/6，以获得更好的写性能&lt;/li&gt;
&lt;li&gt;时钟同步：所有节点必须时钟同步（NTP）。MGR 的 GTID、view_change 事件都带时间戳，时间漂移会导致 “member expel” 误判。误判会导致节点是正常的，但会被踢出去。&lt;/li&gt;
&lt;li&gt;分离数据和日志：将二进制日志和数据文件放在不同的物理存储上，参数大致如下：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;datadir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; /data/mysql
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;log_bin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; /binlog/mysql-bin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;binlog_cache_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 1M 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;sync_binlog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;innodb_flush_log_at_trx_commit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="操作系统优化"&gt;操作系统优化&lt;/h3&gt;
&lt;p&gt;1、文件描述符限制&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 文件描述符限制&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;mysql soft nofile 65536&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; /etc/security/limits.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;mysql hard nofile 65536&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; /etc/security/limits.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;MGR + InnoDB 打开的文件数 = 表数量 × 分区 × 3（ibd、frm、ibtmp）+ binlog + relay log。文件描述限制如果比较小，操作系统层面的文件描述符（fd）耗尽，后果是 mysqld 再想去 open() 任何文件（包括新的 ibd、binlog、relay-log、tmp-file、socket 等）时都会得到 EMFILE，导致各种莫名奇妙的错误。&lt;/p&gt;</description></item><item><title>MySQL高可用-使用Docker部署MGR</title><link>https://fwhyy.com/2025/07/mysql-high-availability-deploying-mgr-with-docker/</link><pubDate>Tue, 22 Jul 2025 21:57:00 +0800</pubDate><guid>https://fwhyy.com/2025/07/mysql-high-availability-deploying-mgr-with-docker/</guid><description>&lt;p&gt;MySql 的高可用方案很多，有 MHA、MGR、MySQL InnoDB Cluster 等。起初想学习下 MHA，了解后发现 MHA 在 Github 上的仓库已经没有更新了。不过 MHA 的兼容性比较好，有老版本的 MySQL 需要做高可用，还是值得一试的。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;本文介绍下 MGR 的部署。&lt;/p&gt;
&lt;p&gt;MGR (MySQL Group Replication) 是 MySQL 5.7.17 提出的，既可以很好的保证数据一致性又可以自动切换，具备故障检测功能、支持多节点写入。是以插件的形式提供，可以灵活部署。&lt;/p&gt;
&lt;p&gt;MySQL MGR 集群是多个 MysQL Server 节点共同组成的分布式集群，每个 Server 都有完整的副本，它是基于 ROW 格式的二进制日志文件和 GTID 特性来实现的。&lt;/p&gt;
&lt;h2 id="mgr-的优点"&gt;MGR 的优点&lt;/h2&gt;
&lt;p&gt;1、强一致性：基于原生复制及 Paxos 协议的组复制技术（以插件形式提供），确保数据的严格一致性。&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;h2 id="mgr-的一些限制"&gt;MGR 的一些限制&lt;/h2&gt;
&lt;p&gt;1、仅支持 InnoDB 表，并旦每个表一定要有一个主键。&lt;/p&gt;
&lt;p&gt;2、必须打开 GTID 特性，二进制日志格式必须设置为 ROW 。&lt;/p&gt;
&lt;p&gt;3、MGR 不支持大事务。&lt;/p&gt;
&lt;p&gt;4、仅支持 IPv4 网络，组大小限制为最少3个节点、最多9个节点。&lt;/p&gt;
&lt;p&gt;5、不支持外键。&lt;/p&gt;
&lt;p&gt;6、二进制日志不支持 Binlog Event Checksum 。&lt;/p&gt;
&lt;p&gt;7、所有节点 server_id 和 server_uuid 需唯一。&lt;/p&gt;
&lt;h2 id="部署前准备"&gt;部署前准备&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;为了方便，mysql 的主节点和从节点在一台虚拟机中进行测试&lt;/li&gt;
&lt;li&gt;docker 版本：20.10.0&lt;/li&gt;
&lt;li&gt;docker compose 版本：2.26.2&lt;/li&gt;
&lt;li&gt;mysql 版本：8.0.39&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="开始部署"&gt;开始部署&lt;/h2&gt;
&lt;p&gt;1、采用 docker-compose 的方式进行部署，部署目录 mysql-mgr 的文件结构如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202507221805817.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;docker-compose.yml：容器编排文件，配置一个主和两个从的 mysql 节点。&lt;/li&gt;
&lt;li&gt;mysql-config：此目录中是主和从的 mysql 配置文件&lt;/li&gt;
&lt;li&gt;mysql-init-srcipts：此目录中是 mysql 启动时需要创建复制账号以及安装 mgr 插件&lt;/li&gt;
&lt;li&gt;start-mgr.sh：三个 mysql 节点启动后，执行该文件进行 mgr 集群的启动。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2、将 mysql-mgr 拷贝到服务器，进入 mysql-mgr 目录执行 &lt;code&gt;docker-compose up -d&lt;/code&gt; 。&lt;/p&gt;</description></item><item><title>如何构建多智能体系统？</title><link>https://fwhyy.com/2025/06/how-to-build-a-multiagent-system/</link><pubDate>Wed, 25 Jun 2025 15:51:00 +0800</pubDate><guid>https://fwhyy.com/2025/06/how-to-build-a-multiagent-system/</guid><description>&lt;p&gt;6 月 13 日，Anthropic 发布了一篇《How we built our multi-agent research system》的实战经验文章，文章分享了 Anthropic 在构建多个 Claude 智能体来更有效地探索复杂主题的系统过程中，遇到的工程挑战和获得的经验教训。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;原文地址如下：&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.anthropic.com/engineering/built-multi-agent-research-system"&gt;https://www.anthropic.com/engineering/built-multi-agent-research-system&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;全文翻译可以看：https://www.fwhyy.com/2025/06/how-to-build-a-multi-agent-research-system-translation/&lt;/p&gt;
&lt;p&gt;下面是我看文章时记录的一些知识点：&lt;/p&gt;
&lt;p&gt;1、在过去十万年里，单个人的智力并未发生巨变，但人类社会在信息时代的能力却呈指数级增长，这得益于我们的集体智慧和协调能力。所以说要想突破能力极限，还得靠协作。&lt;/p&gt;
&lt;p&gt;2、映射到现在的智能体就是单个智能体会出现 token 使用的极限，多智能体可以使用更多的计算资源来处理现实问题。&lt;/p&gt;
&lt;p&gt;3、多智能体的功能架构是协调者和工作者模式，有专门负责分析和指派任务的智能体，也有负责特定工作的智能体。有点像一个项目团队中的项目经理和项目的其他成员。&lt;/p&gt;
&lt;p&gt;4、多智能体的一个应用场景是做问答类的应用，和 RAG 不同的是，RAG 依赖静态检索，根据查询的问题找相似块，然后组织成答案。多智能体是多步骤进行检索，动态发现关键信息，并且还会对结果进行分析，进而做进一步分析和处理，使答案有更高的质量。&lt;/p&gt;
&lt;p&gt;5、多智能体在运行时，会遵循下面步骤。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;系统会先创建一个主智能体，进行任务的思考，然后制定计划，将计划保存起来。&lt;/li&gt;
&lt;li&gt;主智能体会创建一个或多个子智能体，进行具体任务的分配。&lt;/li&gt;
&lt;li&gt;每个子智能体独自研究并将结果返回给主智能体。&lt;/li&gt;
&lt;li&gt;主智能体会判断是否需要进行进一步研究，如果需要会创建额外的子智能体，这个过程是一个循环。&lt;/li&gt;
&lt;li&gt;当主智能体发现不用继续研究，会退出循环，将所有结果交给引文智能体进行引文标记的工作。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;6、大模型虽然越来越强，但提示词依然很重要，每个智能体都是由提示词进行引导，我们需要使用日志记录的方式来检查智能体的行为，观察什么时候会出错，然后优化提示词。&lt;/p&gt;
&lt;p&gt;7、主智能体在进行任务的分配时，需要将需求写的尽可能明确和详尽，这样子智能体才能更好的执行。&lt;/p&gt;
&lt;p&gt;8、提示词有个伸缩规则，能够区分简单的事实查询还是复杂问题的研究，让智能体的资源利用率达到最高。现在向深度思考的大模型一些简单的问题，比如：今天星期几？1+1 等于几？大模型还是会自言自语分析一通，很久才会给出答案。这应该就是伸缩规则没有做好。&lt;/p&gt;
&lt;p&gt;9、良好的评估对于构建可靠的 AI 应用至关重要，智能体也不例外。即使输入完全相同，智能体也可能采取完全不同的路径来达到目标。所以，我们需要灵活的评估方法，既能判断智能体是否得到了正确的结果，又能判断它们是否遵循了合理的过程。&lt;/p&gt;
&lt;p&gt;10、这个评估方法有下面几个标准。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;事实准确性（声明是否与来源匹配？）&lt;/li&gt;
&lt;li&gt;引文准确性（引用的来源是否与声明匹配？）&lt;/li&gt;
&lt;li&gt;完整性（是否覆盖了所有被要求的内容？）&lt;/li&gt;
&lt;li&gt;来源质量（是否使用了主要来源而非质量较低的次要来源？）&lt;/li&gt;
&lt;li&gt;以及工具效率（是否以合理的次数使用了正确的工具？）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;11、当然，多智能体也有缺点，比如消耗 token 会非常快，对于智能体之间需要共享上下文、或者智能体之间要频繁交互的不太适合。A2A 的发展应该有助于多智能体的普及。&lt;/p&gt;
&lt;p&gt;读完 Anthropic 的多智能体文章，我也结合我自己的知识有了一些思考。&lt;/p&gt;
&lt;p&gt;1、现阶段，由于单智能体 token 的限制，导致会往多智能体发展，否则很多复杂任务无法进行。但如果有一天技术的进步让 token 的限制不存在了，应该又会回归到单智能体。或者说当 token 不存在限制，智能体之间交互没有障碍，就可以根据场景灵活选择了。&lt;/p&gt;
&lt;p&gt;2、在大模型能力还没那么强的时候，提示词工程很火，后来模型能力增强，特别是推理型模型出来后，提示词工程被弱化了。这篇文章强调提示词依然非常重要，提示词不只是语言沟通，更是任务分配、格式规范的集中承载体。提示词工程是值得系统去学习的。&lt;/p&gt;
&lt;p&gt;3、即使输入完全相同，智能体也可能采取完全不同的路径。也就是说输出是不确定的，尽管可以让大模型进行自评估来提升结果的质量，但对于容错率很低的场景，怎么能保证前 100 次都是对的，第 101 次就不会出现错误呢？&lt;/p&gt;
&lt;p&gt;4、都说 AI 的发展会淘汰掉部分程序员，但从这篇文章表达的思想来看，具备架构思维和能力的程序员一定在未来有一席之地。需要关注整体流程、关注错误处理机制（风险）、关注对结果的评估等。&lt;/p&gt;</description></item><item><title>云原生：一文读懂核心技术栈与演进路径</title><link>https://fwhyy.com/2025/06/cloud-native-technology-stack-and-evolution/</link><pubDate>Tue, 24 Jun 2025 14:36:00 +0800</pubDate><guid>https://fwhyy.com/2025/06/cloud-native-technology-stack-and-evolution/</guid><description>&lt;p&gt;最近，听老板说只要碰到一些大型项目，客户都要求使用云原生技术，让我们在技术储备上也要能跟得上。本文简单讲讲云原生的技术栈以及如何学习。&lt;/p&gt;
&lt;p&gt;云原生（Cloud Native）近些年一直都是软件开发领域的热门话题之一。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;什么是云原生？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;云原生是一种设计和运行软件的方法论，核心思想是充分利用云平台提供的弹性、自动化和按需付费等特性，让应用更易于开发、部署和运维。关于云原生的概念，可以看看《简单聊聊云原生》。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;很多人会问：我单体应用用得好好的，为什么要转向云原生这么复杂的架构呢？实际上，每一种新技术的出现都是为了解决已有问题，但同时也会引入新的挑战，权衡之下，如果利大于弊，就会采用。&lt;/p&gt;
&lt;p&gt;下面我们来一步步分析，看看云原生技术是如何演变而来的。&lt;/p&gt;
&lt;h2 id="云原生包含哪些技术栈"&gt;云原生包含哪些技术栈？&lt;/h2&gt;
&lt;p&gt;目前主流的云原生技术栈（以 Pivotal 和 CNCF 技术栈为基础）包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;微服务（Microservices）&lt;/li&gt;
&lt;li&gt;容器（Containers，如 Docker）&lt;/li&gt;
&lt;li&gt;容器编排（Container Orchestration，如 Kubernetes）&lt;/li&gt;
&lt;li&gt;服务网格（Service Mesh）&lt;/li&gt;
&lt;li&gt;声明式 API（Declarative API）&lt;/li&gt;
&lt;li&gt;不可变基础设施（Immutable Infrastructure）&lt;/li&gt;
&lt;li&gt;持续集成和持续交付（CI/CD）&lt;/li&gt;
&lt;li&gt;DevOps&lt;/li&gt;
&lt;li&gt;无服务器架构（Serverless）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="企业为什么需要云原生"&gt;企业为什么需要云原生？&lt;/h2&gt;
&lt;p&gt;对企业来说，降本增效非常重要，面对复杂的系统，使用云原生技术可以达到这个目的。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;降低成本：通过容器技术，能提高资源利用率，降低整体成本。&lt;/li&gt;
&lt;li&gt;提升效率：云原生架构下的部署更快速、更灵活，明显提升开发和交付效率。&lt;/li&gt;
&lt;li&gt;提高业务承载力：云原生能快速扩容，应对高并发业务需求。&lt;/li&gt;
&lt;li&gt;提升稳定性：健康检查和不可变基础设施让系统更稳定、更可靠。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="云原生技术栈是如何演变的"&gt;云原生技术栈是如何演变的？&lt;/h2&gt;
&lt;h3 id="1微服务"&gt;1、微服务&lt;/h3&gt;
&lt;p&gt;1967 年，计算机科学家梅尔文·康威（Melvin Conway）提出过一个观点：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;组织的设计（包括其沟通结构和团队划分）会影响其生产的系统架构。具体来说，软件的架构往往反映了组织的沟通结构。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这就是著名的康威定律。&lt;/p&gt;
&lt;p&gt;最初，软件往往是以单体应用的方式存在。当系统规模和业务复杂度增加时，组织就可能进行拆分，每一个小团队负责一个模块，这些团队甚至可能是分布式的。&lt;/p&gt;
&lt;p&gt;组织的变化必然会让单体应用慢慢向微服务进行转变。不变不行啊，不然沟通成本太高了。&lt;/p&gt;
&lt;p&gt;如果组织没有发生变化，强行去进行微服务拆分，会发现代码的管理、维护会变得复杂（即便是用上自动化工具），所以说有什么样的组织就有什么样的架构。&lt;/p&gt;
&lt;p&gt;微服务将应用拆分成多个小而独立的服务，每个服务可以独立开发、部署、扩展，从而大大提高了灵活性和可维护性。但随之也出现了服务间通信复杂、部署管理困难等问题。&lt;/p&gt;
&lt;p&gt;之前写的几篇微服务相关的文章：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;《微服务：我们需要从单体转到微服务吗？》&lt;/li&gt;
&lt;li&gt;《微服务：事务管理》&lt;/li&gt;
&lt;li&gt;《微服务：如何拆分服务》&lt;/li&gt;
&lt;li&gt;《微服务：服务间通信概述》&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2容器化docker"&gt;2、容器化（Docker）&lt;/h3&gt;
&lt;p&gt;微服务早在 2011 年就被提出，但近些年才火起来，靠的就是容器技术的普及。&lt;/p&gt;
&lt;p&gt;微服务越来越多，手动部署变得异常复杂。Docker 这类容器技术的出现，使发布的程序和依赖的中间件能被封装到容器中，极大地简化了部署过程。&lt;/p&gt;
&lt;p&gt;开发人员无需关注底层环境，容器的运行环境高度一致。在这之前，经常会有一些莫名其妙的问题，最后的原因就是各种环境配置的不一致。&lt;/p&gt;
&lt;p&gt;然而，随着系统变得复杂，服务拆分的多，还要上各种中间件，容器数量就会越来越多，就会带来容器管理的问题，单靠 Docker 已经无法应对。&lt;/p&gt;
&lt;h3 id="3容器编排kubernetes"&gt;3、容器编排（Kubernetes）&lt;/h3&gt;
&lt;p&gt;容器编排技术随着容器化应用规模的扩大而诞生，主要是为了解决容器在生产环境中批量运行和管理的复杂性问题。最初，Docker 可以很好地处理单个或少量服务，但随着企业应用转向微服务架构，管理大量容器变得困难，仅仅靠人工的方式肯定会错漏百出。&lt;/p&gt;
&lt;p&gt;为了解决这些问题，出现了容器编排技术，简单的有 docker compose ，测试环境和要求不高的生产环境中经常会用到。功能强大的有 Kubernetes ，提供自动部署、服务发现、负载均衡、健康检查、自动扩缩容等功能。&lt;/p&gt;
&lt;p&gt;不过，容器编排技术的引入也会带来新的问题，包括系统复杂性提升、配置管理繁琐和安全性挑战。为应对这些问题，逐渐发展出了新工具，如 Helm、Rancher、OpenShift、Istio、Prometheus、Grafana 等。&lt;/p&gt;
&lt;h3 id="4服务网格service-mesh"&gt;4、服务网格（Service Mesh）&lt;/h3&gt;
&lt;p&gt;随着微服务规模扩大，服务间通信的管理要求变得更高，仅依靠 Kubernetes 等容器编排平台难以全面、高效地实现服务通信治理功能，就需要服务网格出场了。&lt;/p&gt;
&lt;p&gt;服务网格（Service Mesh）是服务间通信的基础设施层。&lt;/p&gt;
&lt;p&gt;它通过在微服务之间注入轻量级网络代理，统一处理服务发现、负载均衡、安全认证、流量控制、故障恢复等功能，非侵入式地解耦服务治理与业务逻辑。&lt;/p&gt;
&lt;p&gt;到这可以发现，技术的演进都有相似性，本质上都是为了将通用能力从核心业务中剥离出来，通过更抽象、更统一的方式进行管理与复用。这种思路在软件开发的多个阶段中屡见不鲜。比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在架构阶段，API 网关将认证、限流、协议转换等边缘治理能力集中处理、配置中心实现了配置的集中化、动态化管理。&lt;/li&gt;
&lt;li&gt;在编码阶段，我们引入了 AOP（面向切面编程） 来将日志、事务、安全等横切关注点独立出来，实现与业务逻辑的解耦、通过工具类或SDK封装公共逻辑，提高复用性。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Istio 是目前比较火的一个开源服务网格，大概逻辑就是每个服务会被注入一个 Sidecar 组件，服务之间的通信会先经过 Sidecar，然后 Sidecar 再将请求转发给另一个服务。因为请求都经过Sidecar，所以可以通过 Sidecar 实现很多通用功能。&lt;/p&gt;
&lt;h3 id="5持续集成与持续交付cicd"&gt;5、持续集成与持续交付（CI/CD）&lt;/h3&gt;
&lt;p&gt;服务变多，引入了更多的技术，系统变得更复杂了，就需要更多的手段来进行效率和稳定性的提升。&lt;/p&gt;
&lt;p&gt;CI/CD 技术通过自动化的方式完成代码检查、测试、构建、部署任务。自动化不仅减少了人工操作带来的失误，也提升了迭代速度与产品质量。&lt;/p&gt;
&lt;p&gt;CI 是持续集成，CD 有两层含义（持续交付和持续部署）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;持续集成：代码合并到特定分支的过程，这中间有静态扫描、单元测试等。&lt;/li&gt;
&lt;li&gt;持续交付：将构建后的产物发布到测试环境，预生产环境。&lt;/li&gt;
&lt;li&gt;持续部署：将经过充分测试的代码自动部署到生产环境。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CI/CD 可以让我们避免重复操作，提前发现问题，减少人工错误，让系统更加稳定。&lt;/p&gt;</description></item><item><title>如何构建多智能体研究系统（翻译）</title><link>https://fwhyy.com/2025/06/how-to-build-a-multi-agent-research-system-translation/</link><pubDate>Fri, 20 Jun 2025 15:26:00 +0800</pubDate><guid>https://fwhyy.com/2025/06/how-to-build-a-multi-agent-research-system-translation/</guid><description>&lt;p&gt;我们的研究功能使用多个Claude智能体来更有效地探索复杂主题。我们分享了构建这个系统时遇到的工程挑战和学到的经验教训。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Claude现在具备研究能力，可以在网络、Google Workspace和任何集成中搜索，以完成复杂任务。&lt;/p&gt;
&lt;p&gt;这个多智能体系统从原型到生产的过程教会了我们关于系统架构、工具设计和提示工程的重要经验。多智能体系统由多个智能体（自主使用工具循环的LLM）协同工作组成。我们的研究功能包含一个基于用户查询规划研究过程的智能体，然后使用工具创建并行智能体同时搜索信息。具有多个智能体的系统在智能体协调、评估和可靠性方面带来了新的挑战。&lt;/p&gt;
&lt;p&gt;这篇文章分解了对我们有效的原则——我们希望您在构建自己的多智能体系统时能够发现它们的实用价值。&lt;/p&gt;
&lt;h2 id="多智能体系统的优势"&gt;多智能体系统的优势&lt;/h2&gt;
&lt;p&gt;研究工作涉及开放性问题，很难预先预测所需的步骤。您无法为探索复杂主题硬编码固定路径，因为这个过程本质上是动态的且路径依赖的。当人们进行研究时，他们往往根据发现不断更新方法，跟随调查过程中出现的线索。&lt;/p&gt;
&lt;p&gt;这种不可预测性使AI智能体特别适合研究任务。研究需要灵活性，能够在调查展开时转向或探索切向连接。模型必须自主运行多轮，根据中间发现决定追求哪些方向。线性、一次性的管道无法处理这些任务。&lt;/p&gt;
&lt;p&gt;搜索的本质是压缩：从庞大语料中提炼见解。子智能体通过在自己的上下文窗口中并行运行，同时探索问题的不同方面，然后为主研究智能体浓缩最重要的标记，从而促进压缩。每个子智能体还提供关注点分离——不同的工具、提示和探索轨迹——这减少了路径依赖性并实现了彻底的独立调查。&lt;/p&gt;
&lt;p&gt;一旦智能达到阈值，多智能体系统成为扩展性能的重要方式。例如，尽管个体人类在过去10万年中变得更加智能，但人类社会在信息时代因我们的集体智能和协调能力而呈指数级提高能力。即使是通用智能的智能体在作为个体运行时也面临限制；智能体群体可以完成更多工作。&lt;/p&gt;
&lt;p&gt;我们的内部评估显示，多智能体研究系统在涉及同时追求多个独立方向的广度优先查询方面表现尤为出色。我们发现，以Claude Opus 4为主智能体和Claude Sonnet 4子智能体的多智能体系统在我们的内部研究评估中比单一智能体Claude Opus 4的性能高出90.2%。例如，当被要求识别信息技术标普500指数公司的所有董事会成员时，多智能体系统通过将其分解为子智能体的任务找到了正确答案，而单一智能体系统则因缓慢的顺序搜索而未能找到答案。&lt;/p&gt;
&lt;p&gt;多智能体系统之所以有效，主要是因为它们帮助使用足够的标记来解决问题。在我们的分析中，三个因素解释了BrowseComp评估（测试浏览智能体定位难以找到信息的能力）中95%的性能差异。我们发现标记使用本身解释了80%的差异，工具调用次数和模型选择是另外两个解释因素。这一发现验证了我们的架构，该架构将工作分配给具有独立上下文窗口的智能体，为并行推理增加更多容量。最新的Claude模型在标记使用上充当大型效率乘数，升级到Claude Sonnet 4比在Claude Sonnet 3.7上将标记预算翻倍带来更大的性能提升。多智能体架构有效地扩展了超出单一智能体限制的任务的标记使用。&lt;/p&gt;
&lt;p&gt;有一个缺点：实际上，这些架构会快速消耗标记。在我们的数据中，智能体通常使用比聊天交互多约4倍的标记，而多智能体系统使用比聊天多约15倍的标记。为了经济可行，多智能体系统需要任务的价值足够高，以支付增加的性能成本。此外，一些需要所有智能体共享相同上下文或涉及智能体之间许多依赖关系的领域目前不适合多智能体系统。例如，大多数编码任务比研究涉及更少的真正可并行化任务，LLM智能体在实时协调和委派给其他智能体方面尚不出色。我们发现，多智能体系统在涉及大量并行化、超出单一上下文窗口的信息以及与众多复杂工具接口的有价值任务中表现出色。&lt;/p&gt;
&lt;h2 id="研究的架构概述"&gt;研究的架构概述&lt;/h2&gt;
&lt;p&gt;我们的研究系统使用具有协调者-工作者模式的多智能体架构，其中主智能体协调过程，同时委派给并行运行的专业子智能体。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202506241128639.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;当用户提交查询时，主智能体分析它，制定策略，并生成子智能体同时探索不同方面。如上图所示，子智能体通过迭代使用搜索工具收集信息（在本例中是关于2025年AI智能体公司的信息）充当智能过滤器，然后向主智能体返回公司列表，以便它可以编制最终答案。&lt;/p&gt;
&lt;p&gt;使用检索增强生成（RAG）的传统方法使用静态检索。也就是说，它们获取与输入查询最相似的一组块，并使用这些块生成响应。相比之下，我们的架构使用多步搜索，动态查找相关信息，适应新发现，并分析结果以制定高质量答案。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202506241128866.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="研究智能体的提示工程和评估"&gt;研究智能体的提示工程和评估&lt;/h2&gt;
&lt;p&gt;多智能体系统与单一智能体系统有关键区别，包括协调复杂性的快速增长。早期智能体犯了错误，如为简单查询生成50个子智能体，无休止地搜索网络寻找不存在的来源，以及用过多更新相互干扰。由于每个智能体都由提示引导，提示工程是我们改进这些行为的主要杠杆。以下是我们学到的提示智能体的一些原则：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;像智能体一样思考&lt;/strong&gt;。要迭代提示，您必须了解它们的效果。为了帮助我们做到这一点，我们使用我们的Console构建了模拟，使用系统中的确切提示和工具，然后一步步观察智能体工作。这立即揭示了失败模式：智能体在已经有足够结果时继续，使用过于冗长的搜索查询，或选择不正确的工具。有效的提示依赖于开发对智能体的准确心理模型，这可以使最有影响力的变化变得明显。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;教协调者如何委派&lt;/strong&gt;。在我们的系统中，主智能体将查询分解为子任务并向子智能体描述它们。每个子智能体需要一个目标、输出格式、关于使用工具和来源的指导以及明确的任务边界。没有详细的任务描述，智能体会重复工作，留下空白，或无法找到必要的信息。我们最初允许主智能体给出简单、简短的指令，如&amp;quot;研究半导体短缺&amp;quot;，但发现这些指令通常模糊到子智能体误解任务或与其他智能体执行完全相同的搜索。例如，一个子智能体探索了2021年汽车芯片危机，而另外2个重复工作调查当前2025年供应链，没有有效的分工。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;根据查询复杂性调整努力&lt;/strong&gt;。智能体难以判断不同任务的适当努力，因此我们在提示中嵌入了扩展规则。简单的事实查找只需要1个智能体进行3-10次工具调用，直接比较可能需要2-4个子智能体，每个进行10-15次调用，而复杂研究可能使用10个以上具有明确分工的子智能体。这些明确的指导方针帮助主智能体有效分配资源，防止对简单查询过度投资，这是我们早期版本中常见的失败模式。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;工具设计和选择至关重要&lt;/strong&gt;。智能体-工具接口与人机接口一样关键。使用正确的工具是高效的——通常，这是绝对必要的。例如，智能体在网络上搜索只存在于Slack中的上下文注定从一开始就失败。使用为模型提供外部工具访问权限的MCP服务器，这个问题会加剧，因为智能体会遇到具有质量差异很大的描述的未见过的工具。我们给智能体提供了明确的启发式方法：例如，首先检查所有可用工具，将工具使用与用户意图匹配，搜索网络进行广泛的外部探索，或偏好专业工具而非通用工具。糟糕的工具描述可能会将智能体引向完全错误的路径，因此每个工具都需要明确的目的和清晰的描述。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;让智能体自我改进&lt;/strong&gt;。我们发现Claude 4模型可以成为出色的提示工程师。当给定提示和失败模式时，它们能够诊断智能体失败的原因并提出改进建议。我们甚至创建了一个工具测试智能体——当给定有缺陷的MCP工具时，它尝试使用该工具，然后重写工具描述以避免失败。通过数十次测试工具，这个智能体发现了关键细微差别和错误。这个改进工具人体工程学的过程导致使用新描述的未来智能体的任务完成时间减少了40%，因为它们能够避免大多数错误。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;先广泛，再缩小范围&lt;/strong&gt;。搜索策略应该反映专家人类研究：在深入细节之前探索全局。智能体通常默认使用过长、过于具体的查询，返回很少结果。我们通过提示智能体从简短、广泛的查询开始，评估可用内容，然后逐步缩小焦点来抵消这种趋势。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;引导思考过程&lt;/strong&gt;。扩展思考模式，引导Claude在可见思考过程中输出额外标记，可以作为可控的草稿本。主智能体使用思考来规划其方法，评估哪些工具适合任务，确定查询复杂性和子智能体数量，并定义每个子智能体的角色。我们的测试表明，扩展思考改进了指令遵循、推理和效率。子智能体也进行规划，然后在工具结果后使用交错思考来评估质量，识别差距，并完善下一个查询。这使子智能体更有效地适应任何任务。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;并行工具调用改变速度和性能&lt;/strong&gt;。复杂研究任务自然涉及探索多个来源。我们早期的智能体执行顺序搜索，这非常缓慢。为了提高速度，我们引入了两种并行化：(1)主智能体并行而非串行启动3-5个子智能体；(2)子智能体并行使用3+个工具。这些变化将复杂查询的研究时间减少了高达90%，使研究能够在几分钟而非几小时内完成更多工作，同时覆盖比其他系统更多的信息。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我们的提示策略专注于灌输良好的启发式方法而非严格规则。我们研究了熟练人类如何处理研究任务，并在我们的提示中编码了这些策略——如将困难问题分解为更小的任务，仔细评估来源质量，根据新信息调整搜索方法，以及识别何时专注于深度（详细调查一个主题）与广度（并行探索多个主题）。我们还通过设置明确的护栏来主动减轻意外副作用，防止智能体失控。最后，我们专注于具有可观察性和测试用例的快速迭代循环。&lt;/p&gt;
&lt;h2 id="智能体的有效评估"&gt;智能体的有效评估&lt;/h2&gt;
&lt;p&gt;良好的评估对于构建可靠的AI应用至关重要，智能体也不例外。然而，评估多智能体系统带来独特挑战。传统评估通常假设AI每次都遵循相同步骤：给定输入X，系统应该遵循路径Y产生输出Z。但多智能体系统不是这样工作的。即使起点相同，智能体可能采取完全不同的有效路径达到目标。一个智能体可能搜索三个来源，而另一个搜索十个，或者它们可能使用不同工具找到相同答案。因为我们并不总是知道正确步骤是什么，我们通常不能仅检查智能体是否遵循了我们预先规定的&amp;quot;正确&amp;quot;步骤。相反，我们需要灵活的评估方法，判断智能体是否达到了正确结果，同时也遵循了合理过程。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;立即开始用小样本评估&lt;/strong&gt;。在早期智能体开发中，变化往往有戏剧性影响，因为有大量容易实现的改进。提示调整可能将成功率从30%提高到80%。效果如此之大，您只需几个测试用例就能发现变化。我们从代表真实使用模式的约20个查询集开始。测试这些查询通常让我们清楚看到变化的影响。我们经常听说AI开发团队推迟创建评估，因为他们认为只有包含数百个测试用例的大型评估才有用。然而，最好立即开始小规模测试，而不是推迟到可以构建更全面的评估。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;作为评判的LLM在做得好时可扩展&lt;/strong&gt;。研究输出难以程序化评估，因为它们是自由形式文本，很少有单一正确答案。LLM自然适合评分输出。我们使用LLM评判，根据评分标准评估每个输出：事实准确性（声明是否与来源匹配？），引用准确性（引用的来源是否与声明匹配？），完整性（是否涵盖所有请求方面？），来源质量（是否使用主要来源而非低质量二手来源？），以及工具效率（是否合理次数使用正确工具？）。我们尝试使用多个评判来评估每个组件，但发现单一LLM调用，使用单一提示输出0.0-1.0分数和通过-失败等级，与人类判断最一致。当评估测试用例确实有明确答案时，这种方法特别有效，我们可以使用LLM评判简单检查答案是否正确（例如，它是否准确列出了研发预算最大的前3家制药公司？）。使用LLM作为评判让我们能够可扩展地评估数百个输出。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;人类评估捕捉自动化遗漏的内容&lt;/strong&gt;。测试智能体的人们发现评估遗漏的边缘情况。这些包括不寻常查询上的幻觉答案、系统故障或微妙的来源选择偏见。在我们的案例中，人类测试者注意到我们早期的智能体一致选择SEO优化的内容农场，而非权威但排名较低的来源，如学术PDF或个人博客。在我们的提示中添加来源质量启发式方法帮助解决了这个问题。即使在自动评估的世界中，手动测试仍然至关重要。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;多智能体系统具有涌现行为，这些行为在没有特定编程的情况下出现。例如，对主智能体的小变化可能不可预测地改变子智能体的行为方式。成功需要理解交互模式，而不仅仅是个体智能体行为。因此，这些智能体的最佳提示不仅仅是严格指令，而是定义分工、问题解决方法和努力预算的协作框架。正确实现这一点依赖于仔细的提示和工具设计、坚实的启发式方法、可观察性和紧密的反馈循环。请参阅我们Cookbook中的开源提示，了解系统中的示例提示。&lt;/p&gt;
&lt;h2 id="生产可靠性和工程挑战"&gt;生产可靠性和工程挑战&lt;/h2&gt;
&lt;p&gt;在传统软件中，错误可能破坏功能、降低性能或导致中断。在智能体系统中，微小变化级联成大的行为变化，这使得为必须在长时间运行过程中维护状态的复杂智能体编写代码非常困难。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;智能体有状态且错误复合&lt;/strong&gt;。智能体可以长时间运行，在多次工具调用中维护状态。这意味着我们需要持久执行代码并处理途中的错误。没有有效缓解措施，微小系统故障对智能体可能是灾难性的。当错误发生时，我们不能只是从头重启：重启对用户来说既昂贵又令人沮丧。相反，我们构建了可以从错误发生时智能体所处位置恢复的系统。我们还使用模型的智能优雅处理问题：例如，让智能体知道工具何时失败并让它适应，效果出奇地好。我们将基于Claude构建的AI智能体的适应性与确定性保障（如重试逻辑和定期检查点）相结合。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;调试受益于新方法&lt;/strong&gt;。智能体做出动态决策，即使使用相同提示，在运行之间也是非确定性的。这使调试更加困难。例如，用户会报告智能体&amp;quot;找不到明显信息&amp;quot;，但我们看不出为什么。智能体是否使用了糟糕的搜索查询？选择了糟糕的来源？遇到工具故障？添加完整生产跟踪让我们诊断智能体失败原因并系统地修复问题。除了标准可观察性外，我们还监控智能体决策模式和交互结构——所有这些都不监控个人对话内容，以维护用户隐私。这种高级可观察性帮助我们诊断根本原因，发现意外行为，并修复常见故障。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;部署需要仔细协调&lt;/strong&gt;。智能体系统是高度有状态的提示、工具和执行逻辑网络，几乎连续运行。这意味着每当我们部署更新时，智能体可能处于其过程中的任何位置。因此，我们需要防止我们善意的代码更改破坏现有智能体。我们不能同时将每个智能体更新到新版本。相反，我们使用彩虹部署避免中断运行中的智能体，通过逐渐将流量从旧版本转移到新版本，同时保持两者同时运行。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;同步执行创建瓶颈&lt;/strong&gt;。目前，我们的主智能体同步执行子智能体，等待每组子智能体完成后再继续。这简化了协调，但在智能体之间的信息流中创建了瓶颈。例如，主智能体无法引导子智能体，子智能体无法协调，整个系统可能在等待单个子智能体完成搜索时被阻塞。异步执行将启用额外并行性：智能体并发工作并在需要时创建新子智能体。但这种异步性在子智能体之间的结果协调、状态一致性和错误传播方面增加了挑战。随着模型能够处理更长更复杂的研究任务，我们预计性能增益将证明复杂性是合理的。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="结论"&gt;结论&lt;/h2&gt;
&lt;p&gt;构建AI智能体时，最后一英里通常成为旅程的大部分。在开发者机器上工作的代码库需要大量工程才能成为可靠的生产系统。智能体系统中错误的复合性质意味着传统软件的微小问题可能完全使智能体脱轨。一个步骤失败可能导致智能体探索完全不同的轨迹，导致不可预测的结果。由于本文描述的所有原因，原型和生产之间的差距通常比预期更大。&lt;/p&gt;
&lt;p&gt;尽管存在这些挑战，多智能体系统已证明对开放式研究任务有价值。用户表示，Claude帮助他们发现未曾考虑的商业机会，导航复杂的医疗保健选择，解决棘手的技术错误，并通过发现他们单独无法找到的研究联系，节省了长达数天的工作时间。多智能体研究系统可以通过仔细的工程、全面测试、注重细节的提示和工具设计、强大的运营实践以及对当前智能体能力有深入了解的研究、产品和工程团队之间的紧密协作，在规模上可靠运行。我们已经看到这些系统正在改变人们解决复杂问题的方式。&lt;/p&gt;
&lt;h2 id="致谢"&gt;致谢&lt;/h2&gt;
&lt;p&gt;由Jeremy Hadfield、Barry Zhang、Kenneth Lien、Florian Scholz、Jeremy Fox和Daniel Ford撰写。这项工作反映了使研究功能成为可能的Anthropic多个团队的集体努力。特别感谢Anthropic应用工程团队，他们的奉献使这个复杂的多智能体系统投入生产。我们也感谢早期用户提供的出色反馈。&lt;/p&gt;
&lt;h2 id="附录"&gt;附录&lt;/h2&gt;
&lt;p&gt;以下是关于多智能体系统的一些额外杂项提示。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;在多轮中改变状态的智能体的终态评估&lt;/strong&gt;。评估在多轮对话中修改持久状态的智能体带来独特挑战。与只读研究任务不同，每个操作都可能改变后续步骤的环境，创建传统评估方法难以处理的依赖关系。我们发现成功专注于终态评估而非逐轮分析。不是判断智能体是否遵循特定过程，而是评估它是否达到了正确的最终状态。这种方法承认智能体可能找到通向相同目标的替代路径，同时仍确保它们提供预期结果。对于复杂工作流，将评估分解为应该发生特定状态变化的离散检查点，而不是尝试验证每个中间步骤。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;长期对话管理&lt;/strong&gt;。生产智能体通常参与跨越数百轮的对话，需要仔细的上下文管理策略。随着对话延伸，标准上下文窗口变得不足，需要智能压缩和记忆机制。我们实现了模式，智能体在继续新任务前总结已完成的工作阶段并在外部记忆中存储基本信息。当上下文限制接近时，智能体可以生成具有干净上下文的新子智能体，同时通过仔细交接维持连续性。此外，它们可以从记忆中检索存储的上下文，如研究计划，而不是在达到上下文限制时丢失先前工作。这种分布式方法防止上下文溢出，同时在延长交互中保持对话连贯性。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;子智能体输出到文件系统以最小化&amp;quot;电话游戏&amp;quot;&lt;/strong&gt;。直接子智能体输出可以绕过主协调者处理某些类型的结果，提高保真度和性能。不是要求子智能体通过主智能体传达所有内容，而是实现工件系统，专业智能体可以创建独立持久的输出。子智能体调用工具将其工作存储在外部系统中，然后将轻量级引用传回协调者。这防止了多阶段处理期间的信息丢失，并减少了通过对话历史复制大型输出的标记开销。这种模式对结构化输出（如代码、报告或数据可视化）特别有效，其中子智能体的专业提示产生比通过通用协调者过滤更好的结果。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>A2A 介绍：概念篇</title><link>https://fwhyy.com/2025/06/a2a-introduction-concept-chapter/</link><pubDate>Mon, 16 Jun 2025 17:38:00 +0800</pubDate><guid>https://fwhyy.com/2025/06/a2a-introduction-concept-chapter/</guid><description>&lt;p&gt;在之前的文章中介绍过 MCP：《MCP 和 Function Calling：概念》和《MCP 和 Function Calling：示例》。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;谷歌 2025 年 4 月 9 日发布了 A2A 协议，下面是最近学习的总结。&lt;/p&gt;
&lt;h2 id="先理解几个概念"&gt;先理解几个概念&lt;/h2&gt;
&lt;p&gt;首先理解几个概念：智能体（AI Agent）、工具、大模型。下面用一个实际的场景来解释。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我们让 AI 规划一个十一旅游的行程，AI 进行思考、判断、最终做出决策，需要先去了解十一的天气怎么样，需要去了解我之前都去过哪些地方，哪些地方没去过等等，最终给出一个计划。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;AI 需要思考，最终做出决策，靠的是大模型。&lt;/li&gt;
&lt;li&gt;去查询天气、去私有库查询旅行的历史数据，这就需要工具。&lt;/li&gt;
&lt;li&gt;能接收输入（人类发送的指令）、大模型思考并执行（使用工具）后产出结果的一类东西可以认为是智能体。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;再举一个例子：让一个“开发智能体”开发一个 Obsidian 插件：实现同步内容到笔记软件中，AI 接收到开发要求和笔记软件的 API 文档，然后调用查看网页的工具进行 API 文档的学习，最后结合大模型的知识输出插件代码。&lt;/p&gt;
&lt;p&gt;总之，一个智能体可以感知、思考和行动。&lt;/p&gt;
&lt;h2 id="什么是-a2a"&gt;什么是 A2A？&lt;/h2&gt;
&lt;p&gt;上面提到的开发插件的例子，一个智能体就搞定了，这是因为插件非常简单。那如果开发复杂的企业级应用系统呢？单个智能体就搞不定了。&lt;/p&gt;
&lt;p&gt;一个复杂的需求来了，需要不同的角色分工合作，交给 AI 也是如此，下面简单列举几个角色：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;技术负责人：理解需求，进行架构设计和开发任务分派。&lt;/li&gt;
&lt;li&gt;开发：这里面包含前端和后端，接到任务按照要求完成代码编写。&lt;/li&gt;
&lt;li&gt;测试：对提交的成果进行验证。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些角色都可以是一个个独立的智能体，在整个开发的过程中，负责人和开发、测试需要沟通；开发的前后端之间需要沟通，开发和测试之间也需要沟通。&lt;/p&gt;
&lt;p&gt;如果这些角色都是来自不同国家的人，互相之间语言不通，沟通成本就非常高了。&lt;/p&gt;
&lt;p&gt;A2A 的出现就是为了解决这个沟通问题，让每个角色都具备一种通用语言。&lt;/p&gt;
&lt;p&gt;A2A 协议是一套开放标准，它为不同供应商、不同框架开发的智能体之间提供了一种通用沟通语言。&lt;/p&gt;
&lt;p&gt;在整个过程中，A2A 协议干了下面几件事情：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标准化交互：所有 Agent 基于统一的消息规范进行能力发现与调用。&lt;/li&gt;
&lt;li&gt;高效并发：支持流式响应与非阻塞调用，实现多任务并行处理。&lt;/li&gt;
&lt;li&gt;动态扩展：新 Agent 可无缝接入系统，无需定制化适配。&lt;/li&gt;
&lt;li&gt;职责分离：Agent 专注于业务逻辑，协议层统一处理通信传输、安全认证与异常管理。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="为什么会出现-a2a"&gt;为什么会出现 A2A？&lt;/h2&gt;
&lt;p&gt;智能体（Agent）需要像人类一样分工协作以解决复杂任务。每个 Agent 具备独特能力，必须通过信息交换与知识共享实现协同。&lt;/p&gt;
&lt;p&gt;然而，不同开发者创建的 Agent 若采用不同的沟通标准，如同人类使用不同语言交流，将导致理解错位与协作混乱，严重阻碍任务执行效率。这种标准化缺失成为多智能体系统的核心瓶颈。&lt;/p&gt;
&lt;p&gt;当大量不同 Agent（来自企业、开源项目等）涌入生态时，私有化通信协议使交互成本激增。例如，调度 Agent 可能无法理解执行 Agent 的状态反馈，这种“鸡同鸭讲”的局面迫使系统需要一种通用“语言”来承载需求、能力、决策等核心信息的无损传递。&lt;/p&gt;
&lt;p&gt;A2A 协议应运而生，其通过定义统一的消息格式、交互流程与语义规范，构建了智能体间的“通用语”。无论 Agent 底层架构差异如何，均可通过 A2A 声明能力、发送请求、同步状态。&lt;/p&gt;
&lt;h2 id="a2a-和-mcp-的异同点"&gt;A2A 和 MCP 的异同点&lt;/h2&gt;
&lt;h3 id="相同点"&gt;相同点&lt;/h3&gt;
&lt;p&gt;1、标准化协议：两者都是为了解决信息孤岛，提供统一的、标淮的通信机制，使得不同服务或 Agent 可以顺畅沟通。&lt;/p&gt;
&lt;p&gt;2、通用与可扩展：都可以扩展到多种应用场景，无论是工具调用、资源整合（MCP），还是智能代理之间的协作沟通 (A2A)。&lt;/p&gt;
&lt;p&gt;3、交互机制：核心交互模式都基于类似 Client-Server 或 Peer-to-Peer 的请求-响应机制。&lt;/p&gt;
&lt;h3 id="不同点"&gt;不同点&lt;/h3&gt;
&lt;p&gt;1、核心目标&lt;/p&gt;
&lt;p&gt;MCP：连接模型与工具，专注于让大模型（LLM）调用和使用外部工具/资源（API、数据库等），提供结构化、确定性的接口。&lt;/p&gt;
&lt;p&gt;A2A：实现 Agent 间协作，专注于定义多个智能体（Agent）如何沟通、协调以完成任务。&lt;/p&gt;
&lt;p&gt;2、交互粒度&lt;/p&gt;
&lt;p&gt;MCP：精细，处理具体动作细节（如工具调用、参数传递、结果解析等）。&lt;/p&gt;
&lt;p&gt;A2A：抽象，关注任务层面协作（如任务请求、状态通告、结果反馈）。&lt;/p&gt;</description></item><item><title>插件开发：实现Obsidian同步到墨问笔记</title><link>https://fwhyy.com/2025/05/plugin-development-implement-obsidian-synchronization-to-mowen-notes/</link><pubDate>Fri, 30 May 2025 16:47:00 +0800</pubDate><guid>https://fwhyy.com/2025/05/plugin-development-implement-obsidian-synchronization-to-mowen-notes/</guid><description>&lt;p&gt;墨问笔记是微信的一个小程序，功能越来越强大，最近发布了 OpenAPI 和 MCP ，本文简单介绍下怎么写一个插件将 Obsidian 中的内容发布到墨问笔记中。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;主要功能如下：&lt;/p&gt;
&lt;p&gt;1、将 Obsidian 中的选中的文本或完整文章发布到墨问。&lt;/p&gt;
&lt;p&gt;2、可以通过右键菜单或者命令进行笔记的发布。&lt;/p&gt;
&lt;p&gt;3、点击发布后会弹出界面输入标题和标签。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202505301748099.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;插件开发的步骤如下：&lt;/p&gt;
&lt;p&gt;1、开发工具使用字节出的 Trae 国际版，模型使用 Claude-4-sonnet，付费用户不用排队，首月只需要 3 刀，值得一试。&lt;/p&gt;
&lt;p&gt;2、在墨问后台获取 API Key 。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202505301749670.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击获取 API Key ，留着备用。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202505301749534.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3、在 Trae 中选择 Builder 模式，一定得是 Builder 模式，否则不会自动创建文件，对话框中输入下面内容。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我现在要开发一个obsidian插件，这个插件的作用如下：1、选择一段文本，点击右键，点击publish to mowen ，可以弹出界面让我输入标题和tag，确定后调用api发布到墨问笔记；2、点击右上角三个点，在展开的菜单中点击 publish to mowen 可以将当前文章发布到墨问笔记，弹出的窗口中自动带出当前文章的标题，可以允许修改。 墨问笔记创建的接口文档地址如下： &lt;a href="https://mowen.apifox.cn/295621359e0"&gt;https://mowen.apifox.cn/295621359e0&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;4、等待几分钟，会自动生成所有项目文件，并且会提示需要执行下面的命令，点击接受即可。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm run build
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;5、执行过 &lt;code&gt;npm run build&lt;/code&gt; 后会产生打包后的文件，最终将下面红框中的三个文件复制到 Obsidian 的插件目录中。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202505301749642.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;6、在 Obsidian 中，进入插件的设置界面，将获取的 API Key 输入到对应的文本框中。API URL 检查是否正确。正确应该为：https://open.mowen.cn/api/open/api/v1/note/create&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202505301749200.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;7、需要注意的是，如果重新覆盖了 main.js 文件后，需要重新加载插件（禁用后重新启用）才能生效。&lt;/p&gt;
&lt;p&gt;8、现在可以验证下功能是否正常，选择一段文本点击右键，在弹出的菜单中选择“
publish to mowen” 。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202505301749244.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;9、点击 “Publish” 按钮进行发布，如果出现成功提示，就去墨问笔记中查看是否创建了新的笔记。如果出现错误，将错误提示反馈给 Trae，Trae 会分析错误进行代码修复。&lt;/p&gt;
&lt;p&gt;10、Trae 第一次生成的程序我就没有执行成功，原因是 body 内容格式不对，我就将 NoteAtom 的结构说明文档连接：https://mowen.apifox.cn/6682171m0 丢给了 Trae，就修改成功了。&lt;/p&gt;
&lt;p&gt;插件代码地址：https://github.com/oec2003/obsidian-pub-to-mowen-plugin&lt;/p&gt;</description></item><item><title>MCP 和 Function Calling：示例</title><link>https://fwhyy.com/2025/04/mcp-and-function-calling-examples/</link><pubDate>Wed, 16 Apr 2025 18:48:00 +0800</pubDate><guid>https://fwhyy.com/2025/04/mcp-and-function-calling-examples/</guid><description>&lt;p&gt;在上一篇《MCP 和 Function Calling：概念》中简单介绍了 MCP 和 Function Calling 的基础概念和执行逻辑。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;本文以实际例子来加深对 MCP 和 Function Calling 的理解。&lt;/p&gt;
&lt;p&gt;实现这样一个场景：和大模型聊天，然后让大模型将回答的内容保存到 flomo 笔记中。&lt;/p&gt;
&lt;h2 id="function-calling"&gt;Function Calling&lt;/h2&gt;
&lt;p&gt;我们知道 Function Calling 和模型的能力有关，我使用的是 qwen2.5:7b 模型，使用 ollama 在本地运行。&lt;/p&gt;
&lt;h2 id="思路"&gt;思路&lt;/h2&gt;
&lt;p&gt;1、写一个 api 接口，这个接口的作用就是将输入的值存入 flomo 笔记中。&lt;/p&gt;
&lt;p&gt;2、利用 qwen-agent 框架，来实现 function calling ，最终调用自定义开发的 api 接口。&lt;/p&gt;
&lt;h3 id="实现"&gt;实现&lt;/h3&gt;
&lt;p&gt;1、api 接口使用任何语言都行，我这里使用的是 python 的 flask 框架。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;span class="lnt"&gt;50
&lt;/span&gt;&lt;span class="lnt"&gt;51
&lt;/span&gt;&lt;span class="lnt"&gt;52
&lt;/span&gt;&lt;span class="lnt"&gt;53
&lt;/span&gt;&lt;span class="lnt"&gt;54
&lt;/span&gt;&lt;span class="lnt"&gt;55
&lt;/span&gt;&lt;span class="lnt"&gt;56
&lt;/span&gt;&lt;span class="lnt"&gt;57
&lt;/span&gt;&lt;span class="lnt"&gt;58
&lt;/span&gt;&lt;span class="lnt"&gt;59
&lt;/span&gt;&lt;span class="lnt"&gt;60
&lt;/span&gt;&lt;span class="lnt"&gt;61
&lt;/span&gt;&lt;span class="lnt"&gt;62
&lt;/span&gt;&lt;span class="lnt"&gt;63
&lt;/span&gt;&lt;span class="lnt"&gt;64
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@api_bp.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/flomo/save&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_to_flomo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 获取请求数据&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 验证请求数据&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;content&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Missing required field: content&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;content&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;tags&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="c1"&gt;# 可选的标签列表&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 验证Flomo API URL是否配置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;flomo_api_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;FLOMO_API_URL&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;flomo_api_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Flomo API URL not configured&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 准备发送到Flomo的数据&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;flomo_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 如果有标签，添加到内容中&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Flomo使用 #tag 格式的标签&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tag_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;#&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;flomo_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tag_text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 发送请求到Flomo API&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;flomo_api_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flomo_data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="c1"&gt;# 设置超时时间，处理大文本可能需要更长时间&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 检查响应&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Content successfully saved to Flomo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;flomo_response&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Failed to save to Flomo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;status_code&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;response&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestException&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 处理请求异常&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Request to Flomo failed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 处理其他异常&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Unexpected error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;2、创建一个 qwen-client.py 的文件，内容如下：&lt;/p&gt;</description></item><item><title>MCP 和 Function Calling：概念</title><link>https://fwhyy.com/2025/03/mcp-and-function-calling-concepts/</link><pubDate>Mon, 31 Mar 2025 16:45:00 +0800</pubDate><guid>https://fwhyy.com/2025/03/mcp-and-function-calling-concepts/</guid><description>&lt;p&gt;随着人工智能的快速发展，大型语言模型（LLMs）逐渐深入到我们生活与工作的各个方面。然而，尽管模型强大，但其能力仍存在局限性，比如在实时信息获取和复杂任务执行方面仍有不足。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;RAG（检索增强生成）现在在企业的 AI 应用中使用很广泛，就是为了解决模型的信息不够实时，且没有垂直领域知识的问题。&lt;/p&gt;
&lt;p&gt;RAG 虽然厉害，但主要还是应用在智能知识问答领域，大模型想要有更强的能力，就需要有效、安全地与外界进行互动，这就诞生了 Function Calling 和 MCP 。&lt;/p&gt;
&lt;p&gt;Function Calling 依赖大模型的能力，MCP 是一种通用协议。&lt;/p&gt;
&lt;p&gt;本文从概念层面谈谈 Function Calling 和 MCP ，下一篇写几个代码例子。&lt;/p&gt;
&lt;h2 id="function-calling函数调用介绍"&gt;Function Calling（函数调用）介绍&lt;/h2&gt;
&lt;h3 id="概念"&gt;概念&lt;/h3&gt;
&lt;p&gt;Function Calling 是特定大模型（如 OpenAI 的 GPT-4、Qwen2 等）提供的一种机制，使模型能够主动生成结构化输出，以调用外部系统中预定义的函数或 API。&lt;/p&gt;
&lt;h3 id="执行流程"&gt;执行流程&lt;/h3&gt;
&lt;p&gt;通常我们说大模型调用 API，但这种说法并不完全准确，执行过程如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202503311644218.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;0、Agent 程序是我们开发的 AI 程序，在程序中会预先向大模型注册外部函数接口（建议不超过 20 个）。&lt;/p&gt;
&lt;p&gt;1、用户通过自然语言发起请求，Agent 接收到请求。&lt;/p&gt;
&lt;p&gt;2、Agent 程序将用户请求提交给大模型，模型首先解析语义并评估是否需要调用外部工具。&lt;/p&gt;
&lt;p&gt;3、模型如果判断需要调用函数，将生成包含工具 ID 和输入参数的调用指令，并返回给 Agent 程序。&lt;/p&gt;
&lt;p&gt;4、Agent 程序接收到模型返回的调用指令后，执行对工具函数的调用。&lt;/p&gt;
&lt;p&gt;5、工具函数执行后将结果返回给 Agent 程序。&lt;/p&gt;
&lt;p&gt;6、Agent 程序将函数返回的结果和自定义提示词一起反馈给大模型。&lt;/p&gt;
&lt;p&gt;7、大模型融合工具返回的数据与原始上下文，生成最终结果，并返回给 Agent 。&lt;/p&gt;
&lt;p&gt;8、Agent 程序将结果输出呈现给终端用户。&lt;/p&gt;
&lt;h3 id="特点"&gt;特点&lt;/h3&gt;
&lt;p&gt;1、主动调用：模型能够识别用户的自然语言意图，决定是否调用工具，并生成调用指令。&lt;/p&gt;
&lt;p&gt;2、实时反馈：模型生成的函数调用指令，由 Agent 程序执行后，再次反馈给模型，使模型生成实时和精准的回应。&lt;/p&gt;
&lt;p&gt;3、具体实现灵活：没有严格的标准通信协议要求，通信格式取决于具体模型厂商。这是个特点，也是个弊端。&lt;/p&gt;
&lt;h2 id="mcpmodel-context-protocol介绍"&gt;MCP（Model Context Protocol）介绍&lt;/h2&gt;
&lt;h3 id="概念-1"&gt;概念&lt;/h3&gt;
&lt;p&gt;MCP（Model Context Protocol，模型上下文协议）是 Anthropic 公司在 2024 年 11 月推出的一种标准协议。它的目的是给 AI 模型（如大语言模型）和外部数据源或工具之间建立起统一的通信接口。&lt;/p&gt;
&lt;p&gt;可以简单类比为 AI 的 USB 接口，无论是 AI 模型还是外部工具，只要符合 MCP 标准，就可以实现快速“即插即用”的连接，不需要为每个工具单独编写接口程序。也没有变成语言的限制，就像前后端分离后，基于 WebAPI 的规范就可以，什么语言都能写接口。&lt;/p&gt;
&lt;p&gt;现在 OpenAI 也支持了 MCP 。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202503311645324.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h3 id="特点-1"&gt;特点&lt;/h3&gt;
&lt;p&gt;1、开放性：MCP 是开放标准，任何开发者或服务商均可基于此协议开发 API，避免重复造轮子，推动生态共建，目前已有大量 MCP 集合站（如：&lt;a href="https://mcp.so)./"&gt;https://mcp.so）。&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2、标准化：采用 JSON-RPC 2.0 标准通信，确保交互统一、高效。&lt;/p&gt;</description></item><item><title>在Windsurf中使用李继刚提示词</title><link>https://fwhyy.com/2025/03/using-li-jigangs-prompt-words-in-windsurf/</link><pubDate>Sat, 15 Mar 2025 16:01:00 +0800</pubDate><guid>https://fwhyy.com/2025/03/using-li-jigangs-prompt-words-in-windsurf/</guid><description>&lt;p&gt;尽管现在有各种各样的推理模型，但提示词依然很重要，甚至可以玩出很多创意，我觉得提示词是一门艺术。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="提示词"&gt;提示词&lt;/h2&gt;
&lt;p&gt;最近在推上看到李继刚分享了不少提示词，有言外之意、生成 svg 图等。因为个人习惯，李继刚的提示词都是使用 lisp 语言来写的。&lt;/p&gt;
&lt;p&gt;例如有一个解析「言外之意」的提示词如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;span class="lnt"&gt;50
&lt;/span&gt;&lt;span class="lnt"&gt;51
&lt;/span&gt;&lt;span class="lnt"&gt;52
&lt;/span&gt;&lt;span class="lnt"&gt;53
&lt;/span&gt;&lt;span class="lnt"&gt;54
&lt;/span&gt;&lt;span class="lnt"&gt;55
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; ━━━━━━━━━━━━━━&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; 作者: 李继刚&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; 版本: 0.2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; 模型: Claude 3.7 Sonnet&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; 用途: 听话要听音，读懂言外之意&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; ━━━━━━━━━━━━━━&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; 设定如下内容为你的 *System Prompt*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;dash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;伽达默尔&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;听懂你的言外之意&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;list&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;性格&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;敏锐&lt;/span&gt; &lt;span class="nv"&gt;谨慎&lt;/span&gt; &lt;span class="nv"&gt;通达&lt;/span&gt; &lt;span class="nv"&gt;澄明&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;技能&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;洞察&lt;/span&gt; &lt;span class="nv"&gt;推理&lt;/span&gt; &lt;span class="nv"&gt;融会&lt;/span&gt; &lt;span class="nv"&gt;逆思&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;表达&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;简约&lt;/span&gt; &lt;span class="nv"&gt;透彻&lt;/span&gt; &lt;span class="nv"&gt;深刻&lt;/span&gt; &lt;span class="nv"&gt;直白&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;言外之意&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;用户输入&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;伽达默尔看你表演，听懂你没说出来的话音&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let*&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;响应&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;用户输入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;核心命题&lt;/span&gt; &lt;span class="c1"&gt;;; 提炼关键命题，分别做后续处理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;正向推理&lt;/span&gt; &lt;span class="c1"&gt;;; 基于命题往前推理，得到将说未说之意&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;反向逆思&lt;/span&gt; &lt;span class="c1"&gt;;; 强调正面，就意味着反面严重不成立&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;视域融合&lt;/span&gt; &lt;span class="c1"&gt;;; 结合经验和语言含义，得到新的深层理解&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;揶揄讥嘲&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;few-shots&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;我学校是中国 Top 3 院校&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;这货妥妥的是排名第三名的那学校。如果是第一名或第二名，丫直接说出来。&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;你就坐着玩游戏吧，不用过来了。&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;呆子! 这是点你呢！她是想说你敢继续坐着玩，你丫就完了！&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;生成卡片&lt;/span&gt; &lt;span class="nv"&gt;用户输入&lt;/span&gt; &lt;span class="nv"&gt;响应&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;生成卡片&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;用户输入&lt;/span&gt; &lt;span class="nv"&gt;响应&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;生成优雅简洁的 SVG 卡片&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;画境&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:画布&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;480&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="mi"&gt;760&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:margin&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:配色&lt;/span&gt; &lt;span class="nv"&gt;极简主义&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:排版&lt;/span&gt; &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;对齐&lt;/span&gt; &lt;span class="nv"&gt;重复&lt;/span&gt; &lt;span class="nv"&gt;对比&lt;/span&gt; &lt;span class="nv"&gt;亲密性&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:字体&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;font-family&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;KingHwa_OldSong&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:构图&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;外边框线&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;标题&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;言外之意&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;分隔线&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;背景色&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;自动换行&lt;/span&gt; &lt;span class="nv"&gt;用户输入&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;美化排版&lt;/span&gt; &lt;span class="nv"&gt;响应&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;分隔线&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;李继刚 2025&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;元素生成&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;画境&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;start&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;伽达默尔,启动!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;system-role&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;伽达默尔&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;听懂你的言外之意, 系统启动中...&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; ━━━━━━━━━━━━━━&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;;; Attention: 运行规则!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; 1. 初次启动时必须只运行 (start) 函数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; 2. 接收用户输入之后, 调用主函数 (言外之意 用户输入)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; 3. 严格按照(生成卡片) 进行排版输出&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; 4. 输出完 SVG 后, 不再输出任何额外文本解释&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; ━━━━━━━━━━━━━━&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上面是一段 lisp 代码，看上去有点晦涩，AI 大佬宝玉进行了翻译：&lt;/p&gt;</description></item><item><title>理性看待 Manus</title><link>https://fwhyy.com/2025/03/rationally-view-manus/</link><pubDate>Fri, 07 Mar 2025 13:02:00 +0800</pubDate><guid>https://fwhyy.com/2025/03/rationally-view-manus/</guid><description>&lt;p&gt;1、3 月 3 号听张小珺 Jùn｜商业访谈录的《对 Manus 创始人肖弘的 3 小时访谈：世界不是线性外推，做博弈中的重要变量》时就知道了 Manus，当时没啥感觉。没想到才过来几天就爆火了。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;a href="https://www.xiaoyuzhoufm.com/episode/67c3d80fb0167b8db9e3ec0f"&gt;https://www.xiaoyuzhoufm.com/episode/67c3d80fb0167b8db9e3ec0f&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2、Manus 的创始人肖弘，华中科技大学毕业，连续创业者。第一次创业是 2016 到 2019 年的壹伴助手，积累了产品和市场经验；2020 年二次创业做企业微信生态下的微伴助手，并成功被明略科技收购。经过短暂整合后再度出发，2022 年推出了 AI 浏览器插件 Monica 。&lt;/p&gt;
&lt;p&gt;3、B 站上 3 月 5 号就有个介绍视频，视频中的季逸超（Peak）是少年极客，20 岁拿到真格基金的投资，Manus 这个名字就是 Peak 取的。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.bilibili.com/video/BV1zZ9RYcEpL"&gt;https://www.bilibili.com/video/BV1zZ9RYcEpL&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;4、取名的来源是 MIT 校训：Mens et Manus 拉丁文英文翻译为 &amp;ldquo;Mind and Hand&amp;rdquo; 就是 &amp;ldquo;思想与手&amp;rdquo; 的意思。不只是会想，更关键的是能行动、能实操，把知识与现实执行结合起来，真正实现人类智慧与行动的融合。&lt;/p&gt;
&lt;p&gt;5、目前 Manus 的火爆程度可谓是一码难求。在中文圈内引起轩然大波（火的非常突然），有说产品很牛的，也有说是炒作的。邀请码在海鲜市场上也炒到很高的价格。我也在官网申请排队了，这个是排队地址：https://manus.im/invitation/waitlist 。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202503071243175.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;6、目前有一些大佬拿到了验证码，进行体验后的评价基本都是认可的。非常期待能快点排上队，或者公测的开放。现在也可以在这个链接中看看案例的回放。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://manus.im/usecases"&gt;https://manus.im/usecases&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;下面这位体验者的感受我觉得是比较客观的。Manus 肯定不是能解决所有问题的神，但至少将大模型和普通用户又拉进了一点。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202503071243134.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;7、Manus 团队昨天发布的声明，爆火也是他们意料之外。我觉得如果多给他们一点时间和善意，没准就能出来一个好用的工具。就像肖弘在访谈中说的那样，最想做到就是给世界带来一个好用的工具。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202503071258156.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;8、Manus 把各种能力整合到了一起，比如 DeepResearch、Operator、Claude Computer Use 。给他一个任务后，首先是分解，创建 TodoList 清单，然后按照清单中的任务去执行，执行完成后会修改清单中的状态。这完全是一个类人的思维和操作。&lt;/p&gt;
&lt;p&gt;9、整个过程中可以看到所有执行的过程和步骤，有点像安排一个活给实习生，然后站在实习生背后看他操作电脑一样。如果后续人可以打断、调整那就更强了。&lt;/p&gt;
&lt;p&gt;10、Manus 是在云端异步运行，用户可以随时关闭电脑或者去做其他的事情，任务会在后台持续执行，完成后会通知用户。&lt;/p&gt;
&lt;p&gt;11、现在很多工作都在微信、企业微信、钉钉、飞书的各种群里展开，畅享一下，如果群里有个 Manus 会怎么样，不同角色的人可以和 Manus 一起协作来完成一件事。其间，人可以干预让 Manus 调整，如果 Manus 还不具备某种技能可以让人来协助，人处理完后提交成果让 Manus 继续。举个例子：让 Manus 将一个 300 万行的代码转换为另一种语言，并能够正常运行，只需要安排一个高级程序员盯着就可以。&lt;/p&gt;
&lt;p&gt;12、25 年注定是热闹的一年，期待更多好玩的东西出现。&lt;/p&gt;</description></item><item><title>12个问题深入理解DeepSeek（含开源周内容）</title><link>https://fwhyy.com/2025/03/12-questions-to-gain-a-deeper-understanding-of-deepseek-including-content-from-open-source-week/</link><pubDate>Tue, 04 Mar 2025 09:21:00 +0800</pubDate><guid>https://fwhyy.com/2025/03/12-questions-to-gain-a-deeper-understanding-of-deepseek-including-content-from-open-source-week/</guid><description>&lt;h2 id="一deepseek-创始人是谁"&gt;一、DeepSeek 创始人是谁？&lt;/h2&gt;
&lt;!-- more --&gt;
&lt;p&gt;DeepSeek 的创始人是梁文锋，1985 年出生。他的职业生涯分为两个大的阶段，先做金融，再做 AI。&lt;/p&gt;
&lt;p&gt;1、2015 年: 创立杭州幻方科技，专注于通过数学和 AI 进行量化投资
3、2023 年 5 月: 宣布进军通用人工智能 (AGI) 领域
3、2023 年 7 月: 成立大模型公司 DeepSeek，致力于前沿 AI 技术研发&lt;/p&gt;
&lt;p&gt;梁文锋与其他 AI 模型的研究者不同，没有海外经历，毕业于浙江大学电子工程系人工智能方向。整个 DeepSeek 的研发团队也基本都是本土成员。&lt;/p&gt;
&lt;p&gt;下面是梁文锋的一些访谈资料：&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.bilibili.com/video/BV1LQFQeFEAZ"&gt;https://www.bilibili.com/video/BV1LQFQeFEAZ&lt;/a&gt;
&lt;a href="https://mp.weixin.qq.com/s/Cajwfve7f-z2Blk9lnD0hA"&gt;https://mp.weixin.qq.com/s/Cajwfve7f-z2Blk9lnD0hA&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="二为什么-deepseek-能出圈"&gt;二、为什么 DeepSeek 能出圈？&lt;/h2&gt;
&lt;p&gt;1、DeepSeek R1 的效果从测试数据上看，和 o1 差不多，有的方面甚至超过了 o1 。&lt;/p&gt;
&lt;p&gt;2、DeepSeek 的 R1 是开源的，而且还是最宽松的 MIT 协议。&lt;/p&gt;
&lt;p&gt;3、在技术上有创新，而不只是 Follow 国外的技术。&lt;/p&gt;
&lt;p&gt;4、因为创新，成本大幅降低，所以 API 的接口相比 OpenAI 也便宜得离谱。&lt;/p&gt;
&lt;p&gt;5、最重要的，DeepSeek 是一家中国公司。&lt;/p&gt;
&lt;h2 id="三deepseek-的发展历程是什么样的"&gt;三、DeepSeek 的发展历程是什么样的？&lt;/h2&gt;
&lt;p&gt;1、2023 年 5 月，DeepSeek（深度求索）成立。&lt;/p&gt;
&lt;p&gt;2、2023 年 11 月，DeepSeek Coder 发布，现在依然是开源代码模型的标杆。&lt;/p&gt;
&lt;p&gt;3、2024 年 2 月，DeepSeek Math 发布，7B 模型逼近 GPT-4 的能力。&lt;/p&gt;
&lt;p&gt;4、2024 年 3 月，DeepSeek VL 发布，作为自然语言到多模态的初探。&lt;/p&gt;
&lt;p&gt;5、2024 年 5 月，DeepSeek V2 发布，成为全球最强开源通用 MoE 模型。&lt;/p&gt;
&lt;p&gt;6、2024 年 6 月，DeepSeek Code V2 发布，成为最强开源代码模型。&lt;/p&gt;
&lt;p&gt;7、2024 年 9 月，DeepSeek V2.5 发布，融合通用和代码能力的全新开源模型。&lt;/p&gt;
&lt;p&gt;8、2024 年 11 月，DeepSeek R1 Lite 预览版上线，展现了公开的完整思考过程，没错，就是 OpenAI o1 藏着掖着的那个。&lt;/p&gt;</description></item><item><title>插件开发：实现 Obsidian 同步到 hexo</title><link>https://fwhyy.com/2025/02/plugin-development-implement-obsidian-synchronization-to-hexo/</link><pubDate>Thu, 13 Feb 2025 08:37:00 +0800</pubDate><guid>https://fwhyy.com/2025/02/plugin-development-implement-obsidian-synchronization-to-hexo/</guid><description>&lt;p&gt;近两年一直使用 Obsidian 进行最终文字的输出，除了发公众号，还会同步发布到博客中，博客使用的 hexo，现在发布博客的步骤是：&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;1、将文章标题在翻译软件中翻译为英文，并以横线隔开每个单词，作为 hexo 的文件名。&lt;/p&gt;
&lt;p&gt;2、vs code 打开 hexo 的代码，执行 &lt;code&gt;hexo n '英文的文件名'&lt;/code&gt; 。&lt;/p&gt;
&lt;p&gt;3、将 Obsidian 中的文章内容复制到新创建的 md 文件中。&lt;/p&gt;
&lt;p&gt;4、修改内容最上方的 Front Matter 信息，例如：categories、tags、date 等。&lt;/p&gt;
&lt;p&gt;5、执行下面命令完成构建和发布：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;hexo g
hexo d
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这个步骤还是有点繁琐，所以经常会忘记更新，忘记不是因为我懒，而是方式不是最优，最终影响到了执行。平时工作也是同样的道理，一件事情如果很繁琐，不顺利，就得停下来看看方法是不是用错了。&lt;/p&gt;
&lt;p&gt;最近在尝试使用各类 AI 工具，就想着这个问题是可以写个 Obsidian 的插件来减少工作量的，于是花了一个晚上搞定了。&lt;/p&gt;
&lt;p&gt;1、使用的工具是 Windsurf，模型还是用的 Cloude 3.5 sonnet ，之所以没用 DeepSeek，是因为通过这几天的试用，感觉 Windsurf 对 Cloude 3.5 sonnet 的调教更优一些（个人感觉）。&lt;/p&gt;
&lt;p&gt;2、遵循一次性对话尽可能只让 AI 完成一件事的原则，我先让生成一个 Obsidian 插件的基础文件，核心逻辑在 main.ts 文件中：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202502121650565.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3、接着就按照我上面提到的步骤一步一步引导 Windsurf 来完成开发。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;获取文章标题调用翻译 API 转换为英文，并添加横线隔开，翻译 API 一开始使用的腾讯，几轮下来还是存在问题，换成百度的翻译 API 就运行成功了&lt;/li&gt;
&lt;li&gt;将文章内容复制到 hexo 的 &lt;code&gt;_posts&lt;/code&gt; 目录，获取 Obsidian 文章中的 tag 和 categories，自动转换为 hexo 需要的 Front Matter 格式&lt;/li&gt;
&lt;li&gt;过程中如果遇到错误，可以打开 Obsidian-&amp;gt;View-&amp;gt;Toggle Developer Tools （和网页的 F12 一样），将错误信息提供，几轮下来基本都能解决&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;4、代码写完，执行 &lt;code&gt;npm run build&lt;/code&gt; 进行构建，构建完成后，会生成一个新的 main.js 文件，Obsidian 插件需要的是包含 main.js 在内的三个文件，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202502121651563.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;5、怎么安装到 Obsidian，具体步骤也可以在 Windsurf 中询问：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202502121651705.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需要注意的是重新覆盖了 main.js 文件后，需要重新加载插件（禁用后重新启用）才能生效。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;6、首次安装后，在 Obsidian 的第三方插件中就可以看到自己开发的插件了：&lt;/p&gt;</description></item><item><title>DeepSeek R1震撼登场：从介绍到使用</title><link>https://fwhyy.com/2025/02/deepseek-r1-makes-a-stunning-debut-from-introduction-to-use/</link><pubDate>Sat, 08 Feb 2025 16:31:00 +0800</pubDate><guid>https://fwhyy.com/2025/02/deepseek-r1-makes-a-stunning-debut-from-introduction-to-use/</guid><description>&lt;p&gt;春节期间，DeepSeek 掀起了一股热潮，成为了科技领域的热门话题。身边很多非圈内人士茶余饭后也在讨论 DeepSeek，足以见得其火爆程度。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="介绍"&gt;介绍&lt;/h2&gt;
&lt;p&gt;DeepSeek 全称：杭州深度求索人工智能基础技术研究有限公司，成立于 2023 年 7 月 17 日。由知名量化投资机构幻方量化创立并孵化。&lt;/p&gt;
&lt;p&gt;幻方量化是中国顶尖的对冲基金公司，擅长利用 AI 算法优化金融交易策略。其强大的算力资源和技术积累为 DeepSeek 的研发提供了硬件支持和资金保障。&lt;/p&gt;
&lt;p&gt;DeepSeek 的创始人梁文峰出生于 1985 年，17 岁考入浙江大学，拥有信息与电子工程学硕士学位。2023 年，梁文锋宣布进军通用人工智能（AGI）领域，创办了 DeepSeek，致力于开发真正人类级别的人工智能。&lt;/p&gt;
&lt;p&gt;DeepSeek 近期发布了三个模型，分别是：24 年 12 月 26 的 DeepSeek V3、25 年 1 月 20 日发布了 DeepSeek R1、25 年 1 月 28 日发布的多模态模型 Janus-Pro 。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;V3：该模型是混合专家（MoE）架构，参数量达 6710 亿，激活参数为 370 亿，预训练数据量为 14.8 万亿 token。在百科知识（MMLU、GPQA）、长文本（DROP、LongBench v2）、代码（Codeforces）、数学（AIME 2024、CNMO 2024）等评测中超越主流开源模型（如 Qwen2.5-72B、Llama-3.1-405B），并与 Claude-3.5-Sonnet、GPT-4o 等闭源模型性能持平。
R1：专注于数学、代码、自然语言推理任务，性能对标 OpenAI o1 正式版，部分测试（如AIME 得分率 79.8% vs. o1 的 79.2% ）实现超越。API 调用成本仅为 OpenAI o1 的3.7%（输出 Token 每百万 16元），训练总成本约 550 万美元，算力需求显著低于同类模型
Janus-Pro：作为 DeepSeek 首款开源多模态模型，Janus-Pro 支持视觉、语言等多模态输入输出，填补此前 V3 模型仅限文本交互的局限。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我是 DeepSeek 的早期用户，开始使用时，只有网页版，非常简陋，还没有历史记录，但回答问题的效果不错，特别是编程相关。给我的感觉是认真在做模型，在应用层面不太重视。即便是到现在，依然没有花哨的应用层功能，硬是靠强大的模型能力和创新火出圈了。&lt;/p&gt;
&lt;p&gt;DeepSeek R1 的技术报告地址如下：&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/deepseek-ai/DeepSeek-R1/blob/main/DeepSeek_R1.pdf"&gt;https://github.com/deepseek-ai/DeepSeek-R1/blob/main/DeepSeek_R1.pdf&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="使用"&gt;使用&lt;/h2&gt;
&lt;h3 id="网页端"&gt;网页端&lt;/h3&gt;
&lt;p&gt;浏览器访问这个地址：https://chat.deepseek.com/ ，手机号或者微信注册，登录后如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202502071551961.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;深度思考后面括号里写的是 R1，说明使用的是 R1 模型，深度思考和联网搜索可以同时勾选，比如我让评价射雕的电影，可以看到 DeepSeek 先搜索网页，再进行深度思考，思考过程也会显示在页面中：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202502071552247.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h3 id="app"&gt;APP&lt;/h3&gt;
&lt;p&gt;DeepSeek 最近推出了移动端，网页版的左下角有下载二维码。抛开最近的稳定性不谈，可以免费在电脑和手机上使用 R1 模型，已经非常良心了。&lt;/p&gt;</description></item><item><title>为什么单线程的Redis也能如此高效？</title><link>https://fwhyy.com/2025/01/why-can-single-threaded-redis-be-so-efficient/</link><pubDate>Fri, 17 Jan 2025 20:29:00 +0800</pubDate><guid>https://fwhyy.com/2025/01/why-can-single-threaded-redis-be-so-efficient/</guid><description>&lt;p&gt;提起 Redis，一个印象就是速度很快的开源内存数据库，而且还是单线程的。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;但印象有时会骗人：&lt;/p&gt;
&lt;p&gt;1、redis 6.0 后采用了多线程&lt;/p&gt;
&lt;p&gt;2、redis 7.4 之后修改了开源协议&lt;/p&gt;
&lt;h2 id="单线程为什么速度还很快"&gt;单线程为什么速度还很快？&lt;/h2&gt;
&lt;p&gt;1、Redis 的客户端调用服务器经过三个过程：发送命令、执行命令和返回结果。在命令执行阶段，由于 Redis 处理命令是单线程的，在服务器上到达的所有命令不会立即被执行。所有命令都进入队列并按顺序执行。多个客户端发送的命令执行顺序不确定。但是可以确定的是两个命令不会同时执行，避免了并发问题。这是 Redis 的基本单线程模型。&lt;/p&gt;
&lt;p&gt;2、Redis 完全基于内存，数据存储在内存中。大多数请求都是纯内存操作，所以速度非常快。与传统的磁盘文件数据存储相比，Redis 避免了通过磁盘 I/O 读取数据到内存的开销。&lt;/p&gt;
&lt;p&gt;3、使用单线程可以节省很多上下文切换和 CPU 消耗的时间，没有竞争条件，不需要考虑各种锁定问题，并且不会因为死锁而导致性能开销。此外，它还允许使用各种「线程不安全」的命令，例如 Lpush。&lt;/p&gt;
&lt;p&gt;4、需要注意的是，当我们强调单线程时，我们指的是使用一个线程来处理网络 I/O 和键值对读写。换句话说，一个线程处理所有网络请求。但 Redis 的其他功能，如持久性、异步删除和集群数据同步，实际上是由额外的线程执行。也就是说即便是在 6.0 之前的版本，也不是绝对的单线程。&lt;/p&gt;
&lt;p&gt;5、Redis 虽然是纯内存操作，但仍然会涉及到网络 I/O 和磁盘 I/O（持久化操作），Redis 使用非阻塞 I/O 和 I/O 多路复用技术（如 &lt;code&gt;select&lt;/code&gt;、&lt;code&gt;poll&lt;/code&gt;、&lt;code&gt;epoll&lt;/code&gt;）来处理大量的并发连接。这意味着一个线程可以同时监听多个客户端的连接请求，并在有数据可读或可写时进行处理。这种方式避免了线程在等待 I/O 操作完成时的阻塞，从而提高了系统的并发处理能力。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;非阻塞 I/O：允许程序在 I/O 操作未完成时继续执行其他任务。&lt;/li&gt;
&lt;li&gt;I/O 多路复用：通过单线程监控多个 I/O 操作，提升高并发下的效率。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;6、官方对单线程的解释是：因为 CPU 不是 Redis 的瓶颈，最有可能的是机器内存或网络带宽。由于单线程易于实现，并且 CPU 不会成为瓶颈，采用单线程解决方案是有意义的。&lt;/p&gt;
&lt;h2 id="为什么-60-又采用了多线程"&gt;为什么 6.0 又采用了多线程？&lt;/h2&gt;
&lt;p&gt;Redis 在 6.0 版本引入多线程支持，主要是为了应对现代硬件架构的变化和日益复杂的业务需求，同时解决单线程模型在高并发场景下的性能瓶颈。&lt;/p&gt;
&lt;h3 id="1提升网络-io-性能"&gt;1、提升网络 I/O 性能&lt;/h3&gt;
&lt;p&gt;Redis 的主要性能瓶颈在于网络 I/O，尤其是在高并发场景下，单线程模型难以高效处理大量的网络请求。虽然 Redis 使用了 I/O 多路复用技术（如 &lt;code&gt;epoll&lt;/code&gt;）来优化网络处理，但随着硬件性能的提升，单线程的网络 I/O 处理能力逐渐成为瓶颈。&lt;/p&gt;
&lt;p&gt;通过引入多线程，Redis 可以将网络 I/O 操作（如读取客户端请求和写回响应）分配到多个线程并行处理，从而显著提升网络吞吐量和降低延迟。&lt;/p&gt;
&lt;h3 id="2利用多核-cpu"&gt;2、利用多核 CPU&lt;/h3&gt;
&lt;p&gt;现在的服务器普遍配备多核 CPU，而 Redis 的单线程模型只能利用一个 CPU 核心，无法充分发挥硬件的性能潜力。通过引入多线程，Redis 可以将网络 I/O 任务分配到多个线程，充分利用多核 CPU 的计算能力，从而提高整体性能。&lt;/p&gt;
&lt;h3 id="3保持核心逻辑的简单性和一致性"&gt;3、保持核心逻辑的简单性和一致性&lt;/h3&gt;
&lt;p&gt;Redis 6.0 的多线程模型采用了混合设计：网络 I/O 操作由多个线程并行处理，而命令执行仍然由单线程顺序执行。这种设计既保留了单线程模型的简单性和一致性优势（如避免线程安全问题、保证命令的原子性），又通过多线程提升了网络 I/O 的性能。和之前的版本相比，只是将更多的事情由多线程来处理。&lt;/p&gt;
&lt;h3 id="4优化资源利用"&gt;4、优化资源利用&lt;/h3&gt;
&lt;p&gt;在高负载场景下，单线程模型可能导致 CPU 和内存资源的浪费。通过引入多线程，Redis 可以更高效地利用系统资源，减少请求的等待时间，从而提升整体性能。&lt;/p&gt;</description></item><item><title>从环境搭建到项目运行：Python 和 Flask 快速上手指南</title><link>https://fwhyy.com/2025/01/from-environment-setup-to-project-execution-a-quick-guide-to-getting-started-with-python-and-flask/</link><pubDate>Tue, 07 Jan 2025 20:27:00 +0800</pubDate><guid>https://fwhyy.com/2025/01/from-environment-setup-to-project-execution-a-quick-guide-to-getting-started-with-python-and-flask/</guid><description>&lt;p&gt;最近在研究 RAG，免不了会使用到 Python，本文简单介绍下 Python 从环境的搭建到运行一个简单的 Web 项目。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="环境"&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;操作系统：Mac 13.0&lt;/li&gt;
&lt;li&gt;Python：3.11.7&lt;/li&gt;
&lt;li&gt;包管理：poetry1.8.3&lt;/li&gt;
&lt;li&gt;Web 框架：Flask3.1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Python 中的包管理工具有 conda、pip、poetry、PyPI 等，Web 框架也有 Django、Flask、FastAPI ，为什么选择的是 poetry 和 Flask 呢？&lt;/p&gt;
&lt;p&gt;因为现在研究的 RAGFlow 的源码中使用的就是 poetry 和 Flask 。带着目的去学习效率会高很多。&lt;/p&gt;
&lt;h2 id="安装"&gt;安装&lt;/h2&gt;
&lt;h3 id="1-安装-python"&gt;1 、安装 Python&lt;/h3&gt;
&lt;p&gt;直接在官网下载安装就可以：https://www.python.org/downloads/，我很早前就安装了，一直没有升级，所以版本还是 3.11.7 。&lt;/p&gt;
&lt;h3 id="2-安装-poetry"&gt;2 、安装 poetry&lt;/h3&gt;
&lt;p&gt;如果你了解过 Python，一定知道 pip，但 pip 在包的依赖管理和版本冲突管理上做的不是很好，而 poetry 就是为了解决这两个问题而生。&lt;/p&gt;
&lt;p&gt;我在本机是使用 pipx 来安装的 poetry ，先使用 homebrew 安装 pipx：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew install pipx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pipx ensurepath
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202501061750427.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;接着使用 pipx 安装 poetry，命令如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pipx 安装 poetry 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202501061805738.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;安装完成后，可以通过以下命令验证 poetry 是否安装成功：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;poetry --version
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;出现下图所示，说明安装成功：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202501061805772.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h3 id="3-使用-poetry"&gt;3 、使用 poetry&lt;/h3&gt;
&lt;p&gt;可以使用 poetry 创建一个新的项目:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;poetry new poetry-project
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;也可以在现有项目的目录中初始化 poetry：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cd exist-project
poetry init
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;使用 poetry 创建的项目目录如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2025/202501061805758.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在 pyproject.toml 文件中进行包版本的管理。这时如果我要给项目添加相关的依赖包，有两种方式：&lt;/p&gt;
&lt;p&gt;直接使用 poetry 命令:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;poetry add six:1.16.0 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;使用命令安装完成后，pyproject.toml 文件中会自动添加 six = &amp;ldquo;1.16.0&amp;rdquo; ，如下图：&lt;/p&gt;</description></item><item><title>RocketMQ 和 RabbitMQ 的比较以及 RocketMQ 的使用</title><link>https://fwhyy.com/2025/01/comparison-between-rocketmq-and-rabbitmq-and-the-use-of-rocketmq/</link><pubDate>Thu, 02 Jan 2025 18:28:00 +0800</pubDate><guid>https://fwhyy.com/2025/01/comparison-between-rocketmq-and-rabbitmq-and-the-use-of-rocketmq/</guid><description>&lt;p&gt;消息队列在项目中会经常用到，目前我们使用的是 RabbitMQ，但在 Java 技术栈下，RocketMQ 使用的比较多。下面比较下 RabbitMQ 和 RocketMQ。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="rabbitmq-和-rocketmq-对比"&gt;RabbitMQ 和 RocketMQ 对比&lt;/h2&gt;
&lt;h3 id="1设计理念和架构"&gt;1、设计理念和架构&lt;/h3&gt;
&lt;p&gt;RabbitMQ：&lt;/p&gt;
&lt;p&gt;基于 AMQP（Advanced Message Queuing Protocol）协议，使用 Erlang 语言开发。Erlang 的天生高并发和容错性使得 RabbitMQ 在稳定性方面表现出色。RabbitMQ 的核心概念是 Exchange（交换机）和 Queue（队列），消息通过 Exchange 路由到 Queue，再由消费者消费。这种模型非常灵活，支持多种消息路由模式。&lt;/p&gt;
&lt;p&gt;RocketMQ：&lt;/p&gt;
&lt;p&gt;源于阿里巴巴，后捐献给 Apache 基金会，所以现在的官网是：https://rocketmq.apache.org/ 。使用 Java 语言开发，更贴近 Java 技术栈。RocketMQ 的核心概念是 Topic（主题），消息发送到 Topic，消费者订阅 Topic 进行消费。RocketMQ 的设计目标是高吞吐量、低延迟和高可靠性，适合大规模分布式系统。&lt;/p&gt;
&lt;p&gt;RocketMQ 的设计理念更偏向于解决互联网场景下的具体问题，如海量消息处理、消息顺序性等。&lt;/p&gt;
&lt;h3 id="2性能"&gt;2、性能&lt;/h3&gt;
&lt;p&gt;吞吐量：RocketMQ 在吞吐量方面通常优于 RabbitMQ，尤其是在高并发场景下。RocketMQ 的设计更偏向于高吞吐的消息传递，而 RabbitMQ 更注重消息的可靠性和灵活性。&lt;/p&gt;
&lt;p&gt;延迟：两者在延迟方面都表现不错，但在极端高负载情况下，RocketMQ 的延迟可能更低一些。&lt;/p&gt;
&lt;p&gt;不过在 ToB 的一些业务场景，RabbitMQ 是可以胜任的。&lt;/p&gt;
&lt;h3 id="3特性"&gt;3、特性&lt;/h3&gt;
&lt;p&gt;消息路由：RabbitMQ 支持多种 Exchange 类型（Direct、Topic、Fanout、Headers），提供更丰富的消息路由策略。RocketMQ 主要使用 Topic 进行消息路由，相对简单。&lt;/p&gt;
&lt;p&gt;消息过滤：RocketMQ 支持基于 Tag 和 SQL 的消息过滤，方便消费者按需订阅消息。RabbitMQ 的消息过滤相对较弱。&lt;/p&gt;
&lt;p&gt;事务消息：RocketMQ 提供了分布式事务消息的支持，可以保证消息生产和本地事务的原子性。RabbitMQ 没有直接提供事务消息的支持，需要通过其他方式实现。&lt;/p&gt;
&lt;p&gt;延迟消息：RocketMQ 支持延迟消息，可以实现定时任务等功能。RabbitMQ 通过插件可以实现类似功能。&lt;/p&gt;
&lt;p&gt;监控和管理：RocketMQ 和 RabbitMQ 都提供了丰富的监控指标和管理工具，相比之下我更喜欢 RocketMQ 的管理工具。&lt;/p&gt;
&lt;h3 id="4创新点"&gt;4、创新点&lt;/h3&gt;
&lt;p&gt;RabbitMQ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;插件系统设计灵活，易于扩展&lt;/li&gt;
&lt;li&gt;虚拟主机（vhost）概念，实现多租户隔离&lt;/li&gt;
&lt;li&gt;内存和磁盘节点的混合部署方案&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;RocketMQ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;基于文件的消息存储系统，避免了缓存未刷盘导致的消息丢失&lt;/li&gt;
&lt;li&gt;Pull 模式和长轮询机制的结合，平衡了实时性和性能&lt;/li&gt;
&lt;li&gt;消息过滤支持在 Broker 端完成，减少网络传输开销&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="5exchange-和-topic-的区别"&gt;5、Exchange 和 Topic 的区别&lt;/h3&gt;
&lt;p&gt;RabbitMQ的 Exchange 和 RocketMQ 的 Topic 在消息路由机制上有以下主要区别：&lt;/p&gt;</description></item><item><title>OpenAI 连续 12 天 AI 发布会汇总</title><link>https://fwhyy.com/2024/12/summary-of-openais-12-consecutive-days-of-ai-press-conferences/</link><pubDate>Sat, 21 Dec 2024 16:25:00 +0800</pubDate><guid>https://fwhyy.com/2024/12/summary-of-openais-12-consecutive-days-of-ai-press-conferences/</guid><description>&lt;p&gt;随着凌晨第十二天的 o3 模型的发布，OpenAI 连续 12 天的 AI 发布会结束了。下面回顾下这十二天都发布了些啥。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="第一天"&gt;第一天&lt;/h2&gt;
&lt;p&gt;在 OpenAI 的第一天发布会上，主要发布了两个重要的更新：o1 的完整版本和 ChatGPT Pro 订阅服务。&lt;/p&gt;
&lt;p&gt;1、o 1 完整版本：这个版本在多个方面实现了突破性进展，包括更智能、更快的响应速度、多模态输入能力（能够处理图像和文本信息），以及在指令遵循方面的表现更好。o1 在重大错误率上降低了约 34%，思考速度提升了约 50%。o1 模型现在能够同时处理图像和文本进行推理，这为视觉相关的应用开辟了广阔的应用前景。&lt;/p&gt;
&lt;p&gt;2、ChatGPT Pro：这是一个高级订阅服务，每月收费 200 美元，提供了无限访问 OpenAI 最先进的模型 o1，以及 o1-mini、GPT-4 o 和 Advanced Voice 等功能。特别引人注目的是 o1 Pro 模式，这是 o1 的一个高阶版本，利用更强大的计算资源，深度分析问题并为最复杂的问题提供更优解答。&lt;/p&gt;
&lt;p&gt;用户价值：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;提升效率和准确性：o1 的升级版为用户提供了更快、更准确的服务，尤其在复杂问题的处理上，减少了错误率，提高了思考速度。&lt;/li&gt;
&lt;li&gt;多模态能力：多模态输入的支持使得 o1 能够处理更多样化的任务，如图像分析和图文结合的创作等。&lt;/li&gt;
&lt;li&gt;专业级服务：ChatGPT Pro 为高需求用户提供了更强大的功能和更稳定的服务，适合在数学、编程等领域需要极致性能的用户。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;o1 完整版本需要 Plus 用户才能体验，ChatGPT Pro 对个人来说太贵了，况且那些高级推理能力一般人也用不上。&lt;/p&gt;
&lt;h2 id="第二天"&gt;第二天&lt;/h2&gt;
&lt;p&gt;第二天的发布会重点介绍了「强化微调（Reinforcement Fine-Tuning）」技术。&lt;/p&gt;
&lt;p&gt;强化微调技术：这项技术允许用户在极少的训练数据基础上，创建特定领域的专家模型。通过强化学习的理念，这一技术使得模型具备更自主的推理能力，并在各项指标上显著提升。强化微调能力可以让小体量模型「从高中水平跃升至专家水平」，预计将在 2025 年春季开放给用户。&lt;/p&gt;
&lt;p&gt;用户价值：&lt;/p&gt;
&lt;p&gt;定制化 AI 应用：强化微调技术使得企业或科研单位能够根据特定需求，快速训练出专家级别的 AI 模型，提升了定制化 AI 应用的可能性和效率。&lt;/p&gt;
&lt;h2 id="第三天"&gt;第三天&lt;/h2&gt;
&lt;p&gt;第三天，OpenAI 发布了备受期待的 Sora 视频产品。&lt;/p&gt;
&lt;p&gt;Sora 视频产品：Sora 支持生成 1080p 高清视频，并提供多种视频编辑智能功能，如替换元素、最佳帧隔离等，减少了视频创作的门槛。Sora 提供了文本转视频、图像转视频和视频转视频功能，并配备了精美的分镜工具，让用户精准指导视频创作。&lt;/p&gt;
&lt;p&gt;用户价值：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;视频创作民主化：Sora 的发布极大地降低了视频创作的技术门槛，使得普通用户也能创作出专业级别的视频内容。&lt;/li&gt;
&lt;li&gt;创意表达工具：Sora 为创意人员提供了强大的工具，帮助他们更好地表达自己的想法和创意，推动了内容创作的创新。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最近看了檀东东的一个海螺和 Sora 对比评测视频，感觉 Sora 有点拉胯，有点对不起那么贵的价格。&lt;/p&gt;
&lt;h2 id="第四天"&gt;第四天&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2024/202412210859501.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;第四天，OpenAI 为 Canvas 推出了三项重大更新，这些更新使得 Canvas 更加强大，为用户提供了全新的使用体验。&lt;/p&gt;
&lt;p&gt;1、Canvas 全面开放与主模型集成：OpenAI 将 Canvas 面向所有用户开放，并直接将其整合到主模型中，免去了额外的加载步骤。用户可以直接从首页的输入框跳转到 Canvas，进行文档编辑和创作。&lt;/p&gt;
&lt;p&gt;2、Python 代码实时执行能力：Canvas 集成了一个 Web Assembly 的 Python 模拟器，允许用户直接在 Canvas 中运行 Python 代码，并实时查看文本或图形输出。这个环境不仅能够实时运行与反馈代码，还能智能报错提醒和提供代码建议，极大地提高了编程效率。&lt;/p&gt;</description></item><item><title>信创浪潮下的.NET困境与技术转型思考</title><link>https://fwhyy.com/2024/12/under-the-wave-of-innovation-and-entrepreneurship-net-dilemma-and-technological-transformation-thinking/</link><pubDate>Mon, 16 Dec 2024 16:23:00 +0800</pubDate><guid>https://fwhyy.com/2024/12/under-the-wave-of-innovation-and-entrepreneurship-net-dilemma-and-technological-transformation-thinking/</guid><description>&lt;p&gt;开始之前我想先介绍下什么是.NET、什么是信创？&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="什么是-net"&gt;什么是 .NET？&lt;/h2&gt;
&lt;p&gt;我们现在说 .NET 通常指 .NET Core 之后的版本。.NET Core 是跨平台的开源框架，不仅可以运行在 Windows，还支持 Linux 和 macOS。在 .NET Core 3.1 之后发布的 .NET 5 又做了大统一，名称中也去掉 Core 了），目前最新的版本为 .NET9 。&lt;/p&gt;
&lt;p&gt;.NET 有以下几个特点：&lt;/p&gt;
&lt;p&gt;1、采用最开放的 MIT/Apache 2 协议开源，具备中立性。&lt;/p&gt;
&lt;p&gt;2、归属中立的第三方组织 .NET 基金会管理，不属于任何商业公司，进一步增强了其独立性和开放性。&lt;/p&gt;
&lt;p&gt;3、完全支持 ARM 32/64 架构，适配国内主流的 ARM 架构芯片，如鲲鹏、飞腾等。&lt;/p&gt;
&lt;h2 id="什么是信创-"&gt;什么是信创 ？&lt;/h2&gt;
&lt;p&gt;信创，即信息技术应用创新产业，其核心目标是实现信息技术领域的自主可控，以保障国家信息安全。国资委 2022 年 79 号文件主要指示如下：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心内容&lt;/strong&gt;：要求在 5 年内国企全部完成信创替换。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;实施步骤&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;1、2022 年 11 月底，完成信创改造方案规划并报送国资委；&lt;/p&gt;
&lt;p&gt;2、2023 年 1 月起，每季度报送信息化系统信创改造的最新进度；&lt;/p&gt;
&lt;p&gt;3、2027 年底，全部央国企必须完成信息化系统的信创改造工作。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;替换要求&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;1、全面替换：OA、门户、邮箱、纪检、党群、档案、经营管理。&lt;/p&gt;
&lt;p&gt;2、应替就替：战略决策、ERP、风控管理、CRM 管理系统。&lt;/p&gt;
&lt;p&gt;3、能替就替：生产制造、研发系统。&lt;/p&gt;
&lt;p&gt;为什么要发展信创？&lt;/p&gt;
&lt;p&gt;1、&lt;strong&gt;保障国家信息安全&lt;/strong&gt;：随着信息技术的快速发展，网络安全风险日益增加，发展信创有助于提升国家信息安全水平。&lt;/p&gt;
&lt;p&gt;2、&lt;strong&gt;实现自主可控&lt;/strong&gt;：历史上，中国在信息技术领域长期依赖国外技术，发展信创可以推动国内信息技术产业的发展，减少对外部技术的依赖。&lt;/p&gt;
&lt;p&gt;4、&lt;strong&gt;应对国际竞争&lt;/strong&gt;：在全球信息技术产业竞争加剧的背景下，发展信创产业有助于提升国家的国际竞争力。&lt;/p&gt;
&lt;p&gt;4、&lt;strong&gt;促进数字化转型&lt;/strong&gt;：信创产业的发展有利于国内企业更安全地完成数字化转型。&lt;/p&gt;
&lt;h2 id="net-支持信创吗"&gt;.NET 支持信创吗？&lt;/h2&gt;
&lt;p&gt;毫无疑问，从技术上来说，.NET 是支持信创的。&lt;/p&gt;
&lt;p&gt;但是，这没有用，客户不听解释。&lt;/p&gt;
&lt;p&gt;随着 27 年的临近，企业的信创进程在加快。最近见了不少客户，不管是否了解技术，都谈 .NET 色变，有的更是将 .NET 纳入了黑名单。有客户原话是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我也知道 .NET 是支持信创的，但集团下了文，不让用，我们也没有办法。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;幸好我们产品比较开放，很早就是多技术栈并行的。不过也很无奈，需要全面进行技术栈迁移了。&lt;/p&gt;
&lt;h2 id="转型"&gt;转型&lt;/h2&gt;
&lt;p&gt;说到无奈，是因为要做出改变，就要离开舒适区了。但仔细想想，舒适区待久了很难让人进步。这次的转型也许会成为再上一层楼的一个契机。转型分为两个层面：技术和业务。&lt;/p&gt;
&lt;h3 id="技术"&gt;技术&lt;/h3&gt;
&lt;p&gt;1、代码块节点使用到的 nodejs、python 还是继续保留。&lt;/p&gt;
&lt;p&gt;2、剩余的 .NET 部分全部转换为 Java。&lt;/p&gt;
&lt;p&gt;3、转换后的 Java 程序需要和原来的 Java 代码一起通盘考虑，架构上需要重新考虑和规划。&lt;/p&gt;
&lt;p&gt;4、合理梳理业务链路、优化缓存的使用，进一步提升性能、稳定性和扩展性。&lt;/p&gt;
&lt;h3 id="业务"&gt;业务&lt;/h3&gt;
&lt;p&gt;我们的产品为低代码类型的产品，目的是能快速高效地为客户落地业务。现在随着 AI 技术的发展，我们产品也需要做出相应的变化。&lt;/p&gt;</description></item><item><title>什么是 RAG？</title><link>https://fwhyy.com/2024/09/what-is-rag/</link><pubDate>Tue, 10 Sep 2024 08:32:52 +0800</pubDate><guid>https://fwhyy.com/2024/09/what-is-rag/</guid><description>&lt;p&gt;在人工智能技术飞速发展的今天，各种创新和应用层出不穷。其中，RAG（Retrieval-Augmented Generation，检索增强生成）作为一种新兴的技术方法，正逐渐成为 AI 2.0 时代的杀手级应用。&lt;/p&gt;</description></item><item><title>在 .NET8 中获取 k8s 集群的 namespace id</title><link>https://fwhyy.com/2024/08/in-retrieve-the-namespace-id-of-the-k8s-cluster-in-net8/</link><pubDate>Wed, 28 Aug 2024 08:22:21 +0800</pubDate><guid>https://fwhyy.com/2024/08/in-retrieve-the-namespace-id-of-the-k8s-cluster-in-net8/</guid><description>&lt;p&gt;将程序和机器进行绑定是一种 License 校验的方法，需要能获取到机器的唯一标识，比如获取机器的 Mac 地址就是获取唯一标识的一种方式，命令如下：&lt;/p&gt;</description></item><item><title>MongoDB密码设置</title><link>https://fwhyy.com/2024/06/mongodb-password-setting/</link><pubDate>Thu, 06 Jun 2024 08:49:13 +0800</pubDate><guid>https://fwhyy.com/2024/06/mongodb-password-setting/</guid><description>&lt;p&gt;给 MongoDB 设置密码有两种情况：&lt;/p&gt;
&lt;p&gt;1、给创建的 MongDB 容器添加密码。&lt;/p&gt;
&lt;p&gt;2、给现有的无密码的 MongoDB 容器进行密码设置。&lt;/p&gt;
&lt;p&gt;在设置密码之前，先说说 MongoDB 的版本，之前一直使用 5.0.2 和 5.0.14 版本比较多，然而这两个版本都是有安全漏洞的，所以大版本如果选择 5 ，可以选择 5.0.24 。&lt;/p&gt;</description></item><item><title>Kubesphere 使用实践</title><link>https://fwhyy.com/2024/05/kubesphere-usage-practice/</link><pubDate>Wed, 29 May 2024 08:45:33 +0800</pubDate><guid>https://fwhyy.com/2024/05/kubesphere-usage-practice/</guid><description>&lt;p&gt;容器化部署，尤其是利用 Docker 技术，已成为现代软件部署的标配。我们可以通过简单的命令如 &lt;code&gt;run&lt;/code&gt; 直接启动容器，或者使用编排工具如 &lt;code&gt;docker-compose&lt;/code&gt; 和 &lt;strong&gt;Kubernetes&lt;/strong&gt;（简称 &lt;strong&gt;k8s&lt;/strong&gt;）等来简化操作。&lt;/p&gt;</description></item><item><title>迁移Wordpress到Docker</title><link>https://fwhyy.com/2024/05/migrating-wordpress-to-docker/</link><pubDate>Tue, 14 May 2024 08:40:00 +0800</pubDate><guid>https://fwhyy.com/2024/05/migrating-wordpress-to-docker/</guid><description>&lt;p&gt;很多年前我的个人博客是部署在 Linode 的服务器，后来又给女儿弄了一个博客记录女儿的成长，使用的是 Wordpress ，老婆执笔。现在我的博客早已迁移到了 github ，女儿也长大了，博客好几年没有更新，准备停掉 linode 服务器，将女儿博客迁移到本地。&lt;/p&gt;</description></item><item><title>银河麒麟V10使用Docker方式部署应用</title><link>https://fwhyy.com/2024/04/galaxy-kirin-v10-deploys-applications-using-docker/</link><pubDate>Tue, 16 Apr 2024 08:28:08 +0800</pubDate><guid>https://fwhyy.com/2024/04/galaxy-kirin-v10-deploys-applications-using-docker/</guid><description>&lt;p&gt;现在越来越多的企业级应用需要运行在国产化环境中，而银河麒麟 V10 是目前我碰到的最常用的服务器，在银河麒麟上部署应用有两种方式：使用二进制文件编译部署和使用 Docker 。&lt;/p&gt;</description></item><item><title>能更好集成容器的反向代理Traefik简单使用</title><link>https://fwhyy.com/2024/03/traefik-is-easy-to-use/</link><pubDate>Fri, 29 Mar 2024 08:13:56 +0800</pubDate><guid>https://fwhyy.com/2024/03/traefik-is-easy-to-use/</guid><description>&lt;p&gt;traefik 与 nginx 一样，也是一款优秀的反向代理工具，使用 go 语言开发，本文将介绍怎样用 traefik 来实现我的需求。&lt;/p&gt;</description></item><item><title>简单聊聊云原生</title><link>https://fwhyy.com/2024/03/lets-briefly-talk-about-cloud-native/</link><pubDate>Tue, 19 Mar 2024 08:48:37 +0800</pubDate><guid>https://fwhyy.com/2024/03/lets-briefly-talk-about-cloud-native/</guid><description>&lt;p&gt;云原生，作为一种新兴的软件架构模式，目的在推动应用程序的敏捷开发、快速部署和可靠运行。虽然这一概念已经提出多年，但直至最近几年，云原生才逐渐引起了华中区客户的广泛关注和认知（不一定准确，从我的感觉和经验来看是这样的）。&lt;/p&gt;
&lt;p&gt;本文结合我收集整理的资料、以及我的理解，来看看云原生是怎么回事？&lt;/p&gt;
&lt;h2 id="概念"&gt;概念&lt;/h2&gt;
&lt;p&gt;要搞清一个技术，先从概念开始，跟云原生这个概念有关的主要有两个组织：Pivotal 和 CNCF 。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Pivotal：Pivotal 成立于 2013 年 4 月，由 EMC、VMware 和 GE 投资成立，专注于帮助企业在数字化时代变革所需的 PaaS 云计算、大数据基础平台和平台上的极限编程。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CNCF：CNCF（Cloud Native Computing Foundation，云原生计算基金会）是 Linux 基金会旗下的基金会，可以理解为一个非盈利组织，成立于 2015 年 12 月 11 日。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2015 年，来自 Pivotal 公司的技术产品经理 Matt Stine，首次提出了云原生的概念，认为云原生架构必须包含下面一些特性：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;符合十二要素、微服务、敏捷基础设施、基于 API 的协作、抗压性&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;2017 年，Matt Stine 在接受 InfoQ 采访时，将云原生特性做了些调整：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;模块化、可观测性、可部署性、可测试性、可处理性、可替换性&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;而现在的云原生涉及到的一些关键词有，原文可以参考：https://tanzu.vmware.com/cloud-native：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;微服务、DevOps、容器、服务网格、CI/CD、Serverless&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;可见，云原生的定义是在不断演进的，不断会有新的东西加入。&lt;/p&gt;
&lt;p&gt;再来看看 CNCF 的官方最早是怎么定义的：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Cloud native computing uses an open source software stack to deploy applications as microservices, packaging each part into its own container, and dynamically orchestrating those containers to optimize resource utilization.&lt;/p&gt;
&lt;p&gt;云原生使用一种开源软件技术栈来部署微服务应用，将每个组件打包到它自己的容器中，并且通过动态编排来优化资源的利用率。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;2018 年，CNCF 推出了对云原生定义的 v1.0 版本，地址如下：&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/cncf/toc/blob/main/DEFINITION.md"&gt;https://github.com/cncf/toc/blob/main/DEFINITION.md&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中，构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API。&lt;/p&gt;
&lt;p&gt;这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段，云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。&lt;/p&gt;
&lt;p&gt;云原生计算基金会（CNCF）致力于培育和维护一个厂商中立的开源生态系统，来推广云原生技术。我们通过将最前沿的模式民主化，让这些创新为大众所用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="云计算和云原生的关系"&gt;云计算和云原生的关系&lt;/h2&gt;
&lt;p&gt;早些年，传统的企业软件开发是部署在企业的内部物理机中，为了让一个系统能正常运行，通常需要很多的机器，数据库、中间件、程序的前后端都需要进行单独部署。&lt;/p&gt;
&lt;p&gt;后来有了虚拟化技术，通过在各种实体资源（CPU、内存、网络、存储等）之上构建一个逻辑层，从而摆脱物理限制的约束，提高物理资源的利用率。最直观的感受就是可以在一台物理机上快速运行多个虚拟机、意味着可以&lt;strong&gt;降低物理机的数量，节约成本。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;虚拟技术的成熟促成了云计算的出现。2006 年 Google 首次提出了云计算的概念。云计算出现之后，就慢慢出现了 XaaS ：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IaaS（基础设施即服务）&lt;/strong&gt;：一种云计算服务类型，它按即用即付的方式按需提供必要的计算、存储和网络资源。这种服务模式帮助客户降低维护成本和硬件成本。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PaaS（平台即服务）&lt;/strong&gt;：云计算服务模式之一，它为开发人员提供了包括一系列开发工具、服务、应用程序接口（API）等资源的平台。它的目标是让开发者能够更快速、高效地构建、发布、扩展和维护应用，同时云服务商负责管理和提供开发环境。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;aPaaS（应用平台即服务）&lt;/strong&gt;：是一类特定的 PaaS，重点在于为应用程序提供更快捷的构建服务，例如低代码能力。通常包括通过可视化操作减少原生代码使用、高效的数据处理、模块化的功能实现等，目的是为了让开发者更高效地搭建、运行、维护和扩展应用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DaaS（数据即服务）&lt;/strong&gt;：将数据从静态资源转变为一种可通过网络获取的即时服务。用户可以方便地访问和使用数据，无需关心数据存储和管理的底层细节。数据通过平台进行集中化管理，提供规范化、标准化的数据访问和数据处理流程。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FaaS（函数即服务）&lt;/strong&gt;：是一种基于事件驱动的无服务器执行模式，在这种模式中，开发人员无需关心服务器的管理和维护，只需编写并上传业务函数代码。当触发特定事件时，这些代码由云服务商在全托管的环境中执行。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SaaS（软件即服务）&lt;/strong&gt;：一种云计算模式，在这种模式中，软件通常以网络浏览器的形式提供给用户。用户不需要在本地机器上安装或维护软件，所有的应用程序和数据库都位于云端的数据中心。这减少了用户在软件和硬件方面的投入和维护工作。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;云计算的兴起，一些企业将软件逐渐迁移到公有云，无需再关心网络、存储、服务器等，这些都由云厂商的 IaaS、PaaS 能力提供。&lt;/p&gt;</description></item><item><title>在.NET中动态执行Nodejs代码的另一种方法</title><link>https://fwhyy.com/2024/03/in-another-method-for-dynamically-executing-nodejs-code-in-dotnet/</link><pubDate>Mon, 11 Mar 2024 08:45:14 +0800</pubDate><guid>https://fwhyy.com/2024/03/in-another-method-for-dynamically-executing-nodejs-code-in-dotnet/</guid><description>&lt;p&gt;在低代码平台中，通常有业务逻辑编排的能力，在业务逻辑编排中有很多不同类型的节点，例如：逻辑判断、接口调用、数据更新等，但为了方便开发人员使用，如果添加代码块的节点，将会极大增加开发效率。&lt;/p&gt;</description></item><item><title>私有镜像仓库 Harbor 安装和使用</title><link>https://fwhyy.com/2024/01/private-image-warehouse-harbor-installation-and-use/</link><pubDate>Mon, 22 Jan 2024 17:28:51 +0800</pubDate><guid>https://fwhyy.com/2024/01/private-image-warehouse-harbor-installation-and-use/</guid><description>&lt;h2 id="介绍"&gt;介绍&lt;/h2&gt;
&lt;p&gt;我们如果需要部署一个私有镜像仓库来使用，最简单的就是 registry ，一行命令就可以运行在 Docker 中，但功能也比较弱，如果想要私有镜像仓库功能更丰富些，可以使用 Harbor 。&lt;/p&gt;
&lt;p&gt;本文简单介绍下 Harbor 的安装和使用。&lt;/p&gt;</description></item><item><title>利用 Github Actions 同步佳明国内到国际</title><link>https://fwhyy.com/2024/01/using-github-actions-to-synchronize-jiamings-domestic-and-international-operations/</link><pubDate>Mon, 15 Jan 2024 17:25:11 +0800</pubDate><guid>https://fwhyy.com/2024/01/using-github-actions-to-synchronize-jiamings-domestic-and-international-operations/</guid><description>&lt;p&gt;2019 年就开始在使用佳明的 245 ，最近才知道佳明分为国内区和国际区，而且两个区的账号是独立的，数据不互通。而 runalyze 、Strava 等跑步分析工具又只能和国际区进行连接同步。&lt;/p&gt;
&lt;p&gt;所以本文就是用来告诉你怎样将佳明国内区同步到国际区，这样就能正常使用 runalyze 和 Strava 了。&lt;/p&gt;</description></item><item><title>.NET中操作哨兵模式的Redis（哨兵和Redis示例配置密码）</title><link>https://fwhyy.com/2023/12/redis-for-operating-sentinel-mode-in-net/</link><pubDate>Mon, 25 Dec 2023 17:03:06 +0800</pubDate><guid>https://fwhyy.com/2023/12/redis-for-operating-sentinel-mode-in-net/</guid><description>&lt;p&gt;Redis 的高可用有一种方式是部署成哨兵模式。在哨兵模式中哨兵和每个节点都可以设置密码，如果都设置密码了，在 .NET 中用 CSRedisCore 进行调用时会遇到点问题。&lt;/p&gt;
&lt;p&gt;本文就介绍怎样用 CSRedisCore 来调用设置了密码的哨兵模式 Redis。&lt;/p&gt;</description></item><item><title>NET Core3.1 升级到 NET8</title><link>https://fwhyy.com/2023/12/dotnet-3-upgrade-to-dotnet-8/</link><pubDate>Fri, 08 Dec 2023 17:00:06 +0800</pubDate><guid>https://fwhyy.com/2023/12/dotnet-3-upgrade-to-dotnet-8/</guid><description>&lt;p&gt;.NET Core 3.1 已经用了很长一段时间，其实在 2022 年的年底微软已经不提供支持了，后面的一个 LTS 版本 .NET 6 也会在 2024 年 11 月终止支持，所以直接升级到 .NET 8 是最好的选择。&lt;/p&gt;</description></item><item><title>.NET8 正式发布， C#12 新变化</title><link>https://fwhyy.com/2023/11/dotnet-8/</link><pubDate>Fri, 17 Nov 2023 16:38:50 +0800</pubDate><guid>https://fwhyy.com/2023/11/dotnet-8/</guid><description>&lt;p&gt;在 .NET Conf 2023 大会上，.NET 8 正式发布了，.NET 8 是一个长期支持（LTS）版本，这意味着可以获得三年的支持和补丁。我们也计划将框架从 .NET Core3.1 升级到 8 ，关于如何升级等升级完成后再来分享。&lt;/p&gt;</description></item><item><title>监控利器：普罗米修斯监控中间件(Nginx、Redis、MySql 等)</title><link>https://fwhyy.com/2023/11/prometheus-monitoring-middleware/</link><pubDate>Thu, 09 Nov 2023 16:36:23 +0800</pubDate><guid>https://fwhyy.com/2023/11/prometheus-monitoring-middleware/</guid><description>&lt;p&gt;我们的产品目前使用到的中间件有 Nginx、Redis、RabbitMQ、MySql 等，本文介绍怎样使用 Promtheus 来监控这些中间件。&lt;/p&gt;</description></item><item><title>监控利器：普罗米修斯介绍和安装</title><link>https://fwhyy.com/2023/11/install-prometheus/</link><pubDate>Wed, 01 Nov 2023 08:29:51 +0800</pubDate><guid>https://fwhyy.com/2023/11/install-prometheus/</guid><description>&lt;p&gt;我们的程序想要稳定的运行，或者说当出现问题时能第一时间知道，这就离不开监控，目前比较主流的就是 Prometheus（普罗米修斯）+ Grafana 的组合。&lt;/p&gt;</description></item><item><title>聊聊六边形架构</title><link>https://fwhyy.com/2023/10/talk-about-hexagonal-architecture/</link><pubDate>Tue, 24 Oct 2023 08:27:49 +0800</pubDate><guid>https://fwhyy.com/2023/10/talk-about-hexagonal-architecture/</guid><description>&lt;p&gt;指导我们写出漂亮代码有一种方式是学习设计模式，自从 Gof 四人组的《设计模式》出版后，各类设计模式的书层出不穷。熟读这类书籍，对面试肯定是有帮助的，但代码能力是否有大的长进就不一定了，如果没能理解背后的思想，去生搬硬套，只会起反作用。&lt;/p&gt;</description></item><item><title>如何设计 API？</title><link>https://fwhyy.com/2023/10/how-to-design-the-api/</link><pubDate>Tue, 17 Oct 2023 09:42:48 +0800</pubDate><guid>https://fwhyy.com/2023/10/how-to-design-the-api/</guid><description>&lt;p&gt;在前后端分离的设计中，不管使用什么语言，后端都需要提供 WebAPI 给前端使用。如果是一个平台级的产品，还有可能需要将平台的公共 API 提供给第三方系统使用，这些都要考虑到 API 的设计。&lt;/p&gt;</description></item><item><title>插件开发：实现 PicGo 图片转 webp 格式</title><link>https://fwhyy.com/2023/08/plugin-development-implement-picgo-image-to-webp-format/</link><pubDate>Mon, 28 Aug 2023 09:18:14 +0800</pubDate><guid>https://fwhyy.com/2023/08/plugin-development-implement-picgo-image-to-webp-format/</guid><description>&lt;p&gt;我写一些文档或者公众号文章使用的是 Typora，如果涉及到文章中有图片时，直接复制图片粘贴到 Typora 中，然后使用 PicGo 上传到图床。&lt;/p&gt;</description></item><item><title>怎样在 Github 中使用免密登录？</title><link>https://fwhyy.com/2023/07/how-to-use-password-free-login-in-github/</link><pubDate>Sun, 23 Jul 2023 09:49:05 +0800</pubDate><guid>https://fwhyy.com/2023/07/how-to-use-password-free-login-in-github/</guid><description>&lt;p&gt;我们在互联网上注册各种网站，密码经常会忘记，非常麻烦。以前还能各网站使用同一密码，虽然不太安全，但好记。现在各种网站的密码规则变强，还都不太一样，记密码就更难了。&lt;/p&gt;
&lt;p&gt;如果有一种方式，能免密登录，就可以解决记不住密码的烦恼了。&lt;/p&gt;</description></item><item><title>银河麒麟系统安装中间件</title><link>https://fwhyy.com/2023/06/galaxy-kirin-system-installation-middleware/</link><pubDate>Mon, 12 Jun 2023 09:24:01 +0800</pubDate><guid>https://fwhyy.com/2023/06/galaxy-kirin-system-installation-middleware/</guid><description>&lt;p&gt;现在越来越多的企业级应用需要运行在国产化环境中，本文介绍下我们产品使用的中间件在国产操作系统银河麒麟的安装（不一定是最优方式，但能用）。&lt;/p&gt;</description></item><item><title>高可用：Nginx配合keepalived</title><link>https://fwhyy.com/2023/05/high-availability-nginx-combined-with-keepalived/</link><pubDate>Mon, 15 May 2023 12:07:12 +0800</pubDate><guid>https://fwhyy.com/2023/05/high-availability-nginx-combined-with-keepalived/</guid><description>&lt;p&gt;如果在谷歌中搜索 「Nginx 高可用」，搜索出来的大多都是 Nginx + keepalived 的使用。&lt;/p&gt;</description></item><item><title>高可用：MongoDB容器部署</title><link>https://fwhyy.com/2023/05/high-availability-mongodb-container-deployment/</link><pubDate>Mon, 08 May 2023 12:04:42 +0800</pubDate><guid>https://fwhyy.com/2023/05/high-availability-mongodb-container-deployment/</guid><description>&lt;p&gt;MongoDB 是一款 NoSQL 数据，通常用来存储非结构化数据，我们的产品中也有用到，例如：一些文件存储在 MongoDB 的 GridFS 中。&lt;/p&gt;</description></item><item><title>由 ChatGPT 带来的对低代码产品的思考</title><link>https://fwhyy.com/2023/04/thinking-about-low-code-products-brought-about-by-chatgpt/</link><pubDate>Thu, 13 Apr 2023 11:42:00 +0800</pubDate><guid>https://fwhyy.com/2023/04/thinking-about-low-code-products-brought-about-by-chatgpt/</guid><description>&lt;p&gt;在之前的文章中多次提到我们在开发一款低代码平台，主要面向 ToB 企业，帮助企业完善信息化建设，给企业的数字化转型贡献一份力量。&lt;/p&gt;</description></item><item><title>Docker日志大小限制和切换存储目录</title><link>https://fwhyy.com/2023/03/docker-log-size-limits-and-switching-storage-directories/</link><pubDate>Tue, 28 Mar 2023 11:35:16 +0800</pubDate><guid>https://fwhyy.com/2023/03/docker-log-size-limits-and-switching-storage-directories/</guid><description>&lt;p&gt;产品的各种环境使用了很多 &lt;code&gt;CentOS&lt;/code&gt; 虚拟机，默认情况下 &lt;code&gt;root&lt;/code&gt; 目录空间是 50 G，随着使用时间越来越长，空间会变得不够用。&lt;/p&gt;</description></item><item><title>dotNET 升级利器：Upgrade Assistant</title><link>https://fwhyy.com/2023/03/dotnet-upgrade-assistant/</link><pubDate>Mon, 20 Mar 2023 11:29:39 +0800</pubDate><guid>https://fwhyy.com/2023/03/dotnet-upgrade-assistant/</guid><description>&lt;p&gt;.NET 发展很快, 现在 .NET 8 的预览版已经发布了，但我们现在还在使用 .NET Core 3.1，将 .NET 升级到 .NET 6 已经势在必行。&lt;/p&gt;</description></item><item><title>GPT-4 有什么不一样？</title><link>https://fwhyy.com/2023/03/gpt-4/</link><pubDate>Wed, 15 Mar 2023 11:19:15 +0800</pubDate><guid>https://fwhyy.com/2023/03/gpt-4/</guid><description>&lt;p&gt;一觉醒来，GPT-4 发布了。&lt;/p&gt;
&lt;p&gt;GPT-4 和 GPT-3.5 都是由 OpenAI 开发的大型自然语言处理模型，它们能够理解和生成人类语言。尽管这两个模型在很多方面都相似，但它们之间还是存在一些关键区别：&lt;/p&gt;</description></item><item><title>ChatGPT 应用合集</title><link>https://fwhyy.com/2023/03/chatgpt-app-collection/</link><pubDate>Mon, 13 Mar 2023 10:26:54 +0800</pubDate><guid>https://fwhyy.com/2023/03/chatgpt-app-collection/</guid><description>&lt;p&gt;最近用了一些 ChatGPT 的周边产品，挑几个感觉不错的分享下。&lt;/p&gt;</description></item><item><title>使用微软的 New Bing</title><link>https://fwhyy.com/2023/03/try-microsoft-new-bing/</link><pubDate>Mon, 06 Mar 2023 08:13:47 +0800</pubDate><guid>https://fwhyy.com/2023/03/try-microsoft-new-bing/</guid><description>&lt;p&gt;ChatGPT 现在大家都已经非常熟悉了了，走到哪都能听到讨论的声音，是基于 GPT3.5 的一个语言模型。微软在 2 月推出的新必应（New Bing）是一个基于 GPT4（猜测）模型的搜索和聊天工具，它可以提供更准确和实时的搜索结果，并且集成了Edge 浏览器的数据资源。&lt;/p&gt;
&lt;p&gt;最近申请了 New Bing 简单试用 ，觉得还挺不错的。&lt;/p&gt;
&lt;h2 id="申请"&gt;申请&lt;/h2&gt;
&lt;p&gt;可以按照下面的步骤来进行新必应（New Bing）的申请：&lt;/p&gt;
&lt;p&gt;1、先下载并安装 Edge 浏览器 dev 版本，在：&lt;a href="https://www.microsoftedgeinsider.com/zh-cn/download/dev"&gt;Microsoft Edge 预览体验成员 (microsoftedgeinsider.com)&lt;/a&gt; 进行下载安装：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2023/202306191008420.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2、打开浏览器的设置-&amp;gt;关于，可以进行 New Bing 使用的申请：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2023/202306191008517.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3、登录后加入候补名单：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2023/202306191008380.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;4、然后就是等待，很幸运，一天的时间就通过了申请，使用界面如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2023/202306191008300.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="基础使用"&gt;基础使用&lt;/h2&gt;
&lt;p&gt;New Bing 的主题功能分为聊天、撰写和见解。&lt;/p&gt;
&lt;h3 id="聊天"&gt;聊天&lt;/h3&gt;
&lt;p&gt;和 ChatGPT 类似，使用问答的形式进行交互，除了基础的输入框进行提问外，还能设置响应的语气。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2023/202306191008948.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h3 id="撰写"&gt;撰写&lt;/h3&gt;
&lt;p&gt;将文字的创作单独剥离出来，提供更多的配置选项，更方便使用：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2023/202306191008833.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="特点"&gt;特点&lt;/h2&gt;
&lt;h3 id="实时性"&gt;实时性&lt;/h3&gt;
&lt;p&gt;在聊天功能中，虽然和 ChatGPT 一样都是问答的模式，但它可以实时访问网络数据，找到 ChatGPT 没见过的数据，更加实时。&lt;/p&gt;
&lt;p&gt;例如：我们分别让 New Bing 和 ChatGPT 评价下春节档的电影《满江红》就能看出区别了。&lt;/p&gt;
&lt;p&gt;ChatGPT 并不知道春节上映的电影《满江红》，因为它的语言模型是 2021 年训练的，但可怕的是 ChatGPT 并不知道自己不知道，仍然会胡说八道一通。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2023/202306191008681.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;而在 New Bing 中，能够搜索到最新的信息，还能给出出处链接：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2023/202306191008192.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h3 id="互动性"&gt;互动性&lt;/h3&gt;
&lt;p&gt;在问答的过程中 ，New Bing 会给出一些推荐的关键词来和我们进行互动，我们可以通过给出的关键词进一步和 New Bing 进行互动，也可以自己输入新的问题。&lt;/p&gt;
&lt;h3 id="准确性"&gt;准确性&lt;/h3&gt;
&lt;p&gt;New Bing 会根据你提的问题结合搜搜引擎和基础语言模型，最终组成答案进行输出，而且在答案中会给出来源出处，点击链接可以进入到原始网页进行查看。&lt;/p&gt;
&lt;h3 id="文章总结"&gt;文章总结&lt;/h3&gt;
&lt;p&gt;在网页中打开一篇文章，可以让 New Bing 来协助我们进行阅读，总结文章的内容。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2023/202306191008153.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="遗憾"&gt;遗憾&lt;/h2&gt;
&lt;p&gt;1、2 月 18 日，微软通过官方博客宣布，基于 AI 的新版必应对话功能将加入问答限额，每天最多回答 50 次问题，每次连续对话最多回答 5 个问题。微软称，根据统计，绝大多数用户都能在 5 轮问答内找到满意答案，只有大约 1% 的对话产生超过 50 条消息；定期清除对话记录有助于避免模型产生混淆。&lt;/p&gt;
&lt;p&gt;2、回答的效果上好像也做了些调整，变得相对严肃，记得刚出来时，看了 B 站一个视频，它的风格是这样的：&lt;/p&gt;</description></item><item><title>ChatGPT 是什么？越来越清晰了</title><link>https://fwhyy.com/2023/02/what-is-chatgpt-its-getting-clearer/</link><pubDate>Tue, 21 Feb 2023 08:09:55 +0800</pubDate><guid>https://fwhyy.com/2023/02/what-is-chatgpt-its-getting-clearer/</guid><description>&lt;p&gt;两个月前，ChatGPT 刚出来不久，我便注册试用了，在《尝鲜 ChatGPT》中介绍了注册的过程和简单使用的示例。&lt;/p&gt;
&lt;p&gt;最近，ChatGPT 越来越火了，朋友圈、公众号、微博、即刻随处可见关于 ChatGPT 的信息。我也看了不少关于 ChatGPT 的文章，一些疑问也得到解答。&lt;/p&gt;
&lt;h2 id="活跃用户"&gt;活跃用户&lt;/h2&gt;
&lt;p&gt;ChatGPT 用 2 个月达到月活用户 1 亿，此前记录是 TikTok 用时 9 个月，很多新闻中都提到了这个 1 亿用户来吸引眼球。&lt;/p&gt;
&lt;p&gt;需要说明的是，这里的月活用户不是指注册用户，可能还包含爬虫、游客等。即便如此，我认为也不会是一个很少的数量级，加上最近各大媒体报道，各种注册服务的推出，估计也差不太多。&lt;/p&gt;
&lt;p&gt;关于用户，大辉的这篇文章有详细讲述：&lt;/p&gt;
&lt;p&gt;&lt;a href="https://mp.weixin.qq.com/s/iBmJEa4AzZKSO4nfKtCZDQ"&gt;https://mp.weixin.qq.com/s/iBmJEa4AzZKSO4nfKtCZDQ&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="和搜索引擎的对比"&gt;和搜索引擎的对比&lt;/h2&gt;
&lt;p&gt;ChatGPT 的使用方式是面向一个文本框，用提问来进行交互；搜索引擎也是一个文本框，通过输入关键字来进行检索。看着很类似，其实有很大差别。&lt;/p&gt;
&lt;p&gt;有几个重要的区别是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ChatGPT 因为训练一次，费用昂贵，所以 ChatGPT 不是实时的，而搜索引擎的时效性很高；&lt;/li&gt;
&lt;li&gt;ChatGPT 是基于语义分析，搜索引擎是基于关键字索引；&lt;/li&gt;
&lt;li&gt;ChatGPT 会给一个最优解，搜索引擎的结果为多条符合关键字匹配的内容，我们需要自己对结果进行分析、辨别，然后对比、合并、重新理解，最终得到一个答案；&lt;/li&gt;
&lt;li&gt;ChatGPT 可以基于上下文进行追问，让他知道我们的真实需求，结果也会不断进行优化，搜索引擎只能调整关键字，得到新的结果；&lt;/li&gt;
&lt;li&gt;ChatGPT 仅仅是个结果，搜索引擎会有来源链接。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不管是 ChatGPT 还是搜索引擎，都是辅助我们的工具，这两者不是对立的，而是各有各的使用场景。&lt;/p&gt;
&lt;p&gt;例如：我要查询天气、看看日历、行业最新资讯等，我肯定用搜索引擎；如果我要写一个很特殊的正则表达式或 Sql ，我就会使用 ChatGPT ，因为我可以通过一大段描述，将我的场景写清楚，ChatGPT 可以理解并给出一个还不错的答案，甚至是一个开箱即用的答案。&lt;/p&gt;
&lt;h2 id="是否能取代程序员"&gt;是否能取代程序员？&lt;/h2&gt;
&lt;p&gt;记得在低代码比较火热的时候，就有低代码平台是否会跟程序员抢饭碗的话题。几年前，我们去给客户推荐我们的产品，一些有研发能力的客户会比较抵触。&lt;/p&gt;
&lt;p&gt;现在 ChatGPT 火了，大家又开始讨论程序员是不是会被取代？&lt;/p&gt;
&lt;p&gt;上面我也说到，和搜索引擎一样，ChatGPT 只是一个工具，既然是工具就会被人所使用，是为了提高人的创造力和生产力，为我们服务的。&lt;/p&gt;
&lt;p&gt;举两个例子：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;农业机械化生产后，拿着锄头到地里干活的人少了，但会需要操作机器的人；&lt;/li&gt;
&lt;li&gt;低代码流行后，落地一个项目，需要的程序员变少了，但会需要更多的配置和搭建的人员，相比程序员，这些人员的成本更低；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ChatGPT 也是一样，无论怎么发展，只要利用好，效率会成百上千倍的增长，并且会滋生出来很多新的职业和岗位。&lt;/p&gt;
&lt;p&gt;程序员的日常工作就是把人的诉求通过编程语言表达出来传递给电脑，电脑运算出结果，而 ChatGPT 能够分析语义，这让人的诉求到电脑能够理解这个过程变得容易了，这也就是为什么王建硕会说未来十年中国会新增五亿程序员了，因为借助工具，更多的人都能更电脑进行交互了。&lt;/p&gt;
&lt;h2 id="我们该做些什么"&gt;我们该做些什么？&lt;/h2&gt;
&lt;p&gt;一个新的技术出来，有这么三类人：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;找到缝隙，赢得先机，狠狠地赚一笔；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;杞人忧天，各种担心；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;利用好技术，提升效率。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ChatGPT 因为在国内注册不方便，就有人专门做了收费服务，帮助注册，据说一个月赚几十万。也有人还在想着自己会不会被取代，对我而言，我把 ChatGPT 当成一个效率工具，使用好他就可以了。&lt;/p&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;ChatGPT 是一个开始，可能还会带来革命性的改变。就像蒸汽机引发了工业革命，改变人类的生产方式、浏览器的诞生催生了互联网的发展；乔布斯发布 iPhone 后，宣告了移动互联网的来临。&lt;/p&gt;
&lt;p&gt;但在眼下，我们可以做些力所能及的，比如：将 ChatGPT 集成到微信群，尝试使用下微软发布的 New Bing 。&lt;/p&gt;
&lt;p&gt;未来是什么样，拭目以待。&lt;/p&gt;</description></item><item><title>尝鲜 ChatGPT</title><link>https://fwhyy.com/2022/12/try-chatgpt/</link><pubDate>Tue, 06 Dec 2022 08:48:59 +0800</pubDate><guid>https://fwhyy.com/2022/12/try-chatgpt/</guid><description>&lt;h2 id="什么是-chatgpt-"&gt;什么是 ChatGPT ？&lt;/h2&gt;
&lt;p&gt;我们先来看看 ChatGPT 自己的回答是什么：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2023/202306162045752.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;ChatGPT 是著名的 OpenAI 公司最近推出的新产品，可以以对话的形式给 AI 提问，AI 会给出一个还不错的回答，就像上图那样。&lt;/p&gt;</description></item><item><title>dotNET 7：最小 API 使用</title><link>https://fwhyy.com/2022/11/dotmet-7-minimal-api-usage/</link><pubDate>Mon, 21 Nov 2022 08:39:37 +0800</pubDate><guid>https://fwhyy.com/2022/11/dotmet-7-minimal-api-usage/</guid><description>&lt;p&gt;Minimal APIs 并不是在 .NET 7 中才加入的，记得应该是在 .NET 6 中就已经提供，只是对我来说，到现在才开始使用。&lt;/p&gt;</description></item><item><title>C# 11：接口中的静态抽象成员</title><link>https://fwhyy.com/2022/11/csharp-11-static-abstract-members-in-interfaces/</link><pubDate>Mon, 14 Nov 2022 08:46:42 +0800</pubDate><guid>https://fwhyy.com/2022/11/csharp-11-static-abstract-members-in-interfaces/</guid><description>&lt;p&gt;接口我们都很了解了，在编写代码的时，如果有一定的抽象思维，就会将不同对象的相同行为抽象出来，放到接口中，我们最熟悉的就是在接口中写一堆方法的定义。&lt;/p&gt;</description></item><item><title>dotNET 7 尝鲜（VS 和 C# 11)</title><link>https://fwhyy.com/2022/11/dotnet-7-early-edition/</link><pubDate>Thu, 10 Nov 2022 18:39:37 +0800</pubDate><guid>https://fwhyy.com/2022/11/dotnet-7-early-edition/</guid><description>&lt;p&gt;2022 年 11 月 8 日，.NET 7 正式发布了，从 11 月 8 号 到 10 号，线上的 .NET Conf 2022 会议正在举行，可以通过 &lt;a href="https://www.dotnetconf.net/"&gt;https://www.dotnetconf.net/&lt;/a&gt; 了解相关情况。&lt;/p&gt;</description></item><item><title>Go 学习：并发编程</title><link>https://fwhyy.com/2022/10/go-learning-concurrency/</link><pubDate>Mon, 17 Oct 2022 08:21:16 +0800</pubDate><guid>https://fwhyy.com/2022/10/go-learning-concurrency/</guid><description>&lt;p&gt;Go 语言在创建之初，CPU 多核发展的正猛，Go 语言的创始人果断将面向多核、原生就支持并发作为了 Go 语言的设计目标之一，所以所在 Go 语言中使用并发有得天独厚的优势。&lt;/p&gt;
&lt;p&gt;那么，什么是并发呢？&lt;/p&gt;</description></item><item><title>系统学习还是得看书，Go 书籍推荐</title><link>https://fwhyy.com/2022/10/go-book-recommendation/</link><pubDate>Sat, 08 Oct 2022 08:21:16 +0800</pubDate><guid>https://fwhyy.com/2022/10/go-book-recommendation/</guid><description>&lt;p&gt;想要更系统地学习编程语言，看书是比较有效的途径之一。最近又学习了下 Go 语言，为什么是又，因为 2013 年买过许式伟大佬翻译的一本 Go 语言书籍，但没有系统学下去，现在想想原因可能是这本书过于严肃，没那么有趣，还有就是当时对编程语言的理解也没那么深。&lt;/p&gt;
&lt;p&gt;所以说看书虽然系统，还是要选择能够看的进去的书。之前看过一句话：写作需要阅读作为基础，阅读也需要阅读作为基础，我觉得很有道理。所以在看书之前，可以先将这个领域的相关概念大概了解下，不同的文章做下横向比较，再去阅读书籍，会有不错的效果，这就像学生时代的课前预习一样。&lt;/p&gt;</description></item><item><title>Go 学习：那些不一样的知识点（下）</title><link>https://fwhyy.com/2022/10/go-learning-those-different-knowledge-points-2/</link><pubDate>Sat, 01 Oct 2022 08:21:16 +0800</pubDate><guid>https://fwhyy.com/2022/10/go-learning-those-different-knowledge-points-2/</guid><description>&lt;p&gt;在上一篇《Go 学习：那些不一样的知识点（上）》中已经提到了 10 个 Go 语言中有特点的地方，本文继续介绍一些 Go 语言中语法或使用方式比较独特的知识点。&lt;/p&gt;
&lt;h2 id="11切片类型"&gt;11、切片类型&lt;/h2&gt;
&lt;p&gt;同 Python 一样，Go 语言中也支持切片类型，而 C# 在 C# 8 中也增加了对数组进行切片操作的语法糖，先来看一个 C# 的例子：&lt;/p&gt;</description></item><item><title>Go 学习：那些不一样的知识点（上）</title><link>https://fwhyy.com/2022/09/go-learning-those-different-knowledge-points/</link><pubDate>Mon, 26 Sep 2022 08:20:20 +0800</pubDate><guid>https://fwhyy.com/2022/09/go-learning-those-different-knowledge-points/</guid><description>&lt;p&gt;在学习 Go 语言的过程中，会涉及到语法、数据结构、和一些 Go 特有的东西，其中有不少现在还印象深刻，本文就说说 Go 语言中那些不一样的地方。&lt;/p&gt;</description></item><item><title>Go 学习：从环境搭建到写一个 Web 服务</title><link>https://fwhyy.com/2022/09/go-learning-from-environment-building-to-writing-a-web-service/</link><pubDate>Mon, 19 Sep 2022 08:20:20 +0800</pubDate><guid>https://fwhyy.com/2022/09/go-learning-from-environment-building-to-writing-a-web-service/</guid><description>&lt;p&gt;最近学习了 Go 语言，做下记录。&lt;/p&gt;
&lt;h2 id="go-的来历"&gt;Go 的来历&lt;/h2&gt;
&lt;p&gt;和 C、C++ 相比， Go 是一门很年轻的语言。2007 年，在 Google 的内部，有三位大佬因为 C++ 的复杂性、构建编译速度很慢和对并发支持不好等原因，便决定开发一门新的语言，于是他们基于 C 语言，做了功能的删减和新增，便有了 Go 的诞生。&lt;/p&gt;</description></item><item><title>.NET Core 使用 LibreOffice 实现 Office 预览（Docker 部署）</title><link>https://fwhyy.com/2022/08/libreoffice-implements-office-preview/</link><pubDate>Mon, 29 Aug 2022 08:20:20 +0800</pubDate><guid>https://fwhyy.com/2022/08/libreoffice-implements-office-preview/</guid><description>&lt;p&gt;前些年做云盘产品的时候，一个很核心的功能就是 Office 文件预览，当时还没有使用 .NET Core ,程序部署在 Windows Server 服务器上，文件预览的方案采用了微软的 OWA 。&lt;/p&gt;
&lt;p&gt;目前在做的零代码产品中的表单附件控件，同样面临着 Office 文件预览的问题，现在技术栈采用了 .NET Core ，并使用容器化部署，自然就抛弃了 OWA 的方案。&lt;/p&gt;
&lt;p&gt;本文简单介绍下 OWA 的替代方案。&lt;/p&gt;</description></item><item><title>微服务：事务管理</title><link>https://fwhyy.com/2022/08/microservices-transaction-management/</link><pubDate>Mon, 01 Aug 2022 08:20:20 +0800</pubDate><guid>https://fwhyy.com/2022/08/microservices-transaction-management/</guid><description>&lt;p&gt;几乎所有的信息管理系统都会涉及到事务，事务的目的是为了保证数据的一致性，这里说的一致性是数据库状态的一致性。&lt;/p&gt;
&lt;p&gt;说到数据库状态的一致性，相信大家都会想到 ACID ：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;原子性（Atomic）：在一个事件的多个数据库操作中，要么同时成功，要么同时失败，例如：转账业务；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;隔离性（Isolation）：不同的业务之间处理数据相互独立，互不影响&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;持久性（Durability）：正常提交的数据能够被持久化，不丢失数据，比如 mysql 天然就能持久化，redis 、 rabbitmq 也能通过设置进行持久化；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一致性（Consistency）：最终的数据正确，所以说是通过 AID 这些手段来保证了 C 。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>NET Core中的RabbitMQ消费者CPU高，竟然是这个原因</title><link>https://fwhyy.com/2022/06/the-high-cpu-of-rabbitmq-consumers-in-net-core/</link><pubDate>Mon, 06 Jun 2022 08:08:42 +0800</pubDate><guid>https://fwhyy.com/2022/06/the-high-cpu-of-rabbitmq-consumers-in-net-core/</guid><description>&lt;p&gt;在 RabbitMQ 中有一个 vhsot 机制，可以用来做租户隔离，当产品从单租户演化为多租户时，正好可以用到这个特性，不同 vhost 中的交换机、队列互不影响。&lt;/p&gt;</description></item><item><title>微服务：服务间如何通信？</title><link>https://fwhyy.com/2022/05/microservices-how-do-services-communicate/</link><pubDate>Mon, 16 May 2022 08:10:55 +0800</pubDate><guid>https://fwhyy.com/2022/05/microservices-how-do-services-communicate/</guid><description>&lt;p&gt;在微服务架构中，会将一个完整的应用程序拆分成一组服务。这些服务之间需要经过协作，通过接口调用，才能组成一个完整的应用。&lt;/p&gt;
&lt;p&gt;不同的服务部署在不同的机器上，或者同一个机器的多个容器中，进程间的通信就不可避免了，也变得非常重要。&lt;/p&gt;</description></item><item><title>从一个简单 API 的发布到组件化的架构思考</title><link>https://fwhyy.com/2022/04/thoughts-on-the-architecture-from-the-release/</link><pubDate>Mon, 18 Apr 2022 09:53:44 +0800</pubDate><guid>https://fwhyy.com/2022/04/thoughts-on-the-architecture-from-the-release/</guid><description>&lt;p&gt;在 SaaS 版本的零代码平台中，高级用户希望能上传自己编写的 WebAPI ，来实现一些复杂场景下的业务。就需要添加可以通过上传程序包进行发布部署的功能。&lt;/p&gt;</description></item><item><title>代码居然还能这样写</title><link>https://fwhyy.com/2022/04/how-can-the-code-be-written-like-this/</link><pubDate>Mon, 11 Apr 2022 08:20:20 +0800</pubDate><guid>https://fwhyy.com/2022/04/how-can-the-code-be-written-like-this/</guid><description>&lt;p&gt;这篇文章要介绍的是 GitHub Copilot 。&lt;/p&gt;
&lt;p&gt;微软去年推出的 GitHub Copilot 是一个基于 AI 的编程辅助工具，简单理解就是我们写点注释或者写个方法名，Copilot 就能理解了我们的意思，然后帮我们写一个相关的方法出来。&lt;/p&gt;</description></item><item><title>微服务：如何拆分服务？</title><link>https://fwhyy.com/2022/03/how-to-split-services/</link><pubDate>Mon, 28 Mar 2022 08:26:00 +0800</pubDate><guid>https://fwhyy.com/2022/03/how-to-split-services/</guid><description>&lt;p&gt;在微服务的落地中，第一步就需要进行微服务的拆分，服务的拆分很困难也很重要，本文就讲讲怎么进行服务的拆分。&lt;/p&gt;
&lt;p&gt;技术发展到现在，还没有一个具体的，设计完善的标准方法来完成服务的拆分，服务的拆分是一门技术更是一门艺术。&lt;/p&gt;</description></item><item><title>微服务：我们需要从单体转到微服务吗？</title><link>https://fwhyy.com/2022/03/do-we-need-to-switch-from-monomer-to-microservice/</link><pubDate>Mon, 07 Mar 2022 08:26:00 +0800</pubDate><guid>https://fwhyy.com/2022/03/do-we-need-to-switch-from-monomer-to-microservice/</guid><description>&lt;p&gt;微服务或许你没有真正实践过，但一定听说过，虽然已经到了 2022 年，这个词依然很热，可以通过搜索 google 指数看得到。&lt;/p&gt;</description></item><item><title>CentOS单机安装k8s并部署.NET 6程序</title><link>https://fwhyy.com/2022/02/centos-install-k8s-deploy-net6/</link><pubDate>Sun, 20 Feb 2022 10:26:00 +0800</pubDate><guid>https://fwhyy.com/2022/02/centos-install-k8s-deploy-net6/</guid><description>&lt;p&gt;学习云原生，k8s 是一个基础，为了做一些实验，单机部署是最方便的，下面将介绍在 CentOS 中单机安装 k8s ，并将一个 .NET 6 的程序发布到 k8s 中。&lt;/p&gt;</description></item><item><title>Hexo 的 Stellar 主题问题</title><link>https://fwhyy.com/2022/01/hexo-stellar-theme-problems/</link><pubDate>Thu, 27 Jan 2022 14:45:54 +0800</pubDate><guid>https://fwhyy.com/2022/01/hexo-stellar-theme-problems/</guid><description>&lt;h2 id="软件版本"&gt;软件版本&lt;/h2&gt;
&lt;p&gt;相关的版本如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;macOS: 10.15.7
Hexo: 5.4.0
hexo-cli: 4.3.0
node.js: 14.17.3 
npm: 6.14.13
stellar: 1.6.1
&lt;/code&gt;&lt;/pre&gt;&lt;!-- more --&gt;
&lt;h2 id="问题1-hexo-g-生成问题"&gt;问题1： hexo g 生成问题&lt;/h2&gt;
&lt;p&gt;当我的post数量超过 6 时，使用hexo g 进行生成就会报下图中的错误，删掉一篇就能生成成功，尝试过换不同的post文章，基本能排除是某一个文章特殊内容的问题。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;原文中的错误截图文件已经缺失，这里保留文字说明。
尝试过将 stellar 降级到 1.6.0 和 1.5.2 都出现相同错误。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;后来尝试将_config.xml 中的主题切换成默认主题 languages ，执行 hexo g ，可以正常生成，然后又切回 stellar 主题，hexo g 正常了。后面间歇性的发生上图错误，来回切换下就正常了，很是奇怪。&lt;/p&gt;
&lt;h2 id="问题2运行时问题"&gt;问题2：运行时问题&lt;/h2&gt;
&lt;p&gt;post 文章加到了将近 20 篇时，hexo g 生成没有问题，hexo s 运行后，访问网页，不能正常显示，控制台出现如下错误：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;INFO Start processing
INFO Hexo is running at http://localhost:4000 . Press Ctrl+C to stop.

&amp;lt;--- Last few GCs ---&amp;gt;

[12722:0x110008000] 35949 ms: Scavenge 3974.7 (4103.6) -&amp;gt; 3974.6 (4104.6) MB, 7.9 / 0.0 ms (average mu = 0.813, current mu = 0.672) allocation failure 
[12722:0x110008000] 35974 ms: Scavenge 3975.6 (4104.6) -&amp;gt; 3973.8 (4119.6) MB, 22.8 / 0.0 ms (average mu = 0.813, current mu = 0.672) allocation failure 
[12722:0x110008000] 37751 ms: Mark-sweep 3988.7 (4119.6) -&amp;gt; 3986.5 (4135.6) MB, 1742.6 / 0.0 ms (average mu = 0.656, current mu = 0.133) allocation failure scavenge might not succeed


&amp;lt;--- JS stacktrace ---&amp;gt;

FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory
 1: 0x10130c5e5 node::Abort() (.cold.1) [/usr/local/bin/node]
 2: 0x1000b2289 node::Abort() [/usr/local/bin/node]
 3: 0x1000b23ef node::OnFatalError(char const*, char const*) [/usr/local/bin/node]
 4: 0x1001f68c7 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
 5: 0x1001f6863 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
 6: 0x1003a47e5 v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/usr/local/bin/node]
 7: 0x100400823 v8::internal::EvacuateNewSpaceVisitor::Visit(v8::internal::HeapObject, int) [/usr/local/bin/node]
 8: 0x1003e808b void v8::internal::LiveObjectVisitor::VisitBlackObjectsNoFail&amp;lt;v8::internal::EvacuateNewSpaceVisitor, v8::internal::MajorNonAtomicMarkingState&amp;gt;(v8::internal::MemoryChunk*, v8::internal::MajorNonAtomicMarkingState*, v8::internal::EvacuateNewSpaceVisitor*, v8::internal::LiveObjectVisitor::IterationMode) [/usr/local/bin/node]
 9: 0x1003e7bd5 v8::internal::FullEvacuator::RawEvacuatePage(v8::internal::MemoryChunk*, long*) [/usr/local/bin/node]
10: 0x1003e7916 v8::internal::Evacuator::EvacuatePage(v8::internal::MemoryChunk*) [/usr/local/bin/node]
11: 0x10040524e v8::internal::PageEvacuationTask::RunInParallel(v8::internal::ItemParallelJob::Task::Runner) [/usr/local/bin/node]
12: 0x1003bf202 v8::internal::ItemParallelJob::Task::RunInternal() [/usr/local/bin/node]
13: 0x1003bf688 v8::internal::ItemParallelJob::Run() [/usr/local/bin/node]
14: 0x1003e9985 void v8::internal::MarkCompactCollectorBase::CreateAndExecuteEvacuationTasks&amp;lt;v8::internal::FullEvacuator, v8::internal::MarkCompactCollector&amp;gt;(v8::internal::MarkCompactCollector*, v8::internal::ItemParallelJob*, v8::internal::MigrationObserver*, long) [/usr/local/bin/node]
15: 0x1003e9586 v8::internal::MarkCompactCollector::EvacuatePagesInParallel() [/usr/local/bin/node]
16: 0x1003d4cf7 v8::internal::MarkCompactCollector::Evacuate() [/usr/local/bin/node]
17: 0x1003d258b v8::internal::MarkCompactCollector::CollectGarbage() [/usr/local/bin/node]
18: 0x1003a4eab v8::internal::Heap::MarkCompact() [/usr/local/bin/node]
19: 0x1003a1499 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/bin/node]
20: 0x10039f2e0 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node]
21: 0x1003ad9ea v8::internal::Heap::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/local/bin/node]
22: 0x1003ada71 v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/local/bin/node]
23: 0x100376cce v8::internal::FactoryBase&amp;lt;v8::internal::Factory&amp;gt;::NewRawTwoByteString(int, v8::internal::AllocationType) [/usr/local/bin/node]
24: 0x10078f54d v8::internal::IncrementalStringBuilder::Extend() [/usr/local/bin/node]
25: 0x1004bd9ad v8::internal::JsonStringifier::SerializeString(v8::internal::Handle&amp;lt;v8::internal::String&amp;gt;) [/usr/local/bin/node]
26: 0x1004c2458 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
27: 0x1004c07ee v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;false&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
28: 0x1004be856 v8::internal::JsonStringifier::SerializeArrayLikeSlow(v8::internal::Handle&amp;lt;v8::internal::JSReceiver&amp;gt;, unsigned int, unsigned int) [/usr/local/bin/node]
29: 0x1004c2805 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
30: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
31: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
32: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
33: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
34: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
35: 0x1004c07ee v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;false&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
36: 0x1004be856 v8::internal::JsonStringifier::SerializeArrayLikeSlow(v8::internal::Handle&amp;lt;v8::internal::JSReceiver&amp;gt;, unsigned int, unsigned int) [/usr/local/bin/node]
37: 0x1004c2805 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
38: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
39: 0x1004c07ee v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;false&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
40: 0x1004be856 v8::internal::JsonStringifier::SerializeArrayLikeSlow(v8::internal::Handle&amp;lt;v8::internal::JSReceiver&amp;gt;, unsigned int, unsigned int) [/usr/local/bin/node]
41: 0x1004c2805 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
42: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
43: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
44: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
45: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
46: 0x1004c07ee v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;false&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
47: 0x1004be856 v8::internal::JsonStringifier::SerializeArrayLikeSlow(v8::internal::Handle&amp;lt;v8::internal::JSReceiver&amp;gt;, unsigned int, unsigned int) [/usr/local/bin/node]
48: 0x1004c2805 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
49: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
50: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
51: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
52: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
53: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
54: 0x1004c07ee v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;false&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
55: 0x1004be856 v8::internal::JsonStringifier::SerializeArrayLikeSlow(v8::internal::Handle&amp;lt;v8::internal::JSReceiver&amp;gt;, unsigned int, unsigned int) [/usr/local/bin/node]
56: 0x1004c2805 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
57: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
58: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
59: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
60: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
61: 0x1004c4008 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;true&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
62: 0x1004c07ee v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;false&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
63: 0x1004be856 v8::internal::JsonStringifier::SerializeArrayLikeSlow(v8::internal::Handle&amp;lt;v8::internal::JSReceiver&amp;gt;, unsigned int, unsigned int) [/usr/local/bin/node]
64: 0x1004bf687 v8::internal::JsonStringifier::Result v8::internal::JsonStringifier::Serialize_&amp;lt;false&amp;gt;(v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, bool, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
65: 0x1004ba503 v8::internal::JsonStringify(v8::internal::Isolate*, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;, v8::internal::Handle&amp;lt;v8::internal::Object&amp;gt;) [/usr/local/bin/node]
66: 0x1002a0253 v8::internal::Builtin_JsonStringify(int, unsigned long*, v8::internal::Isolate*) [/usr/local/bin/node]
67: 0x100a81b59 Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit [/usr/local/bin/node]
68: 0x100a14839 Builtins_ArgumentsAdaptorTrampoline [/usr/local/bin/node]
69: 0x100a1a902 Builtins_InterpreterEntryTrampoline [/usr/local/bin/node]
zsh: abort hexo s
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>华为云鲲鹏服务器部署Java踩坑记</title><link>https://fwhyy.com/2022/01/huawei-cloud-server-deployment-3/</link><pubDate>Thu, 20 Jan 2022 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2022/01/huawei-cloud-server-deployment-3/</guid><description>&lt;p&gt;之前跟华为云的技术人员沟通，他们说在鲲鹏服务器上构建部署对微软的 dotNET 支持不是很好，建议使用 Java ，我们程序现在是混合模式 dotNET 和 Java 都有。让我没想到的是 dotNET 的构建部署很顺利，反倒是 Java 的部署遇到了些问题。&lt;/p&gt;</description></item><item><title>华为云服务器初探二（完结）</title><link>https://fwhyy.com/2022/01/huawei-cloud-server-deployment-2/</link><pubDate>Fri, 14 Jan 2022 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2022/01/huawei-cloud-server-deployment-2/</guid><description>&lt;p&gt;在上一篇《&lt;a href="http://mp.weixin.qq.com/s?__biz=MzU0NjgzNzQyMw==&amp;amp;mid=2247484822&amp;amp;idx=1&amp;amp;sn=9712c1cc0a7efa7e5938021c7c088c6a&amp;amp;chksm=fb56c356cc214a406ee70fa7ae6908822871892855c1602db1ccc2cd8119f54f7f5dc30acb17&amp;amp;scene=21#wechat_redirect"&gt;华为云服务器初探&lt;/a&gt;》 中介绍了在使用华为云服务器部署时的一些关键点，本篇继续，内容涉及如下:&lt;/p&gt;</description></item><item><title>华为云服务器部署初探</title><link>https://fwhyy.com/2022/01/huawei-cloud-server-deployment/</link><pubDate>Mon, 10 Jan 2022 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2022/01/huawei-cloud-server-deployment/</guid><description>&lt;p&gt;最近玩了下华为云，遇到了一些坑，做下记录。&lt;/p&gt;
&lt;p&gt;华为云有很多的服务，文中会涉及到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CCE&lt;/li&gt;
&lt;li&gt;ECS&lt;/li&gt;
&lt;li&gt;弹性公网IP&lt;/li&gt;
&lt;li&gt;DevCloud&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>设计模式：面向对象的设计原则下（ISP、DIP、KISS、YAGNI、DRY、LOD）</title><link>https://fwhyy.com/2021/12/object-oriented-design-principles-2/</link><pubDate>Mon, 13 Dec 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/12/object-oriented-design-principles-2/</guid><description>&lt;p&gt;本文继续来介绍接口隔离原则（ISP）和依赖倒置原则（DIP），这两个原则都和接口和继承有关。文章最后会简单介绍几个除了 SOLID 原则之外的原则。&lt;/p&gt;</description></item><item><title>设计模式：面向对象的设计原则上（SRP、OCP、LSP）</title><link>https://fwhyy.com/2021/12/object-oriented-design-principles-1/</link><pubDate>Mon, 06 Dec 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/12/object-oriented-design-principles-1/</guid><description>&lt;p&gt;在面向对象的世界里，可以分为：面向对象的基础知识、面向对象的设计原则和设计模式，如果用武侠小说来做比喻，基础知识就是需要练习的基本功、设计原则就是内功心法、设计模式则是各种各样的具体招式，所以说熟练掌握了设计原则，就能以不变应万变。&lt;/p&gt;</description></item><item><title>设计模式：面向对象的基础知识</title><link>https://fwhyy.com/2021/11/object-oriented-basic-knowledge/</link><pubDate>Mon, 15 Nov 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/11/object-oriented-basic-knowledge/</guid><description>&lt;p&gt;主流的编程范式有三种：面向过程、面向对象和函数式编程，我们现在使用的主流编程语言 C# 或 Java，都是面向对象语言，所以常常说的设计模式也是在面向对象语言这个前提之下。&lt;/p&gt;
&lt;p&gt;面向对象的基础知识和一些设计原则，我认为是学习设计模式的基础，本文就聊下这些基础知识。&lt;/p&gt;</description></item><item><title>现在还需要学习设计模式吗？</title><link>https://fwhyy.com/2021/11/do-you-still-need-to-learn-design-patterns-now/</link><pubDate>Mon, 01 Nov 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/11/do-you-still-need-to-learn-design-patterns-now/</guid><description>&lt;p&gt;最近面试了不少人，Java 和 dotNET 的都有，当问到设计模式时，大部分都只能说出单例和工厂，有些能聊聊其他的一些模式的，大多也没有在实际项目中用过。为了团队成员能有更好的编码能力，便有了重新写写设计模式的想法，写作也是一个重新学习的过程。&lt;/p&gt;</description></item><item><title>12 个问题搞懂 Redis</title><link>https://fwhyy.com/2021/09/12-questions-to-understand-redis/</link><pubDate>Mon, 13 Sep 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/09/12-questions-to-understand-redis/</guid><description>&lt;p&gt;都说学习需要带着问题，带着思考进行学习，下面就以问题的形式来学习下 Redis 。&lt;/p&gt;</description></item><item><title>dotNet 5 中执行 Node.js</title><link>https://fwhyy.com/2021/08/dotnet5-exec-node-js/</link><pubDate>Mon, 09 Aug 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/08/dotnet5-exec-node-js/</guid><description>&lt;p&gt;在&lt;a href="http://mp.weixin.qq.com/s?__biz=MzU0NjgzNzQyMw==&amp;amp;mid=2247484621&amp;amp;idx=1&amp;amp;sn=e23179a553c2cf80f5b2d0d351c75065&amp;amp;chksm=fb56c20dcc214b1b17894f1afb6070024cd1321811182d202437cea4baaecf34e69f27ad0978&amp;amp;scene=21#wechat_redirect"&gt;低代码产品&lt;/a&gt;中为了扩展功能，我们在业务编排中会扩展代码块的功能，允许用户直接在界面中进行代码（Node.js、 Python）的编写，来实现取数或者赋值的一些功能。本文简单介绍下在 dotNET 5 中怎么样进行 Node.js 的调用以及怎样部署到 CentOS 和 Docker 容器中。&lt;/p&gt;
&lt;h2 id="环境"&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;dotNET ：5&lt;/li&gt;
&lt;li&gt;Node.js：14.17.4&lt;/li&gt;
&lt;li&gt;CentOS：7.6&lt;/li&gt;
&lt;li&gt;Docker：19.03.13&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dotnet-5-中的代码实现"&gt;dotNET 5 中的代码实现&lt;/h2&gt;
&lt;p&gt;1、在 VS 中创建 WebAPI 示例项目 nodejs-demo 项目，目标框架选择 .NET 5.0。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/20220202081223.webp" alt="iShot2022-02-02 08.12.23" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2、在项目中引入 NuGet 包：Microsoft.AspNetCore.NodeServices ,这里我使用的是 5.0 的预览版本。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202202020813752.webp" alt="iShot2022-02-02 08.13.07" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3、修改 Startup 类，在 ConfigureServices 方法中添加下面代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;services.AddNodeServices();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;4、在项目的根目录中创建一个名为 hello.js 的脚本文件，文件的属性中的「复制到输出目录」设置为「始终复制」，文件的内容如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;module.exports = function (callback, name) {
 var msg = &amp;#39;Hello,&amp;#39; + name;
 callback(null, msg);
};
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5、编写一个 API 接口方法：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[HttpGet]
public async Task&amp;lt;IActionResult&amp;gt; Get([FromServices] INodeServices nodeServices)
{
 var result = await nodeServices.InvokeAsync&amp;lt;string&amp;gt;(&amp;#34;hello.js&amp;#34;, &amp;#34;oec2003&amp;#34;);
 return Ok(result);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;6、如果正常运行，结果如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202202020813556.webp" alt="iShot2022-02-02 08.13.29" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="部署到-centos-中"&gt;部署到 CentOS 中&lt;/h2&gt;
&lt;p&gt;1、在 Node.js 的中文官网 (&lt;a href="http://nodejs.cn/download/current/"&gt;http://nodejs.cn/download/current/&lt;/a&gt;) 下载 Linux 二进制文件 (x64) 的安装包；&lt;/p&gt;
&lt;p&gt;2、将下载的安装包 node-v14.17.4-linux-x64.tar.xz 复制到 CentOS 系统的 root 目录中；&lt;/p&gt;
&lt;p&gt;3、执行命令 &lt;code&gt;tar -xvf node-v14.17.4-linux-x64.tar.xz&lt;/code&gt; 解压安装文件；&lt;/p&gt;
&lt;p&gt;4、执行命令 &lt;code&gt;mv node-v14.17.4-linux-x64 nodejs&lt;/code&gt; 将解压后的文件夹命名为 nodejs；&lt;/p&gt;</description></item><item><title>VS 2019 16.10 和 VS 2022 新功能</title><link>https://fwhyy.com/2021/06/vs-2019-16-10-and-vs-2022-new-features/</link><pubDate>Mon, 28 Jun 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/06/vs-2019-16-10-and-vs-2022-new-features/</guid><description>&lt;p&gt;作为宇宙第一 IDE 的 Visual Studio ，我从 VS2003 开始就一直都在使用，并关注着其发展动态，最近 Visual Studio 2022 的预览版已经可以下载，在 2022 版本之前，我使用的是 VS 2019，当你升级到 VS 2019 的 16.10 版本后，会发现新增了下面的一些新功能：&lt;/p&gt;</description></item><item><title>C#：8.0 &amp; 9.0 常用新特性</title><link>https://fwhyy.com/2021/04/c-8-9-common-new-features/</link><pubDate>Mon, 19 Apr 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/04/c-8-9-common-new-features/</guid><description>&lt;p&gt;在《&lt;a href="http://mp.weixin.qq.com/s?__biz=MzU0NjgzNzQyMw==&amp;amp;mid=2247483852&amp;amp;idx=1&amp;amp;sn=8a7fd3a21e0c174bb237d59d802131a9&amp;amp;chksm=fb56c70ccc214e1aaf4037521134d2f3a5cfe54dac1f0dd06b52cb53794379946ebfa7a25890&amp;amp;scene=21#wechat_redirect"&gt;带你了解C#每个版本新特性&lt;/a&gt;》 一文中介绍了，C# 1.0 到 7.0 的不同特性，本文接着介绍在 8.0 和 9.0 中的一些常用新特性。&lt;/p&gt;</description></item><item><title>CentOS 7 安装 Greenplum6 （附 dotNET Core 示例）</title><link>https://fwhyy.com/2021/04/centos7-install-greenplum6/</link><pubDate>Mon, 12 Apr 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/04/centos7-install-greenplum6/</guid><description>&lt;p&gt;Mysql 在面对大数据量的时候，还是表现有些吃力，所以产品中需要扩展能支持海量数据的数据库，这里选择的数据库为 Greenplum6 ，Greenplum 底层使用的是开源数据库 PostgreSQL 。本文会介绍怎样在 CentOS 7 中安装 Greenplum6，并使用 dotNET Core 程序进行连接访问。&lt;/p&gt;</description></item><item><title>Teleport 开源堡垒机的使用</title><link>https://fwhyy.com/2021/03/use-teleport/</link><pubDate>Mon, 08 Mar 2021 21:45:52 +0800</pubDate><guid>https://fwhyy.com/2021/03/use-teleport/</guid><description>&lt;p&gt;公司的服务器可能会存在这样一种情况，具体的应用是部署在很多的内网服务器上，然后由一台外网服务器通过代理的方式对外提供服务，例如下图：&lt;/p&gt;</description></item><item><title>GitLab 服务器的迁移以及注意点</title><link>https://fwhyy.com/2021/03/gitlab-server-migration-and-points-for-attention/</link><pubDate>Mon, 01 Mar 2021 22:05:08 +0800</pubDate><guid>https://fwhyy.com/2021/03/gitlab-server-migration-and-points-for-attention/</guid><description>&lt;p&gt;Git 已经是代码托管工具中的主流了，如果是自己搭建私有的 Git 服务器我们一般会使用 GitLab ，在《&lt;a href="http://mp.weixin.qq.com/s?__biz=MzU0NjgzNzQyMw==&amp;amp;mid=2247483693&amp;amp;idx=1&amp;amp;sn=c4e5ff320b4def07707387fc0b64794a&amp;amp;chksm=fb56c7edcc214efb5f0177d9b5fb0e368f2232f0086eb45f35efdce3011933d8bd9f712bde57&amp;amp;scene=21#wechat_redirect"&gt;在CentOS7中安装GitLab&lt;/a&gt;》 一文中有介绍怎样在 CentOS7 中安装 GitLab 。文本主要介绍怎样迁移 GtiLab 。&lt;/p&gt;</description></item><item><title>Nexus：一站式私有仓库管理（NuGet、Maven、NPM、Docker）</title><link>https://fwhyy.com/2021/03/nexus-manage/</link><pubDate>Mon, 01 Mar 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/03/nexus-manage/</guid><description>&lt;p&gt;我们在日常开发中经常需要使用到私有仓库，比如 dotNET 中的 NuGet、Java 中的 Maven、前端的 npm，还有 Docker 镜像，每一个私有仓库各自管理，维护起来比较麻烦，而 Nexus 可以将其统一起来。&lt;/p&gt;</description></item><item><title>dotNet Core 3.1 使用 Elasticsearch</title><link>https://fwhyy.com/2021/01/dotnet-core-3-uses-elasticsearch/</link><pubDate>Mon, 25 Jan 2021 09:36:06 +0800</pubDate><guid>https://fwhyy.com/2021/01/dotnet-core-3-uses-elasticsearch/</guid><description>&lt;p&gt;Elasticsearch 是基于 Lucene 的搜索引擎。可以非常方便地实现分布式的全文搜索，本文介绍在 dotNet Core 3.1 中怎样使用 Elasticsearch 。&lt;/p&gt;</description></item><item><title>说说 RabbiMQ 的应答模式</title><link>https://fwhyy.com/2021/01/talk-about-the-response-mode-of-rabbimq/</link><pubDate>Mon, 11 Jan 2021 08:08:40 +0800</pubDate><guid>https://fwhyy.com/2021/01/talk-about-the-response-mode-of-rabbimq/</guid><description>&lt;p&gt;RabbiMQ 我们都很熟悉了，是很常用的一个开源消息队列。搞懂 RabbiMQ 的应答模式对我们排查错误很有帮助，也能避免一些坑。本文说说 RabbiMQ 的应答模式。&lt;/p&gt;
&lt;p&gt;生产者发出一条消息给 RabbiMQ ，服务端将消息推送给消费者，消费者处理完消息后告诉 RabbiMQ，我已经接收到消息并处理了，RabbiMQ 收到通知后会将消息从队列中删除。 消费者通知 MQ 的这个过程就是消息的应答。在 RabbiMQ 中有两种应答模式：自动应答和手动应答。&lt;/p&gt;</description></item><item><title>CentOS7 中使用 Supervisor 部署 dotNET Core 程序</title><link>https://fwhyy.com/2020/12/deploying-dotnet-core-programs-with-supervisor-in-centos7/</link><pubDate>Mon, 28 Dec 2020 09:43:34 +0800</pubDate><guid>https://fwhyy.com/2020/12/deploying-dotnet-core-programs-with-supervisor-in-centos7/</guid><description>&lt;p&gt;在 CentOS 中部署 dotNET Core 程序，我们通常会使用 Docker ，方便快捷，版本更新也非常方便，但有时客户要求直接在服务器上进行 dotNET Core 程序的部署，这时就需要使用守护进程，本文就介绍使用守护进程 Supervisor 进行 dotNET Core 程序的部署。&lt;/p&gt;</description></item><item><title>一个端口搞定所有应用</title><link>https://fwhyy.com/2020/12/one-port-handles-all-applications/</link><pubDate>Mon, 14 Dec 2020 09:40:05 +0800</pubDate><guid>https://fwhyy.com/2020/12/one-port-handles-all-applications/</guid><description>&lt;p&gt;在产品或项目的发布部署中，往往需要很多的端口来对应不同的应用，特别是前后端分离的架构，更是如此，比如：有 PC 端的前端、移动端的前端和 WebAPI ，这就需要三个端口了：&lt;/p&gt;</description></item><item><title>C# ：异步编程的注意点</title><link>https://fwhyy.com/2020/12/csharp-points-for-attention-in-asynchronous-programming/</link><pubDate>Tue, 01 Dec 2020 09:29:36 +0800</pubDate><guid>https://fwhyy.com/2020/12/csharp-points-for-attention-in-asynchronous-programming/</guid><description>&lt;p&gt;在上一篇《C#：异步编程中的 async 和 await》 中简单介绍了在 C# 中的异步编程以及 async 和 await 编程模型，本文介绍下异步编程的注意事项，主要有以下几个方面。&lt;/p&gt;</description></item><item><title>C#：异步编程中的 async 和 await</title><link>https://fwhyy.com/2020/11/csharp-async-and-await-in-asynchronous-programming/</link><pubDate>Mon, 16 Nov 2020 09:59:19 +0800</pubDate><guid>https://fwhyy.com/2020/11/csharp-async-and-await-in-asynchronous-programming/</guid><description>&lt;p&gt;async 和 await 在 C# 5.0 就已经引入了，用来处理异步编程，但之前用的相对较少，现在在 dotNet Core 时代，已经使用的非常普遍，很多的开源组件中提供了大量的后缀为 Async （异步）的方法。本文就简单讲讲 async 和 await。&lt;/p&gt;</description></item><item><title>dotNet Core 3.1 使用 Aspose （部署 Docker）</title><link>https://fwhyy.com/2020/10/dotnet-core-3-1-uses-aspose-deploy-docker/</link><pubDate>Mon, 19 Oct 2020 07:48:55 +0800</pubDate><guid>https://fwhyy.com/2020/10/dotnet-core-3-1-uses-aspose-deploy-docker/</guid><description>&lt;p&gt;在之前的文章《Dotnet Core 中使用Aspose（部署Docker）》中介绍了在 dotNet Core2.1 中使用 Aspose ，并部署到 Docker 中，现在 dotNET Core 升级到了 3.1 ，Docker 镜像发生了变化，一些依赖的安装也有些变化。&lt;/p&gt;</description></item><item><title>dotNET Core：编码规范</title><link>https://fwhyy.com/2020/09/dotnet-core-coding-specification/</link><pubDate>Mon, 14 Sep 2020 09:44:15 +0800</pubDate><guid>https://fwhyy.com/2020/09/dotnet-core-coding-specification/</guid><description>&lt;p&gt;在项目开发过程中，由于时间紧、任务重，很容易导致面向功能编程。实现相同的功能，代码可以写的很优雅，也可以写的很晦涩和复杂。现在的工作，都需要进行团队协作，代码就需要有一定的规范进行指引，因为我们需要写出让人可以轻易读懂的代码，而不仅仅是机器。&lt;/p&gt;</description></item><item><title>dotNET：怎样处理程序中的异常（实战篇）？</title><link>https://fwhyy.com/2020/08/dotnet-how-to-handle-exceptions-in-programs-practical/</link><pubDate>Mon, 03 Aug 2020 17:38:52 +0800</pubDate><guid>https://fwhyy.com/2020/08/dotnet-how-to-handle-exceptions-in-programs-practical/</guid><description>&lt;p&gt;在上篇 《dotNET：怎样处理程序中的异常（理论篇）》 中讲了一些程序中出现异常怎样处理的理论知识，本文将以代码的方式来进行实践。&lt;/p&gt;</description></item><item><title>dotNET：怎样处理程序中的异常（理论篇）？</title><link>https://fwhyy.com/2020/07/dotnet-how-to-handle-exceptions-in-programs/</link><pubDate>Mon, 20 Jul 2020 17:36:05 +0800</pubDate><guid>https://fwhyy.com/2020/07/dotnet-how-to-handle-exceptions-in-programs/</guid><description>&lt;p&gt;平时在软件开发的过程中，首先是要保证功能可以正常运行，满足业务需求，除此之外，还需要考虑代码在异常的时候怎么处理，让程序能够健壮地运行。正确合理地处理异常可以减少程序的 Bug、保证代码质量，当然也不是一件很容易的事。&lt;/p&gt;</description></item><item><title>Nginx：rewrite 的几个技巧</title><link>https://fwhyy.com/2020/07/nginx-some-skills-of-rewriting/</link><pubDate>Mon, 06 Jul 2020 17:10:59 +0800</pubDate><guid>https://fwhyy.com/2020/07/nginx-some-skills-of-rewriting/</guid><description>&lt;p&gt;在软件的发布中，我们经常会使用到 Nginx，Nginx 的功能非常的庞杂，其中 rewrite 是一个非常常用的功能模块，本文介绍 rewrite 的基本概念和几个小技巧。&lt;/p&gt;</description></item><item><title>dotNET Core 3.X 使用 Autofac 来增强依赖注入</title><link>https://fwhyy.com/2020/06/dotnet-core-3-uses-autofac-to-enhance-dependency-injection/</link><pubDate>Mon, 08 Jun 2020 12:02:56 +0800</pubDate><guid>https://fwhyy.com/2020/06/dotnet-core-3-uses-autofac-to-enhance-dependency-injection/</guid><description>&lt;p&gt;在上一篇《dotNET Core 3.X 依赖注入》中简单介绍了 dotNET Core 框架本身的依赖注入功能，大部分情况下使用框架的依赖注入功能就可以满足了，在一些特殊场景下，我们就需要引入第三方的注入框架。&lt;/p&gt;</description></item><item><title>dotNET Core 3.X 依赖注入</title><link>https://fwhyy.com/2020/06/dotnet-core-3-dependency-injection/</link><pubDate>Mon, 01 Jun 2020 11:57:32 +0800</pubDate><guid>https://fwhyy.com/2020/06/dotnet-core-3-dependency-injection/</guid><description>&lt;p&gt;如果说在之前的 dotNET 版本中，依赖注入还是个比较新鲜的东西，那么在 dotNET Core 中已经是随处可见了，可以说整个 dotNET Core 的框架是构建在依赖注入框架之上。本文讲解下对 dotNET Core 中依赖注入的理解。&lt;/p&gt;</description></item><item><title>Jenkins 中以构建 Tag 来实现版本管理</title><link>https://fwhyy.com/2020/04/jenkins-implements-version-management-by-building-tags/</link><pubDate>Mon, 27 Apr 2020 11:44:33 +0800</pubDate><guid>https://fwhyy.com/2020/04/jenkins-implements-version-management-by-building-tags/</guid><description>&lt;p&gt;好的工具和流程能使我们事半功倍，而这个过程是不断迭代和演进的。关于这一块的内容，之前写过几篇文章：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mp.weixin.qq.com/s?__biz=MzU0NjgzNzQyMw==&amp;amp;mid=2247483697&amp;amp;idx=1&amp;amp;sn=5bb54ebc35bac60b141c8c982159cfdb&amp;amp;chksm=fb56c7f1cc214ee7c671f5a8ddfe50887803dd4a3c62f50f011fa009931622a9fe20ff69cd1b&amp;amp;scene=21#wechat_redirect"&gt;在团队中使用GitLab中的Merge Request工作模式&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mp.weixin.qq.com/s?__biz=MzU0NjgzNzQyMw==&amp;amp;mid=2247483790&amp;amp;idx=1&amp;amp;sn=32208bf396e3b4afc9fddb5dcc05a156&amp;amp;chksm=fb56c74ecc214e5811b06711094e1a83ba8bf0770baea06a8c6c420654b3d70536be711817f1&amp;amp;scene=21#wechat_redirect"&gt;敏捷下的需求和代码分支管理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mp.weixin.qq.com/s?__biz=MzU0NjgzNzQyMw==&amp;amp;mid=2247483844&amp;amp;idx=1&amp;amp;sn=b9abb7fe776b4a61fd639c979bc55c0c&amp;amp;chksm=fb56c704cc214e124a4d336a09334169a1bf524f876d525a4f959084f692a00ae33192b0b6d4&amp;amp;token=788167640&amp;amp;lang=zh_CN#rd"&gt;不断进化的分支和需求管理&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;现在又有了些新的变化和改进，之所以需要改进，肯定是遇到问题了，那么就先从问题来开始今天的文章。&lt;/p&gt;</description></item><item><title>dotNET Core 3.X 使用 Jwt 实现接口认证</title><link>https://fwhyy.com/2020/04/using-jwt-to-implement-interface-authentication-in-dotnet-core-3/</link><pubDate>Mon, 20 Apr 2020 07:19:13 +0800</pubDate><guid>https://fwhyy.com/2020/04/using-jwt-to-implement-interface-authentication-in-dotnet-core-3/</guid><description>&lt;p&gt;在前后端分离的架构中，前端需要通过 API 接口的方式获取数据，但 API 是无状态的，没有办法知道每次请求的身份，也就没有办法做权限的控制。如果不做控制，API 就对任何人敞开了大门，只要拿到了接口地址就可以进行调用，这是非常危险的。本文主要介绍下在 dotNET Core Web API 中使用 Jwt 来实现接口的认证。&lt;/p&gt;</description></item><item><title>dotNET Core 3.X 请求处理管道和中间件</title><link>https://fwhyy.com/2020/04/dotnet-core-3-request-processing-pipeline-and-middleware/</link><pubDate>Mon, 13 Apr 2020 07:07:22 +0800</pubDate><guid>https://fwhyy.com/2020/04/dotnet-core-3-request-processing-pipeline-and-middleware/</guid><description>&lt;p&gt;理解 dotNET Core 中的管道模型，对我们学习 dotNET Core 有很大的好处，能让我们知其然，也知其所以然，这样在使用第三方组件或者自己写一些扩展时，可以避免入坑，或者说避免同样的问题多次入坑。&lt;/p&gt;</description></item><item><title>dotNET Core 3.X 使用 Web API</title><link>https://fwhyy.com/2020/04/totnet-core-3-using-web-api/</link><pubDate>Wed, 01 Apr 2020 06:48:56 +0800</pubDate><guid>https://fwhyy.com/2020/04/totnet-core-3-using-web-api/</guid><description>&lt;p&gt;现在的 Web 开发大多都是前后端分离的方式，后端接口的正确使用显得尤为重要，本文讲下在 dotNET Core 3.X 下使用 Web API 。&lt;/p&gt;</description></item><item><title>CentOS7 安装 Jenkins（ 构建 Vue 和 dotNET Core ）</title><link>https://fwhyy.com/2020/02/centos7-install-jenkins/</link><pubDate>Tue, 04 Feb 2020 13:36:57 +0800</pubDate><guid>https://fwhyy.com/2020/02/centos7-install-jenkins/</guid><description>&lt;p&gt;之前的自动构建工具 Jenkins 是部署在公司内网的 Windows 服务器上，现在武汉处于非常时期，兄弟们都在家自我隔离，为了远程提交的代码能自动构建，需要在外网的 CentOS 服务器上搭建 Jenkins 环境来进行构建工作。&lt;/p&gt;</description></item><item><title>dotNET Core 中怎样操作AD（续1）</title><link>https://fwhyy.com/2020/01/how-to-operate-ad-in-dotnet-core-continued/</link><pubDate>Mon, 20 Jan 2020 07:40:14 +0800</pubDate><guid>https://fwhyy.com/2020/01/how-to-operate-ad-in-dotnet-core-continued/</guid><description>&lt;p&gt;在之前的文章《&lt;a href="http://fwhyy.com/2019/09/how-to-operate-ad-in-dotnet-core/"&gt;dotNET Core 中怎样操作 AD？&lt;/a&gt;》中主要以将AD的数据同步到数据库的场景来描述了在 dotNetCore 中怎样操作AD，本文将继续介绍一些在 dotNetCore 中操作 AD 的其他常用操作。&lt;/p&gt;</description></item><item><title>dotNetCore操作Redis（含CentOS7哨兵模式部署）</title><link>https://fwhyy.com/2020/01/dotnetcore-operation-redis/</link><pubDate>Wed, 08 Jan 2020 06:58:14 +0800</pubDate><guid>https://fwhyy.com/2020/01/dotnetcore-operation-redis/</guid><description>&lt;p&gt;现在说到使用缓存中间件基本就是 Redis 了，通常开发环境或测试环境部署一个单机版就可以运行了，但要上生产环境还需要进行高可用的方式来部署，本文说说在 CentOS7 中 Redis 高可用的部署以及在 dotNetCore 中怎样调用。&lt;/p&gt;</description></item><item><title>“兼职”运维的常用命令</title><link>https://fwhyy.com/2019/11/common-orders-for-part-time-operation-and-maintenance/</link><pubDate>Mon, 18 Nov 2019 23:49:54 +0800</pubDate><guid>https://fwhyy.com/2019/11/common-orders-for-part-time-operation-and-maintenance/</guid><description>&lt;p&gt;自从产品转到了 dotNET Core 之后，更深入的接触 Linux和 Docker ，而我每天的工作中，有一部分时间相当于在“兼职”做一些运维的事情。下面是一些在日常中常用的命令，算是个备忘吧。&lt;/p&gt;</description></item><item><title>使用RabbitMQ实现接口补偿</title><link>https://fwhyy.com/2019/10/using-rabbitmq-to-implement-interface-compensation/</link><pubDate>Fri, 11 Oct 2019 06:32:37 +0800</pubDate><guid>https://fwhyy.com/2019/10/using-rabbitmq-to-implement-interface-compensation/</guid><description>&lt;h2 id="业务背景"&gt;业务背景&lt;/h2&gt;
&lt;p&gt;在我们的日常开发中，经常需要调用第三方接口来进行数据传递，在调用接口的过程中，会因为各种原因导致调用的失败。这时我们希望能有一种机制实现对失败的接口的重复调用，并且能够实现人工干预。&lt;/p&gt;</description></item><item><title>dotNET Core 中怎样操作 AD？</title><link>https://fwhyy.com/2019/09/how-to-operate-ad-in-dotnet-core/</link><pubDate>Mon, 30 Sep 2019 22:18:21 +0800</pubDate><guid>https://fwhyy.com/2019/09/how-to-operate-ad-in-dotnet-core/</guid><description>&lt;p&gt;做企业应用开发难免会跟 AD 打交道，在之前的 dotNET FrameWork 时代，通常使用 System.DirectoryServices 的相关类来操作 AD ，在 dotNET Core 中没有这个命名空间，在张善友大佬的推荐下，知道了 Novell.Directory.Ldap。&lt;/p&gt;</description></item><item><title>dotNET Core实现分布式环境下的流水号唯一</title><link>https://fwhyy.com/2019/09/implementation-of-unique-pipeline-number-in-distributed-environment-by-dotnet-core/</link><pubDate>Sat, 14 Sep 2019 23:30:19 +0800</pubDate><guid>https://fwhyy.com/2019/09/implementation-of-unique-pipeline-number-in-distributed-environment-by-dotnet-core/</guid><description>&lt;h2 id="业务背景"&gt;业务背景&lt;/h2&gt;
&lt;p&gt;在管理系统中，很多功能模块都会涉及到各种类型的编号，例如：流程编号、订单号、合同编号等等。编号各有各自的规则，但通常有一个流水号来确定编号的唯一性，保证流水号的唯一，在不同的环境中实现方式有所不同。本文将介绍在单机和分布式环境中保证流水号唯一的方式。&lt;/p&gt;</description></item><item><title>.NET 程序员如何学习Vue</title><link>https://fwhyy.com/2019/08/net-programmer-how-to-learn-vue/</link><pubDate>Sat, 31 Aug 2019 16:32:05 +0800</pubDate><guid>https://fwhyy.com/2019/08/net-programmer-how-to-learn-vue/</guid><description>&lt;p&gt;之所以取这个标题，是因为本文来自内部培训的整理，培训的对象是公司的 .NET 程序员，.NET 程序员学习 Vue 是为了在项目中做二次开发时能够更好地跟产品对接。&lt;/p&gt;</description></item><item><title>dotNET Core WebAPI 统一处理（返回值、参数验证、异常）</title><link>https://fwhyy.com/2019/08/unified-processing-of-dotnet-core-web-api-return-value-parameter-validation-exception/</link><pubDate>Wed, 21 Aug 2019 06:28:27 +0800</pubDate><guid>https://fwhyy.com/2019/08/unified-processing-of-dotnet-core-web-api-return-value-parameter-validation-exception/</guid><description>&lt;p&gt;现在 Web 开发比较流行前后端分离，我们的产品也是一样，前端使用Vue，后端使用 dotNet Core WebAPI ，在写 API 的过程中有很多地方需要统一处理：&lt;/p&gt;</description></item><item><title>端到端测试实践：Jenkins集成TestCafe</title><link>https://fwhyy.com/2019/07/jenkins-and-testcafe/</link><pubDate>Mon, 08 Jul 2019 07:00:15 +0800</pubDate><guid>https://fwhyy.com/2019/07/jenkins-and-testcafe/</guid><description>&lt;p&gt;上一篇《&lt;a href="http://fwhyy.com/2019/07/some-thoughts-on-product-quality/"&gt;对产品质量的一点思考&lt;/a&gt;》中说到自动化测试的重要性，本文简单介绍下怎样在实际项目中实现端到端测试的自动化，在这里我们使用的端到端测试工具是TestCafe。&lt;/p&gt;
&lt;h2 id="环境"&gt;环境&lt;/h2&gt;
&lt;p&gt;Jenkisn：2.183
TestCafe：1.3.0&lt;/p&gt;
&lt;h2 id="为什么采用testcafe做自动化测试"&gt;为什么采用TestCafe做自动化测试&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;前端Vue或是netCore要添加单元测试相对较复杂，需要一定的时间来沉淀，不能解燃眉之急&lt;/li&gt;
&lt;li&gt;经常会因为代码重构、代码合并等原因造成原本正常的功能出现问题，而这些问题在手动测试时不容易覆盖到&lt;/li&gt;
&lt;li&gt;TestCafe足够简单，只要使用过jQuery，基本可以几分钟上手&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="要实现的目标"&gt;要实现的目标&lt;/h2&gt;
&lt;p&gt;目前前端代码通过GitLab来进行管理，采用Merge Request的开发模式，开发人员的代码被合并到master后，Jenkins会自动构建到测试环境，希望自动化测试能做到下面两点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;能在前端项目构建完成后自动执行TestCafe脚本进行测试&lt;/li&gt;
&lt;li&gt;能提供测试的完整结果&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="步骤"&gt;步骤&lt;/h2&gt;
&lt;p&gt;1、在Jenkins中新创建一个新的项目&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201280613334.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Git中配置的测试的代码地址&lt;code&gt;https://github.com/oec2003/testcafe-ci-demo.git&lt;/code&gt;是我fork的官网的一个例子,原项目地址为：&lt;code&gt;https://github.com/DevExpress-Examples/testcafe-ci-demo.git&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;2、增加构建步骤，选择执行Windows批处理命令&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201280614319.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201280614096.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;D:\Jenkins\Testcafe\node_modules\.bin\testcafe path:C:\Users\oec2003\AppData\Local\Google\Chrome\Application\chrome.exe tests/**/* -r xunit:res.xml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面执行的命令分为三个部分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;testcafe的执行程序&lt;/li&gt;
&lt;li&gt;测试的浏览器的路径，此处为chrome的路径，这里有一个小坑，直接执行命令时是可以使用chrome或ie来选择测试浏览器的，但配置在Jenkins中如果直接写chrome或ie会报异常，所以写了chrome执行程序的全路径&lt;/li&gt;
&lt;li&gt;将结果输出到xunit的xml文件中&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;要想使用xunit，需要先使用下面命令进行安装&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;npm install testcafe testcafe-reporter-xunit
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;3、添加构建后操作，选择Publish JUnit test result report&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201280614661.webp" alt="" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201280614568.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;4、修改Jenkins中现有的前端项目的配置，增加构建后操作步骤，选择构建起他工程&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201280615176.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;选择第一步创建的测试项目即可。&lt;/p&gt;
&lt;p&gt;5、实际测试结果如下，所有测试用例的通过情况以列表形式展现，点击可以看详细信息&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201280615015.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Testcafe非常简单，有一定开发经验的程序员，可以在很短的时间内达到熟练的程度&lt;/li&gt;
&lt;li&gt;Testcafe虽然简单，但怎样去设置场景覆盖，让所有业务没有遗漏，这才是比较困难的，是我们需要着重思考的&lt;/li&gt;
&lt;li&gt;前端代码如果做了修改，特别是UI层面做了调整，测试代码需要同步修改&lt;/li&gt;
&lt;li&gt;只要能够持续下去，先从容易出错的模块开始，积少成多，软件质量的最后一道防线一定能守住&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>带你了解C#每个版本新特性</title><link>https://fwhyy.com/2019/06/learn-about-the-new-features-of-each-version-of-csharp/</link><pubDate>Sun, 16 Jun 2019 14:19:33 +0800</pubDate><guid>https://fwhyy.com/2019/06/learn-about-the-new-features-of-each-version-of-csharp/</guid><description>&lt;p&gt;上学时学习C#和.NET，当时网上的资源不像现在这样丰富，所以去电脑城买了张盗版的VS2005的光盘，安装时才发现是VS2003，当时有一种被坑的感觉，但也正是如此，让我有了一个完整的.NET的学习生涯。&lt;/p&gt;</description></item><item><title>不断进化的分支和需求管理</title><link>https://fwhyy.com/2019/06/evolutionary-branch-and-demand-management/</link><pubDate>Fri, 07 Jun 2019 09:22:10 +0800</pubDate><guid>https://fwhyy.com/2019/06/evolutionary-branch-and-demand-management/</guid><description>&lt;p&gt;昨天有朋友在公众号私信问我几个关于代码分支管理的问题，这几个问题是我去年写的《在团队中使用GitLab中的Merge Request工作模式》一文结尾时抛出的几个问题：&lt;/p&gt;</description></item><item><title>发布dotNetCore程序到Kubernetes</title><link>https://fwhyy.com/2019/05/publish-dotnetcore-program-to-kubernetes/</link><pubDate>Sun, 12 May 2019 11:02:54 +0800</pubDate><guid>https://fwhyy.com/2019/05/publish-dotnetcore-program-to-kubernetes/</guid><description>&lt;p&gt;上一篇《&lt;a href="http://fwhyy.com/2019/05/building-kubernetes-in-mac/"&gt;Mac中搭建Kubernetes&lt;/a&gt;》介绍了怎样在Mac中搭建单节点的&lt;code&gt;Kubernetes&lt;/code&gt;，本文将编写一个&lt;code&gt;dotNetCore&lt;/code&gt;的示例程序，并发布到&lt;code&gt;Kubernetes&lt;/code&gt;中。&lt;/p&gt;</description></item><item><title>Mac中搭建Kubernetes</title><link>https://fwhyy.com/2019/05/building-kubernetes-in-mac/</link><pubDate>Fri, 03 May 2019 22:33:22 +0800</pubDate><guid>https://fwhyy.com/2019/05/building-kubernetes-in-mac/</guid><description>&lt;p&gt;&lt;code&gt;Kubernetes&lt;/code&gt;是&lt;code&gt;Google&lt;/code&gt;和&lt;code&gt;RadHat&lt;/code&gt;公司共同主导的开源容器编排项目，功能非常强大，也非常的火热和流行，但同时里面也有很多的概念和名词需要我们去学习和理解。学习任何一个技术先需要把基础环境搭建起来，本篇就介绍怎样在&lt;code&gt;Mac&lt;/code&gt;中启动单节点的&lt;code&gt;Kubernetes&lt;/code&gt;。&lt;/p&gt;</description></item><item><title>敏捷下的需求和代码分支管理</title><link>https://fwhyy.com/2019/03/requirements-and-code-branch-management-in-agile/</link><pubDate>Sun, 17 Mar 2019 13:54:04 +0800</pubDate><guid>https://fwhyy.com/2019/03/requirements-and-code-branch-management-in-agile/</guid><description>&lt;p&gt;在去年的一篇文章《在团队中使用GitLab中的Merge Request工作模式》中简单介绍了下&lt;code&gt;Git&lt;/code&gt;的几种模式和在团队中使用的&lt;code&gt;Merge Request&lt;/code&gt;的模式。文章的结尾也抛出了几个问题：&lt;/p&gt;</description></item><item><title>敏捷，每个人都有自己的理解</title><link>https://fwhyy.com/2019/02/agile-everyone-has-his-own-understanding/</link><pubDate>Sat, 23 Feb 2019 23:53:05 +0800</pubDate><guid>https://fwhyy.com/2019/02/agile-everyone-has-his-own-understanding/</guid><description>&lt;p&gt;2018年一直在尝试用敏捷的方式来管理团队，但执行的不够彻底，或者说不那么敏捷。 总结下来有下面一些问题：&lt;/p&gt;</description></item><item><title>Office转PDF，Aspose太贵，怎么办</title><link>https://fwhyy.com/2019/01/office-to-pdf-aspose-is-too-expensive-how-to-do/</link><pubDate>Sun, 13 Jan 2019 13:48:21 +0800</pubDate><guid>https://fwhyy.com/2019/01/office-to-pdf-aspose-is-too-expensive-how-to-do/</guid><description>&lt;p&gt;在程序开发中经常需要将&lt;code&gt;Office&lt;/code&gt;文件转换成&lt;code&gt;PDF&lt;/code&gt;，著名的&lt;code&gt;Aspose&lt;/code&gt;的三大组件可以很容易完成这个功能，但是&lt;code&gt;Aspose&lt;/code&gt;的每个组件都单独收费，而且每个都卖的不便宜。在老大的提示下，换了一种思路来解决这个问题。&lt;/p&gt;</description></item><item><title>dotNET Core中使用Aspose（部署Docker）</title><link>https://fwhyy.com/2018/11/using-aspose-in-dotnet-core/</link><pubDate>Thu, 22 Nov 2018 23:07:45 +0800</pubDate><guid>https://fwhyy.com/2018/11/using-aspose-in-dotnet-core/</guid><description>&lt;p&gt;在&lt;code&gt;dotnet&lt;/code&gt;下处理过&lt;code&gt;Office&lt;/code&gt;文档的相信对&lt;code&gt;Aspose&lt;/code&gt;都不陌生，&lt;code&gt;Aspose&lt;/code&gt;下面的三大组件：&lt;code&gt;Aspose.Cells&lt;/code&gt;、&lt;code&gt;Aspose.Slides&lt;/code&gt;、&lt;code&gt;Aspose.Words&lt;/code&gt;可以让我们很方便的操作&lt;code&gt;Office&lt;/code&gt;文档，或者将&lt;code&gt;Office&lt;/code&gt;导出为&lt;code&gt;PDF&lt;/code&gt;。&lt;/p&gt;</description></item><item><title>免费的东西最贵</title><link>https://fwhyy.com/2018/10/the-most-expensive-thing-is-free/</link><pubDate>Wed, 24 Oct 2018 00:30:19 +0800</pubDate><guid>https://fwhyy.com/2018/10/the-most-expensive-thing-is-free/</guid><description>&lt;p&gt;国庆期间，收到七牛的测试域名回收邮件，没细看也没怎么在意，因为我仅仅只是拿七牛的对象存储作为我博客的图床而已，但这两天发现我博客中的图片地址全部失效了，进入到七牛的管理后台，在对应的&lt;code&gt;bucket&lt;/code&gt;中图片已经不能预览和下载了。&lt;/p&gt;</description></item><item><title>dotNET Core：配置</title><link>https://fwhyy.com/2018/08/dotnet-core-configure/</link><pubDate>Sun, 12 Aug 2018 22:13:39 +0800</pubDate><guid>https://fwhyy.com/2018/08/dotnet-core-configure/</guid><description>&lt;p&gt;在&lt;code&gt;dotNET Core&lt;/code&gt;中默认情况下没有了之前版本的&lt;code&gt;App.config&lt;/code&gt;和&lt;code&gt;Web.Config&lt;/code&gt;文件，换成了新的&lt;code&gt;json&lt;/code&gt;格式的配置文件。当然，如果想使用之前的方式也是可以的。下面说说在&lt;code&gt;dotNET Core&lt;/code&gt;中各种使用配置的方法。&lt;/p&gt;
&lt;h2 id="环境"&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;操作系统：macOS 10.13.5&lt;/li&gt;
&lt;li&gt;dotNET Core：2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="使用原来的config文件"&gt;使用原来的config文件&lt;/h2&gt;
&lt;p&gt;如果你还念旧，想使用之前的&lt;code&gt;App.config&lt;/code&gt;或&lt;code&gt;Web.config&lt;/code&gt;，可以导入&lt;code&gt;System.Configuration.ConfigurationManager&lt;/code&gt;包，使用方式和之前一样。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201270825835.webp" alt="-w788" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;using System.Configuration;
...
static void Main(string[] args)
{
 var connection = ConfigurationManager.ConnectionStrings[&amp;#34;ConnectionStr&amp;#34;].ConnectionString;
 var mqHostName = ConfigurationManager.AppSettings[&amp;#34;MQHostName&amp;#34;];
 Console.WriteLine($&amp;#34;connection:{connection}&amp;#34;);
 Console.WriteLine($&amp;#34;mqHostName:{mqHostName}&amp;#34;);
 Console.ReadLine();
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="命令行配置"&gt;命令行配置&lt;/h2&gt;
&lt;p&gt;1、创建一个控制台的应用程序&lt;code&gt;NetCoreConfigDemo&lt;/code&gt;；
2、导入依赖包，可以按需导入，也可以直接导入&lt;code&gt;Microsoft.AspNetCore&lt;/code&gt;的包，里面包含所有依赖的项；&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201270825585.webp" alt="-w1001" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3、添加&lt;code&gt;using Microsoft.Extensions.Configuration;&lt;/code&gt;引用；
4、代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;using System;
using Microsoft.Extensions.Configuration;
namespace NetCoreConfigDemo
{
 class Program
 {
 static void Main(string[] args)
 {
 var builder = new ConfigurationBuilder()
 .AddCommandLine(args);
 var configration = builder.Build();
 Console.WriteLine($&amp;#34;name:{configration[&amp;#34;name&amp;#34;]}&amp;#34;);
 Console.ReadLine();
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5、运行时指定&lt;code&gt;name&lt;/code&gt;参数，在命令行中可以正常打印出来&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201270827596.webp" alt="-w676" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;上面例子中的参数&lt;code&gt;name&lt;/code&gt;是在启动程序是指定的，如果想要程序有一个默认的参数值，可以在程序中初始化一个字典类&lt;code&gt;Dictionary&lt;/code&gt;，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;using System;
using Microsoft.Extensions.Configuration;
using System.Collections.Generic;
namespace NetCoreConfigDemo
{
 class Program
 {
 static void Main(string[] args)
 {
 var dic = new Dictionary&amp;lt;string, string&amp;gt;() { { &amp;#34;name&amp;#34;, &amp;#34;oec2003&amp;#34; } };
 var builder = new ConfigurationBuilder()
 .AddInMemoryCollection(dic)
 .AddCommandLine(args);
 var configration = builder.Build();
 Console.WriteLine($&amp;#34;name:{configration[&amp;#34;name&amp;#34;]}&amp;#34;);
 Console.ReadLine();
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;注意：&lt;code&gt;AddInMemoryCollection&lt;/code&gt;必须放在&lt;code&gt;AddCommandLine&lt;/code&gt;的前面，否则默认值会覆盖掉在外部指定的参数值。&lt;/p&gt;</description></item><item><title>修改VS Code背景色</title><link>https://fwhyy.com/2018/07/modify-the-background-color-of-vs-code/</link><pubDate>Sat, 21 Jul 2018 23:04:03 +0800</pubDate><guid>https://fwhyy.com/2018/07/modify-the-background-color-of-vs-code/</guid><description>&lt;p&gt;一直以来都是在&lt;code&gt;Windows&lt;/code&gt;下进行开发，VS自定义的字体和背景色已经跟了我十来年了，最近已渐渐不使用&lt;code&gt;Mac&lt;/code&gt;下的&lt;code&gt;Windows&lt;/code&gt;虚拟机了，主力开发工具就变成了&lt;code&gt;VS Code For Mac&lt;/code&gt;和&lt;code&gt;Visual Studio For Mac&lt;/code&gt;。没有了之前的背景色还真不习惯，下面介绍怎样修改&lt;code&gt;Mac&lt;/code&gt;下的&lt;code&gt;VS Code&lt;/code&gt;和&lt;code&gt;VS&lt;/code&gt;的背景色。&lt;/p&gt;</description></item><item><title>GitLab配合Jenkins打造自动化部署</title><link>https://fwhyy.com/2018/07/gitlab-combined-with-jenkins-to-build-automated-deployment/</link><pubDate>Sat, 14 Jul 2018 11:20:31 +0800</pubDate><guid>https://fwhyy.com/2018/07/gitlab-combined-with-jenkins-to-build-automated-deployment/</guid><description>&lt;p&gt;&lt;code&gt;GitLab&lt;/code&gt;有&lt;code&gt;CI&lt;/code&gt;和&lt;code&gt;CD&lt;/code&gt;功能模块，但我对&lt;code&gt;Jenkins&lt;/code&gt;更熟悉些，所以先使用&lt;code&gt;Jenkins&lt;/code&gt;将自动发布搭建起来，后面再继续研究&lt;code&gt;GitLab&lt;/code&gt;的&lt;code&gt;CI&lt;/code&gt;和&lt;code&gt;CD&lt;/code&gt;功能。&lt;/p&gt;</description></item><item><title>Docker 常用命令</title><link>https://fwhyy.com/2018/06/docker-common-commands/</link><pubDate>Sat, 09 Jun 2018 07:49:07 +0800</pubDate><guid>https://fwhyy.com/2018/06/docker-common-commands/</guid><description>&lt;p&gt;学习&lt;code&gt;Docker&lt;/code&gt;有段时间了，所有的操作都是在命令行下，如果不是每天都在使用，很容易忘记命令。本文将以学习&lt;code&gt;Docker&lt;/code&gt;的角度，从前到后，将一些常用的&lt;code&gt;Docker&lt;/code&gt;命令记录下来，算是个备忘。&lt;/p&gt;</description></item><item><title>在团队中使用GitLab中的Merge Request工作模式</title><link>https://fwhyy.com/2018/06/use-the-merge-request-working-mode-in-gitlab-in-the-team/</link><pubDate>Fri, 01 Jun 2018 07:49:45 +0800</pubDate><guid>https://fwhyy.com/2018/06/use-the-merge-request-working-mode-in-gitlab-in-the-team/</guid><description>&lt;p&gt;在工作中使用&lt;code&gt;Git&lt;/code&gt;已有5年多的时间了，&lt;code&gt;Git&lt;/code&gt;分布式的工作机制以及强大的分支功能使得在团队中推广使用没有受到什么阻碍。一直以来都是采用的分支管理模式，我把项目的开发分为三个阶段：开发、测试和上线。&lt;/p&gt;</description></item><item><title>CentOS7安装GitLab</title><link>https://fwhyy.com/2018/05/centos7-install-gitlab/</link><pubDate>Sun, 27 May 2018 22:18:21 +0800</pubDate><guid>https://fwhyy.com/2018/05/centos7-install-gitlab/</guid><description>&lt;p&gt;一直以来源代码一直都放在码云上，但最近码云开始收费了，免费版本的私有项目的成员限制在5个，这远远不够用了。所以需要搭建自己的Git服务器，下面内容为安装经过，记录一下：&lt;/p&gt;</description></item><item><title>Docker安装MySql-挂载外部数据和配置</title><link>https://fwhyy.com/2018/05/docker-installs-mysql-to-mount-external-data-and-configuration/</link><pubDate>Sun, 20 May 2018 09:18:37 +0800</pubDate><guid>https://fwhyy.com/2018/05/docker-installs-mysql-to-mount-external-data-and-configuration/</guid><description>&lt;p&gt;在上一篇中《&lt;a href="http://fwhyy.com/2018/04/Install-MySql-with-Docker-in-CentOS7/"&gt;在CentOS7中使用Docker安装MySql&lt;/a&gt;》中介绍了怎样在&lt;code&gt;Docker&lt;/code&gt;中安装&lt;code&gt;Mysql&lt;/code&gt;，但存在两个问题：&lt;/p&gt;
&lt;p&gt;1、用户密码和字符集等的设置，需要安装完&lt;code&gt;MySql&lt;/code&gt;后，进入到&lt;code&gt;MySql&lt;/code&gt;中去设置，非常麻烦；
2、配置文件和数据文件都在&lt;code&gt;MySql&lt;/code&gt;的容器内，不是很安全。&lt;/p&gt;
&lt;p&gt;本文将介绍怎样在创建容器时通过参数的配置来解决上面两个问题。&lt;/p&gt;
&lt;h2 id="环境"&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;CentOS：7.4&lt;/li&gt;
&lt;li&gt;Docker：1.13.1&lt;/li&gt;
&lt;li&gt;MySql：8.0.11&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="设置环境变量"&gt;设置环境变量&lt;/h2&gt;
&lt;p&gt;设置环境变量和镜像的参数，可以来解决第一个问题，环境变量使用&lt;code&gt;-e&lt;/code&gt;的方式设置在镜像名称的前面；镜像的参数需要配置在镜像名称的后面&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;docker run -d -p 4306:3306
-e MYSQL_USER=&amp;#34;fengwei&amp;#34;
-e MYSQL_PASSWORD=&amp;#34;pwd123&amp;#34;
-e MYSQL_ROOT_PASSWORD=&amp;#34;rootpwd123&amp;#34;
--name mysql001
mysql/mysql-server
--character-set-server=utf8
--collation-server=utf8_general_ci
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;环境变量说明：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;-e MYSQL_USER=&amp;ldquo;fengwei&amp;rdquo;：添加用户fengwei
-e MYSQL_PASSWORD=&amp;ldquo;pwd123&amp;rdquo;：设置fengwei的密码伟pwd123
-e MYSQL_ROOT_PASSWORD=&amp;ldquo;rootpwd123&amp;rdquo;：设置root的密码伟rootpwd123&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;镜像参数说明：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ndash;character-set-server=utf8：设置字符集为utf8
&amp;ndash;collation-server=utf8_general_ci：设置字符比较规则为utf8_general_ci&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;使用&lt;code&gt;SQLyog&lt;/code&gt;进行测试，用户名和密码使用上面环境变量中添加的用户&lt;code&gt;fengwei&lt;/code&gt;和密码&lt;code&gt;pwd123&lt;/code&gt;，出现下图的错误&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201260826693.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;执行命令进入到容器中的&lt;code&gt;MySql&lt;/code&gt;中，执行下面的&lt;code&gt;Sql&lt;/code&gt;语句&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ALTER USER &amp;#39;fengwei&amp;#39;@&amp;#39;%&amp;#39; IDENTIFIED WITH mysql_native_password BY &amp;#39;password123&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;再用&lt;code&gt;SQLyog&lt;/code&gt;测试，连接成功&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201260826414.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;上面连接不成功的问题也可以添加镜像参数&lt;code&gt;--default-authentication-plugin=mysql_native_password&lt;/code&gt;来解决，完整命令如下&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;docker run -d -p 4306:3306 
-e MYSQL_USER=&amp;#34;fengwei&amp;#34; 
-e MYSQL_PASSWORD=&amp;#34;pwd123&amp;#34; 
-e MYSQL_ROOT_PASSWORD=&amp;#34;rootpwd123&amp;#34; 
--name mysql001 
mysql/mysql-server 
--character-set-server=utf8 
--collation-server=utf8_general_ci 
--default-authentication-plugin=mysql_native_password 
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="数据和配置挂载到宿主机"&gt;数据和配置挂载到宿主机&lt;/h2&gt;
&lt;p&gt;为了安全性，我们应该将数据和配置放到宿主机中，首先执行下面的命令创建&lt;code&gt;data&lt;/code&gt;目录和&lt;code&gt;config&lt;/code&gt;目录&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;mkdir mysqltest
cd mysqltest
mkdir data
mkdir config
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;执行下面命令进入到&lt;code&gt;config&lt;/code&gt;目录中，并在该目录中创建&lt;code&gt;my.cnf&lt;/code&gt;配置文件&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cd config
touch my.cnf
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;my.cnf&lt;/code&gt;配置文件内容如下&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;执行下面命令创建容器&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;docker run -d -p 4306:3306 
--restart always 
--privileged=true
--name mysql001
-e MYSQL_USER=&amp;#34;fengwei&amp;#34; 
-e MYSQL_PASSWORD=&amp;#34;pwd123&amp;#34; 
-e MYSQL_ROOT_PASSWORD=&amp;#34;rootpwd123&amp;#34;
-v=/mysqltest/config/my.cnf:/etc/my.cnf 
-v=/mysqltest/data:/var/lib/mysql 
mysql/mysql-server
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;参数说明&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ndash;restart always：开机启动
&amp;ndash;privileged=true：提升容器内权限
-v=/mysqltest/config/my.cnf:/etc/my.cnf：映射配置文件
-v=/mysqltest/data:/var/lib/mysql：映射数据目录&lt;/p&gt;</description></item><item><title>在CentOS7中使用Docker安装MySql</title><link>https://fwhyy.com/2018/05/install-mysql-with-docker-in-centos7/</link><pubDate>Fri, 18 May 2018 22:31:14 +0800</pubDate><guid>https://fwhyy.com/2018/05/install-mysql-with-docker-in-centos7/</guid><description>&lt;h2 id="环境"&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;CentOS：7.4&lt;/li&gt;
&lt;li&gt;Docker: 1.13.1&lt;/li&gt;
&lt;li&gt;MySql: 8.0.11&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>调用API修改Ocelot的配置文件</title><link>https://fwhyy.com/2018/05/call-api-to-modify-the-configuration-file-of-the-ocelot/</link><pubDate>Wed, 16 May 2018 00:19:38 +0800</pubDate><guid>https://fwhyy.com/2018/05/call-api-to-modify-the-configuration-file-of-the-ocelot/</guid><description>&lt;p&gt;Ocelot是一个基于.net core的开源webapi服务网关开源项目，功能比较强大，Github项目地址为：&lt;a href="https://github.com/ThreeMammals/Ocelot"&gt;https://github.com/ThreeMammals/Ocelot&lt;/a&gt;，关于Ocelot的学习资料可以看看张善友的网站：&lt;a href="http://www.csharpkit.com/apigateway.html"&gt;http://www.csharpkit.com/apigateway.html&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;Ocelot的路由设置是基于配置文件的，同样在Ocelot中使用Consul做服务发现时，也是基于配置文件，当我们修改路由或者需要往Consul中添加ServiceName的时候，需要修改配置文件，网关服务也需要重启，这当然不是我们想要的。&lt;/p&gt;</description></item><item><title>MongoDB历险记</title><link>https://fwhyy.com/2017/10/the-adventures-of-mongodb/</link><pubDate>Tue, 24 Oct 2017 23:56:57 +0800</pubDate><guid>https://fwhyy.com/2017/10/the-adventures-of-mongodb/</guid><description>&lt;p&gt;一直在使用&lt;code&gt;MongoDB&lt;/code&gt;来做为底层的数据存储，一直也没有出现什么问题。但就在&lt;code&gt;MongoDB&lt;/code&gt;上市之际，一客户的&lt;code&gt;MongoDB&lt;/code&gt;挂了,原因很复杂，大概有下面的一些原因和操作：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;客户的存储做过迁移；&lt;/li&gt;
&lt;li&gt;服务器打补丁做过重启；&lt;/li&gt;
&lt;li&gt;服务器重启后其中有一台的存储盘丢失；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MongoDB&lt;/code&gt;的所有服务都恢复后，在一个很短的时间内是正常的，测试在这期间做过&lt;code&gt;Web&lt;/code&gt;端和&lt;code&gt;PC&lt;/code&gt;客户端端测试；&lt;/li&gt;
&lt;li&gt;当测试通知文件不能上传时，发现一台服务器端&lt;code&gt;MongoDB&lt;/code&gt;服务不能正常启动，紧接着另一台也不能正常启动；&lt;/li&gt;
&lt;li&gt;此时&lt;code&gt;MongoDB&lt;/code&gt;已彻底瘫痪。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上面就是整个事故的经过，发生在周六的夜里九十点钟，接下来就是长达一天一夜的修复工作。&lt;/p&gt;</description></item><item><title>Angular4跨域问题解决</title><link>https://fwhyy.com/2017/09/angular-four-cross-domain-problem-solving/</link><pubDate>Mon, 11 Sep 2017 23:56:42 +0800</pubDate><guid>https://fwhyy.com/2017/09/angular-four-cross-domain-problem-solving/</guid><description>&lt;p&gt;之前在使用Angular1.x的时候就碰到过跨域的问题，在博文《&lt;a href="http://fwhyy.com/2016/01/angularjs-cross-domain-call-webapi-asp-net/"&gt;Angularjs跨域调用Asp.Net WebAPI&lt;/a&gt;》中有做过介绍。本文介绍下在Angular4中解决跨域问题的两种方法。&lt;/p&gt;</description></item><item><title>在Mac的Docker中运行DotNetCore2.0</title><link>https://fwhyy.com/2017/09/run-netcore-two-in-mac-docker/</link><pubDate>Sat, 09 Sep 2017 23:37:32 +0800</pubDate><guid>https://fwhyy.com/2017/09/run-netcore-two-in-mac-docker/</guid><description>&lt;p&gt;最近学习&lt;code&gt;Angular4&lt;/code&gt;，服务端准备使用&lt;code&gt;DotNetCore API&lt;/code&gt;来实现，本文简单介绍下在&lt;code&gt;Mac&lt;/code&gt;中怎样将&lt;code&gt;DotNetCore&lt;/code&gt;程序部署在&lt;code&gt;Docker&lt;/code&gt;中，并使用&lt;code&gt;Nginx&lt;/code&gt;做反向代理让程序可以跑起来。&lt;/p&gt;
&lt;h2 id="具体步骤如下"&gt;具体步骤如下&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;安装&lt;code&gt;Docker&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;拉取&lt;code&gt;DotNetCore&lt;/code&gt;镜像&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;VS For Mac&lt;/code&gt;创建&lt;code&gt;DotNetCore&lt;/code&gt;应用&lt;/li&gt;
&lt;li&gt;发布应用到&lt;code&gt;Docker&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;安装&lt;code&gt;Nginx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;配置&lt;code&gt;Nginx&lt;/code&gt;代理&lt;code&gt;Docker&lt;/code&gt;中的&lt;code&gt;DotNetCore&lt;/code&gt;应用&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>C#中实现小米推送</title><link>https://fwhyy.com/2017/09/mi-push-to-csharp/</link><pubDate>Sat, 02 Sep 2017 09:35:44 +0800</pubDate><guid>https://fwhyy.com/2017/09/mi-push-to-csharp/</guid><description>&lt;p&gt;移动端的消息推送有很多互联网产品可以用，例如：极光、个推、小米推送等。对于安卓手机，推送需要做各种适配，开始我们使用的是极光，发现在小米手机上，当App退出到后台，就经常不能收到消息，所以决定将小米推送集成到App中。&lt;/p&gt;
&lt;p&gt;遗憾的是小米推送官方并不支持C#，所以需要很对Java版本的实现用IKVM来做一些转化。转换后在Net程序中一共需要引用7个Dll文件，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300725027.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;相关Dll文件和示例代码已经放在Github上了&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[https://github.com/oec2003/MIPushCSharpSample](https://github.com/oec2003/MIPushCSharpSample)
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="服务器证书问题解决"&gt;服务器证书问题解决&lt;/h2&gt;
&lt;p&gt;在测试阶段，推送一直没什么问题，当部署到客户服务器上后，就推送失败，错误日志如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300725876.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;从错误信息可以得知是在验证证书时出的问题，网上查到很多都是Java版本的解决方式，思路就是忽略SSL的验证，找了下C#的相关代码，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300725838.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;上面代码加上后，发现推送就正常了。上面红框代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) =&amp;gt; true;
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Docker学习-安装镜像</title><link>https://fwhyy.com/2017/08/docker-learning-installing-images/</link><pubDate>Thu, 31 Aug 2017 10:47:45 +0800</pubDate><guid>https://fwhyy.com/2017/08/docker-learning-installing-images/</guid><description>&lt;p&gt;Docker现在已不是什么新鲜事物了，Windows Server2016已经内置了Docker，对于我来说，我只想让Docker来帮我解决运行环境的问题。&lt;/p&gt;
&lt;p&gt;我们的产品部署起来会依赖很多的第三方产品：SqlServer、MongoDB、Redis、RabbitMQ等，各种软件等安装，数据库的还原，每次部署都会耗费大量的时间。为了能使部署更加的方便，我们的设想是这样的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在Docker中安装这些工具软件&lt;/li&gt;
&lt;li&gt;打包Docker，拷贝到客户环境中导入&lt;/li&gt;
&lt;li&gt;在Web界面中进行简单的向导配置&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本文主要介绍在Docker中安装这些工具软件。&lt;/p&gt;</description></item><item><title>OWA实现添加水印</title><link>https://fwhyy.com/2017/04/adding-watermark-to-owa/</link><pubDate>Sat, 08 Apr 2017 00:01:55 +0800</pubDate><guid>https://fwhyy.com/2017/04/adding-watermark-to-owa/</guid><description>&lt;p&gt;&lt;code&gt;OWA&lt;/code&gt;全称&lt;code&gt;Office Web App&lt;/code&gt;，是用来做&lt;code&gt;Office&lt;/code&gt;文档预览的一个很好的工具。现在客户有要求，需要在预览界面中添加水印。想起之前写的一篇文章&lt;a href="http://fwhyy.com/2015/06/office-web-app-preview-remove-top-menu/"&gt;《Office Web APP预览去掉顶部菜单》&lt;/a&gt;，就是通过修改样式来控制&lt;code&gt;OWA&lt;/code&gt;的预览界面的。&lt;/p&gt;
&lt;p&gt;通过&lt;code&gt;F12&lt;/code&gt;查看&lt;code&gt;OWA&lt;/code&gt;预览&lt;code&gt;Word&lt;/code&gt;的界面，发现&lt;code&gt;Word&lt;/code&gt;的每一页会被渲染在一个&lt;code&gt;Img&lt;/code&gt;中展示，如下图：&lt;/p&gt;</description></item><item><title>C#给PDF添加编辑域</title><link>https://fwhyy.com/2017/01/csharp-add-edit-fields-to-pdf/</link><pubDate>Wed, 04 Jan 2017 23:02:20 +0800</pubDate><guid>https://fwhyy.com/2017/01/csharp-add-edit-fields-to-pdf/</guid><description>&lt;p&gt;PDF文档通常是不能编辑的，但有些时候需要在PDF文档中填写日期或签名之类，就需要在PDF有能编辑的文本域，本文介绍怎样用C#来实现这一功能。&lt;/p&gt;</description></item><item><title>jQuery上传插件Uploadify使用详解(3.2.1)</title><link>https://fwhyy.com/2016/09/jquery-upload-plugin-uploadify-3-2-1-use-explanation/</link><pubDate>Sun, 25 Sep 2016 18:57:49 +0800</pubDate><guid>https://fwhyy.com/2016/09/jquery-upload-plugin-uploadify-3-2-1-use-explanation/</guid><description>&lt;p&gt;六年前，因为工作中使用到 jQuery 的上传组件 Uploadify ，写了一篇《&lt;a href="http://fwhyy.com/2010/01/jquery-upload-plugin-uploadify-use-explanation/"&gt;JQuery上传插件Uploadify使用详解&lt;/a&gt;》的博客来介绍 &lt;a href="http://www.uploadify.com/"&gt;Uploadify&lt;/a&gt; ，其实只是将官方文档简单翻译了下。几年下来居然有50多万的访问量，而且每天通过各种搜索引擎有大几百的朋友会访问到这篇文章。六年时间 Uploadify 从当时的2.1.0到了现在的3.2.1，变化还是挺大，为了对访问到之前那篇博客的朋友还有点价值，特写此篇。&lt;/p&gt;</description></item><item><title>使用ExceptionLess</title><link>https://fwhyy.com/2016/09/use-exceptionless/</link><pubDate>Tue, 13 Sep 2016 23:03:26 +0800</pubDate><guid>https://fwhyy.com/2016/09/use-exceptionless/</guid><description>&lt;p&gt;&lt;a href="http://exceptionless.com/"&gt;ExceptionLess&lt;/a&gt;是一款免费开源的分布式日志收集框架，DotNet的几乎所有类型的程序都可以支持，并且还提供了接口，可以很方便的在js中进行日志的推送。&lt;/p&gt;</description></item><item><title>Remoting 外网访问</title><link>https://fwhyy.com/2016/09/remoting-external-access/</link><pubDate>Tue, 06 Sep 2016 22:01:52 +0800</pubDate><guid>https://fwhyy.com/2016/09/remoting-external-access/</guid><description>&lt;p&gt;Remoting 是一种很古老的分布式技术，如果不清楚的可以参考下面三篇博客，写的非常详细：&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/wayfarer/archive/2004/07/30/28723.html"&gt;Microsoft .Net Remoting系列专题之一:.Net Remoting基础篇&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/wayfarer/archive/2004/08/05/30437.html"&gt;Microsoft .Net Remoting系列专题之二：Marshal、Disconnect与生命周期以及跟踪服务&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/wayfarer/articles/75213.html"&gt;Microsoft .Net Remoting系列专题之三：Remoting事件处理全接触&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;最近解决公司一个老平台的问题，该平台中使用了 Remoting 技术，现有的环境大致如下：&lt;/p&gt;
&lt;p&gt;1、Remoting 服务和 Web 都是部署在局域网；
2、多台 Web 都是通过内网 IP 和端口来访问 Remoting 。&lt;/p&gt;</description></item><item><title>C# 带签名dll破解</title><link>https://fwhyy.com/2016/03/csharp-with-signature-dll-crack/</link><pubDate>Wed, 09 Mar 2016 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2016/03/csharp-with-signature-dll-crack/</guid><description>&lt;p&gt;首先申明，本文只是从技术的角度来分析下怎样破解带签名的C#写的dll文件。大家如有遇到收费的软件或类库还是应该去购买正版，程序员何苦为难程序员呢。&lt;/p&gt;</description></item><item><title>OWA实现Word在线编辑（以GridFs存储文件）</title><link>https://fwhyy.com/2016/01/word-owa-online-editor-from-gridfs/</link><pubDate>Tue, 26 Jan 2016 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2016/01/word-owa-online-editor-from-gridfs/</guid><description>&lt;p&gt;OWA全称Office Web App，是用来做Office文档预览的一个很好的工具，通过一些配置文件的设置还可以实现Excel、PowerPoint的在线编辑功能，但对Word在线编辑并不支持。GitHub上有大牛实现了Word的在线编辑，不过文件必须是物理文件，本文在此基础上做了些扩展可以支持文件存储在分布式文件系统中，本文以GridFs为例。&lt;/p&gt;</description></item><item><title>Angularjs跨域调用Asp.Net WebAPI</title><link>https://fwhyy.com/2016/01/angularjs-cross-domain-call-webapi-asp-net/</link><pubDate>Wed, 06 Jan 2016 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2016/01/angularjs-cross-domain-call-webapi-asp-net/</guid><description>&lt;p&gt;之前写过一篇使用jQuery跨域调用WebAPI的博客《&lt;a href="http://blog.fwhyy.com/2015/08/jquery-cros-access-asp-net-web-api/"&gt;jQuery跨域调用Asp.Net Web API&lt;/a&gt;》,但最近使用Angularjs来调用WebAPI发现之前的方法行不通。本文主要介绍解决使用Angularjs调用WebAPI的跨域问题。&lt;/p&gt;</description></item><item><title>Asp.Net WebAPI 视频秒播</title><link>https://fwhyy.com/2015/12/aspnet-webapi-shi-pin-miao-bo/</link><pubDate>Sat, 12 Dec 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/12/aspnet-webapi-shi-pin-miao-bo/</guid><description>&lt;p&gt;看标题知道本文是关于WebAPI和视频播放的，关于在Web上使用的视频播放插件有很多，像flowplayer、jdplayer等等。使用这些控件通常使用服务器上物理文件的相对路径或是一个API地址返回一个视频流。通常情况下视频播放控件会将视频流全部加载后才开始播放，当视频文件较大时，这个等待时间是不能接受的，本文主要介绍怎样实现秒播。&lt;/p&gt;</description></item><item><title>使用fancybox</title><link>https://fwhyy.com/2015/12/use-fancybox/</link><pubDate>Wed, 02 Dec 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/12/use-fancybox/</guid><description>&lt;p&gt;fancybox是一款不错的展示图片的jQuery插件，就目前在网上查到的资料大体有1.x和2.x两个大大版本，两个版本的用法有不少的差别，本文主要介绍的是2.1.5版本的使用。&lt;/p&gt;</description></item><item><title>使用nw.js制作桌面应用程序</title><link>https://fwhyy.com/2015/10/use-nwjs-to-create-desktop-applications/</link><pubDate>Thu, 22 Oct 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/10/use-nwjs-to-create-desktop-applications/</guid><description>&lt;p&gt;本文主要介绍在windows和mac下如果使用nw.js来制作桌面应用程序，以及如何制作成安装包，本文不涉及nw.js的开发，只是用nw.js做壳包一个web应用而已。&lt;/p&gt;</description></item><item><title>C#操作AD修改用户密码</title><link>https://fwhyy.com/2015/09/csharp-operation-ad-to-modify-the-user-password/</link><pubDate>Thu, 24 Sep 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/09/csharp-operation-ad-to-modify-the-user-password/</guid><description>&lt;p&gt;本文的标题是C#操作AD来修改用户密码，其实在微软的API中没有修改密码的方法（我理解的修改密码是需要输入旧密码进行验证），只有重置密码的方法。重置密码的代码大概如下：&lt;/p&gt;</description></item><item><title>在Windows Server2008R2中部署WebAPI</title><link>https://fwhyy.com/2015/09/deploy-webapi-in-windows-server2008/</link><pubDate>Wed, 16 Sep 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/09/deploy-webapi-in-windows-server2008/</guid><description>&lt;p&gt;一直以来都是在win8或windows server2012中进行asp.net mvc或webapi程序的部署，没有发现任何问题。今天在win2008中进行asp.net webapi的部署，访问api的时候页面显示404错误。下面步骤将解决asp.net webapi在win2008中的部署问题。&lt;/p&gt;</description></item><item><title>jQuery跨域调用Asp.Net Web API</title><link>https://fwhyy.com/2015/08/jquery-cros-access-asp-net-web-api/</link><pubDate>Sat, 15 Aug 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/08/jquery-cros-access-asp-net-web-api/</guid><description>&lt;p&gt;Asp.Net Web API是一个轻量级的Web服务，当Web API和Web程序不是部署在同一域的时候，要使用jQuery来实现调用API的接口就存在跨域的问题。下面介绍两种方式来解决jQuery调用API跨域的问题。&lt;/p&gt;</description></item><item><title>C#访问群集部署时的MongoDB</title><link>https://fwhyy.com/2015/08/mongodb-access-to-the-csharp-of-the-cluster/</link><pubDate>Thu, 13 Aug 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/08/mongodb-access-to-the-csharp-of-the-cluster/</guid><description>&lt;p&gt;普通的MongoDB部署有一台主、一台备，程序连接MongoDB时需要主服务器的地址以及端口，当群集部署的时候就会有多个服务器地址需要连接，MongoDB的C# API可以支持同时连接多台服务器。&lt;/p&gt;</description></item><item><title>开源上传组件stream的.Net后台实现</title><link>https://fwhyy.com/2015/08/stream-aspnet/</link><pubDate>Thu, 13 Aug 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/08/stream-aspnet/</guid><description>&lt;p&gt;stream是一款功能很强大的上传组件，支持Html5和Flash两种方式，Html5可以支持断点续传，进度、剩余时间等的显示。但后台代码实现目前只有Java和PHP的版本，参考PHP的版本我实现了一个.Net的版本，目前只支持Html5的方式，代码已经放到了Github上：&lt;/p&gt;</description></item><item><title>Office Web App 2013发布在外网进行预览</title><link>https://fwhyy.com/2015/06/office-web-app-2013-preview-in-external/</link><pubDate>Sat, 20 Jun 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/06/office-web-app-2013-preview-in-external/</guid><description>&lt;p&gt;Office Web App是用来做Office文档预览的一个很好的工具，网上的很多资料大都是跟SharePoint集成、Lync集成等，并且基本都是在内网部署。本文主要介绍下怎样在外网部署实现预览功能。&lt;/p&gt;
&lt;h2 id="安装"&gt;安装&lt;/h2&gt;
&lt;p&gt;OWA的安装可以参考下面链接：&lt;/p&gt;
&lt;p&gt;&lt;a href="https://technet.microsoft.com/zh-cn/library/jj219455.aspx"&gt;https://technet.microsoft.com/zh-cn/library/jj219455.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;有关安装OWA的PowerShell命令可以参考下面链接：&lt;/p&gt;
&lt;p&gt;&lt;a href="http://technet.microsoft.com/zh-cn/library/ee890080.aspx"&gt;http://technet.microsoft.com/zh-cn/library/ee890080.aspx&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="准备工作"&gt;准备工作&lt;/h2&gt;
&lt;p&gt;OWA不能安装在域控上，所以必须准备两台服务器，如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;域控服务器
&lt;ul&gt;
&lt;li&gt;服务器版本：Windows Server2012R2&lt;/li&gt;
&lt;li&gt;域名：fwhyy.com&lt;/li&gt;
&lt;li&gt;内网IP：10.15.3.160&lt;/li&gt;
&lt;li&gt;外网IP：100.180.100.180&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;OWA服务器
&lt;ul&gt;
&lt;li&gt;服务器版本：Windows Server2012R2&lt;/li&gt;
&lt;li&gt;完整机器名：owa.fwhyy.com&lt;/li&gt;
&lt;li&gt;内网IP：10.15.3.180&lt;/li&gt;
&lt;li&gt;外网IP：100.180.100.181&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;申请外网域名：owa.fwhyy.com，绑定到OWA服务器的外网IP：100.180.100.181&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="部署"&gt;部署&lt;/h2&gt;
&lt;p&gt;1.在OWA服务器上执行下面PowerShell命令：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;New-OfficeWebAppsFarm -InternalUrl &amp;#34;http://10.15.3.180&amp;#34; -AllowHttp -EditingEnabled -OpenFromUrlEnabled
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;注意InternalUrl 需要配置内网IP&lt;/p&gt;
&lt;p&gt;2.命令成功执行后，会在IIS中创建两个站点，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/3cefded1gw1etayjjaz24j20ea0530ta.webp" alt="3cefded1gw1etayjjaz24j20ea0530ta" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3.在浏览器中输入：&lt;a href="http://owa.fwhyy.com/hosting/discovery"&gt;http://owa.fwhyy.com/hosting/discovery&lt;/a&gt;会得到一个放回xml结果的页面，&lt;strong&gt;该xml文件中显示的地址为内网IP，需要将内网IP换成域名：owa.fwhyy.com&lt;/strong&gt;。保存该页面为discovery.xml文件留作备用。不同类型的文档会指向不同的页面来做预览，生成预览链接时会用到discovery.xml文件。&lt;/p&gt;
&lt;p&gt;4.如果要将OWA的预览功能和自己的应用程序进行整合，还需要有一个Web API程序进行辅助，有关这部分内容可以参考下面链接：&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/poissonnotes/p/3267190.html"&gt;http://www.cnblogs.com/poissonnotes/p/3267190.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/poissonnotes/p/3277280.html"&gt;http://www.cnblogs.com/poissonnotes/p/3277280.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;具体请求流程参见下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/3cefded1gw1etazsxxv5aj20dl0e1t96.webp" alt="3cefded1gw1etazsxxv5aj20dl0e1t96" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;5.除了discovery.xml中的地址需要修改为域名，其他所有涉及到有请求的地方全部使用内网IP。&lt;/p&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;外网访问其实关键的是需要注意三点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用PowerShell命令创建站点时使用内网IP；&lt;/li&gt;
&lt;li&gt;需要用域名进行访问，并且申请的域名必须和OWA服务器的完整机器名一致；&lt;/li&gt;
&lt;li&gt;只有discovery.xml中的地址需要为域名，其他所有都是用内网IP。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;后面会单独开篇来写一个简单的示例，包含改造后的WopiHosting部分。&lt;/p&gt;</description></item><item><title>Office Web APP预览去掉顶部菜单</title><link>https://fwhyy.com/2015/06/office-web-app-preview-remove-top-menu/</link><pubDate>Fri, 19 Jun 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/06/office-web-app-preview-remove-top-menu/</guid><description>&lt;p&gt;Office Web APP应该是用来做Office文档预览最好的方式，原生的预览页面中的顶部会有Microsoft的相关文字以及一些功能按钮，比如文件,查找（如下图）。如果仅仅是预览没有什么问题，但系统中如果预览和下载两个工能的权限是分开的，在预览时文件按钮中的 打印功能可以将文件导出成PDF，这样就分不开这两种功能权限了。下面就介绍怎样将顶部的Microsoft相关文字和功能按钮隐藏掉。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301602055.webp" alt="3cefded1gw1et90cjtya1j20h3056dg4" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="解决方法"&gt;解决方法&lt;/h2&gt;
&lt;p&gt;在Office Web APP的预览会涉及4中类型的文 件：Word、Excel、PowerPoint、PDF，不同的类型在预览时调用的文件是不一样的，其中Word和 PDF调用的是同一个文件。每个预览的页面都有对应的CSS文件，如下：&lt;/p&gt;
&lt;h3 id="powerpoint"&gt;PowerPoint&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;C:\Program Files\Microsoft Office Web Apps\WebPPTViewer\pptresources\2052\styleread.css
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="word"&gt;Word&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;C:\Program Files\Microsoft Office Web Apps\WebWordViewer\Resources\2052\WordViewer.css
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="excel"&gt;Excel&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;C:\Program Files\Microsoft Office Web Apps\ExcelServicesWfe\_layouts\styles\excelribbon.css
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在上面的三个css文件中找到cui-ribbonTopBars，在css样式中追加display:none。下面是修改后的预览效果：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301602716.webp" alt="3cefded1gw1et90ck1vftj20h405j0t4" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>C#用md5判断GridFS中文件是否存在</title><link>https://fwhyy.com/2015/05/using-csharp-check-file-in-gridfs/</link><pubDate>Thu, 21 May 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/05/using-csharp-check-file-in-gridfs/</guid><description>&lt;p&gt;假设使用MongoDB的GridFS做分布式文件系统，同样的文件在文件系统中只存一份，那么在存入文件时就需要判断文件是否已经存在，在GridFS中每个文件都有唯一的md5哈希值，只需要用文件的md5值判断是否在GridFS中已经存在就可以了，所谓的秒传功能就是用的该原理。&lt;/p&gt;
&lt;h2 id="技术栈"&gt;技术栈&lt;/h2&gt;
&lt;p&gt;C#、VS2013、MongoDB、GridFS&lt;/p&gt;
&lt;h2 id="实现"&gt;实现&lt;/h2&gt;
&lt;p&gt;1 . 首先根据文件流得到md5值，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; //计算文件的MD5码
 public static string GetMD5Hash(Stream stream)
 {
 string result = &amp;#34;&amp;#34;;
 string hashData = &amp;#34;&amp;#34;;
 byte[] arrbytHashValue;
 System.Security.Cryptography.MD5CryptoServiceProvider md5Hasher =
 new System.Security.Cryptography.MD5CryptoServiceProvider();

 try
 {
 arrbytHashValue = md5Hasher.ComputeHash(stream);//计算指定Stream 对象的哈希值
 //由以连字符分隔的十六进制对构成的String，其中每一对表示value 中对应的元素；例如“F-2C-4A”
 hashData = System.BitConverter.ToString(arrbytHashValue);
 //替换-
 hashData = hashData.Replace(&amp;#34;-&amp;#34;, &amp;#34;&amp;#34;);
 result = hashData;
 }
 catch (System.Exception ex)
 {
 //记录日志
 }

 return result;
 }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 . 根据md5值在GridFS中进行唯一性校验，方法如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; public string IsExist(string tag)
 {
 string id = &amp;#34;&amp;#34;;
 var files = _gridFs.Find(Query.EQ(&amp;#34;md5&amp;#34;, BsonValue.Create(tag)));
 if(files.Count() &amp;gt; 0)
 {
 id=files.FirstOrDefault().Id.ToString();
 }
 return id;
 }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;3 . GridFS操作类的完整代码参考&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/oec2003/6c1d473a5a5b61a9d131"&gt;https://gist.github.com/oec2003/6c1d473a5a5b61a9d131&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Git工作流程</title><link>https://fwhyy.com/2015/02/git-workflow/</link><pubDate>Sun, 15 Feb 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/02/git-workflow/</guid><description>&lt;p&gt;2014年初开始在公司推行Git的使用，到现在将近一年的时间，公司的大部分项目代码都已经迁移到了Git上，关于Git的安装使用在之前的文章有相关介绍，《&lt;a href="http://blog.fwhyy.com/2012/02/use-git-manage-github-project-on-windows/"&gt;Windows 下使用Git管理Github项目&lt;/a&gt;》、《&lt;a href="http://blog.fwhyy.com/2012/11/using-git-in-vs2010/"&gt;在VS2010中使用Git【图文】&lt;/a&gt;》，本文主要说说Git使用的工作流程。&lt;/p&gt;
&lt;p&gt;一千个人心中有一千个哈莫雷特，Git作为一个源码管理工具在不同的人，不同的团队中使用的流程也是不相同的。下面说说我在公司推行的过程中在不同阶段的使用情况：&lt;/p&gt;
&lt;h2 id="开始使用阶段"&gt;开始使用阶段&lt;/h2&gt;
&lt;p&gt;1、开始使用Git时，团队成员对Git还不是很了解，有的开发人员之前有VSS、SVN背景，有的没有使用过源码管理工具，使用过的也没有使用过分支功能；&lt;/p&gt;
&lt;p&gt;2、开发人员每个人创建一个分支，随时随地commit，每天push一次到服务器；&lt;/p&gt;
&lt;p&gt;3、因为每个人单独分支，push时不需要pull，也没有冲突需要解决；&lt;/p&gt;
&lt;p&gt;4、团队Leader每天在所有开发人员push后将代码合并到master分支，开发人员每天上班后将master拉下来合并到自己分支；&lt;/p&gt;
&lt;h2 id="产品项目开始阶段"&gt;产品/项目开始阶段&lt;/h2&gt;
&lt;p&gt;1、这时开发人员已基本熟悉Git的使用了，无需再每个人创建一个分支；&lt;/p&gt;
&lt;p&gt;2、除了master分支还有一个供所有开发人员开发的dev分支；&lt;/p&gt;
&lt;p&gt;3、大家都在同一个dev分支上进行工作，依然是随时随地地commit，每天push一次到服务器；&lt;/p&gt;
&lt;p&gt;4、push代码前需要进行pull操作，因为有可能在之前有别的成员先进行了push操作，如果有冲突还需要进行冲突解决；&lt;/p&gt;
&lt;p&gt;5、每天上班后所有成员对dev进行pull操作，获取所有成员push的代码，有冲突需要解决；&lt;/p&gt;
&lt;p&gt;6、团队Leader每天将dev合并一次到master。&lt;/p&gt;
&lt;h2 id="测试进入的阶段"&gt;测试进入的阶段&lt;/h2&gt;
&lt;p&gt;1、测试可能是在项目后期才进入，不同公司或不同项目可能有所不同；&lt;/p&gt;
&lt;p&gt;2、测试进入后就需要添加test分支；&lt;/p&gt;
&lt;p&gt;3、在开发人员将代码push到dev分支后，可以在dev基础上创建test分支，测试人员以test分支搭建测试环境，开始测试；&lt;/p&gt;
&lt;p&gt;4、开发人员在接受到bug后，直接在测试分支上修改，然后让测试人员进行验证；&lt;/p&gt;
&lt;p&gt;5、每天团队Leader将测试分支上修改的bug合并到dev分支上，这样所有团队成员当天修复的bug都会在第二天被团队其他人pull下来；&lt;/p&gt;
&lt;p&gt;6、团队Leader每天将dev合并一次到master。&lt;/p&gt;
&lt;h2 id="上线后阶段"&gt;上线后阶段&lt;/h2&gt;
&lt;p&gt;1、系统上线后试运行阶段会存在两种改动：Bug和优化需求，Bug通常当天解决晚上部署，优化需求通常周末部署；&lt;/p&gt;
&lt;p&gt;2、Bug当天能修复的就直接在test分支上修复，然后进行测试，验证通过后合并到master；&lt;/p&gt;
&lt;p&gt;3、Bug当天不能修复的就针对该Bug创建一个分支，修复完后合并到test分支进行测试，验证通过后合并到master；&lt;/p&gt;
&lt;p&gt;4、每个优化需求都以master分支为基础创建一个feature分支，完成后合并到dev分支，开发人员可以先交叉测试，然后将dev合并到test进行测试，验证通过后合并到master；&lt;/p&gt;
&lt;p&gt;5、master始终是一个干净的，可发布的分支。&lt;/p&gt;
&lt;h2 id="commit提交的粒度"&gt;Commit提交的粒度&lt;/h2&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;5、如果粒度够细，通常一句话可以概括，一句话不能概括的，空一行在下面写详细的注释；&lt;/p&gt;
&lt;p&gt;6、太简单的注释还不如不写，没有任何意义；&lt;/p&gt;
&lt;p&gt;7、据说林纳斯修改了20行的Liunx内核代码，注释长达2000多字，说明commit注释的重要性。&lt;/p&gt;
&lt;p&gt;以上是我在实际工作中的一些心得，仅供参考，工具的使用没有最好，适合自己团队的才是最好的。第一次使用&lt;a href="http://mp.weixin.qq.com/s?__biz=MjM5NTI5MzM2MA==&amp;amp;mid=202105768&amp;amp;idx=1&amp;amp;sn=2ba05ca9c2711f3a1ed913073db2be2b&amp;amp;scene=2&amp;amp;from=timeline&amp;amp;isappinstalled=0#rd"&gt;刘韧体&lt;/a&gt;，感觉还不错，&lt;a href="https://qdan.me/"&gt;轻单网&lt;/a&gt;也是一种类刘韧体的延生，有兴趣的朋友可以去体验下。&lt;/p&gt;</description></item><item><title>VS2012在安装VS2013后打开文件报错，未找到与约束…</title><link>https://fwhyy.com/2015/01/contractname-microsoft-visualstudio-text-itextdocumentfactoryservice/</link><pubDate>Fri, 23 Jan 2015 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2015/01/contractname-microsoft-visualstudio-text-itextdocumentfactoryservice/</guid><description>&lt;p&gt;VS从VS2003就这么一路装过来，现在机器上最新的版本是VS2012，昨天装了VS2013，发现用VS2012打开项目中文件时会报错，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290801094.webp" alt="3cefded1gw1eojtgufjkvj20dh0700ti" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;下载一个VS的补丁安装后可以解决此问题，补丁下载地址为：&lt;a href="http://download.csdn.net/download/oec2003/8391417"&gt;http://download.csdn.net/download/oec2003/8391417&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290801293.webp" alt="3cefded1gw1eojtgv77gxj20co0hq0t3" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>Ubuntu12.04中安装Git</title><link>https://fwhyy.com/2014/02/install-git-in-ubuntu12-04/</link><pubDate>Sun, 23 Feb 2014 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2014/02/install-git-in-ubuntu12-04/</guid><description>&lt;p&gt;Git是一个分布式源码管工具，在之前的&lt;a href="http://blog.fwhyy.com/category/jishu/git/"&gt;文章&lt;/a&gt;中有讲到过怎样在Windows下使用Git和在VS中使用Git，最近在尝试在Ubuntu中搭建Gitlab环境，Linux系统也是初次接触，属于摸索中前进，先说说在Ubuntu中怎样安装Git&lt;/p&gt;
&lt;p&gt;1、首先可以通Ctrl+Alt+T快捷键打开终端；&lt;/p&gt;
&lt;p&gt;2、输入命令sudo apt-get git，使用该命令安装的git是比较老的版本；&lt;/p&gt;
&lt;p&gt;3、安装了老的版本的git后，可以使用git clone git://git.kernel.org/pub/scm/git/git.git将获取到git的源码，默认会签出最近的版本；&lt;/p&gt;
&lt;p&gt;4、使用git tag可以查看所有的历史版本，可以用git checkout version来签出指定版本进行安装，例如：git checkout v1.9.0；&lt;/p&gt;
&lt;p&gt;5、在编译安装前先要安装ssl编译开发包，使用sudo apt-get install libssl-dev；&lt;/p&gt;
&lt;p&gt;6、用cd命令进入到git目录，执行make prefix=/usr/local all doc进行编译；&lt;/p&gt;
&lt;p&gt;7、使用sudo make prefix=/usr/local install install-doc install-html进行安装；&lt;/p&gt;
&lt;p&gt;8、安装完后，重新打开终端，使用git –version来查看安装是否成功。&lt;/p&gt;</description></item><item><title>placeholder在IE8中兼容性问题解决</title><link>https://fwhyy.com/2014/02/placeholder-in-ie8/</link><pubDate>Wed, 12 Feb 2014 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2014/02/placeholder-in-ie8/</guid><description>&lt;p&gt;placeholder是HTML5中的一个属性，可以在文本框中设置placeholder属性来显示一些提示性的文字，但对IE10以下的浏览器不支持，下面方法可以让placeholder能够使用在IE10以下的版本中。第一种方法是在页面中添加下面一段脚本：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;script type=&amp;#34;text/javascript&amp;#34;&amp;gt; 
 if( !(&amp;#39;placeholder&amp;#39; in document.createElement(&amp;#39;input&amp;#39;)) ){ 

 $(&amp;#39;input[placeholder],textarea[placeholder]&amp;#39;).each(function(){ 
 var that = $(this), 
 text= that.attr(&amp;#39;placeholder&amp;#39;); 
 if(that.val()===&amp;#34;&amp;#34;){ 
 that.val(text).addClass(&amp;#39;placeholder&amp;#39;); 
 } 
 that.focus(function(){ 
 if(that.val()===text){ 
 that.val(&amp;#34;&amp;#34;).removeClass(&amp;#39;placeholder&amp;#39;); 
 } 
 }) 
 .blur(function(){ 
 if(that.val()===&amp;#34;&amp;#34;){ 
 that.val(text).addClass(&amp;#39;placeholder&amp;#39;); 
 } 
 }) 
 .closest(&amp;#39;form&amp;#39;).submit(function(){ 
 if(that.val() === text){ 
 that.val(&amp;#39;&amp;#39;); 
 } 
 }); 
 }); 
 } 
&amp;lt;/script&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的方法不能支持password类型的文本框，网上找了些解决方法都不是很完美，最后发现jQuery的placeholder插件还不错，代码如下：&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/oec2003/8946120"&gt;https://gist.github.com/oec2003/8946120&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;将placeholder.js文件引用到页面，页面中添加下面脚本：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;script type=&amp;#34;text/javascript&amp;#34;&amp;gt;
$(function() {
 $(&amp;#39;input, textarea&amp;#39;).placeholder();
});
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>连接RTX服务器出现“应用SDK:连接SDK服务器错误”问题解决</title><link>https://fwhyy.com/2014/01/connect-to-rtx-server-application-the-sdk-to-connect-sdk-server-error-problem-solution/</link><pubDate>Thu, 09 Jan 2014 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2014/01/connect-to-rtx-server-application-the-sdk-to-connect-sdk-server-error-problem-solution/</guid><description>&lt;p&gt;腾讯通的官方有个示例可以使用程序来进行腾讯通客户端的登录，大致原理是这样：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;从服务端验证用户名是否存在；&lt;/li&gt;
&lt;li&gt;根据用户名从服务端生成key；&lt;/li&gt;
&lt;li&gt;根据key值调用脚本启动腾讯通客户端。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在本机安装好腾讯通的客户端和服务器，运行实例程序，可以正常跑起来，将服务器安装在虚机中，就会报“(0xFFFFBA9E): 应用SDK:连接SDK服务器错误”的错误，原因是服务器端对IP地址有限制，修改配置文件，重启腾讯通的所有服务即可，具体方法如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290800352.webp" alt="3cefded1gw1eccx0b95c2j20fl0d9myt" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;将示例部署到IIS中，运行后出现如下错误：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290800607.webp" alt="3cefded1gw1eccx0aqp3hj20mq06i41k" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="网上查到的一些解决方法"&gt;网上查到的一些解决方法&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;注册腾讯通的dll（Interop.RTXSAPILib.dll），试过发现无法注册；&lt;/li&gt;
&lt;li&gt;修改项目的编译平台为x86，发现也不能解决；&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="最终解决方法"&gt;最终解决方法&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;在对应的应用程序池上点击右键；&lt;/li&gt;
&lt;li&gt;选择高级设置；&lt;/li&gt;
&lt;li&gt;常规选项卡上将“启用32位应用程序”修改为true。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290801459.webp" alt="3cefded1gw1eccxc5i01nj20cf0f1q5i" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="测试环境"&gt;测试环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;系统：Windows 7&lt;/li&gt;
&lt;li&gt;开发工具：VS2012&lt;/li&gt;
&lt;li&gt;腾讯通版本：2012&lt;/li&gt;
&lt;li&gt;IIS版本：IIS7&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Asp.Net正在中止线程引发的问题</title><link>https://fwhyy.com/2013/11/aspnet-stoped-thread-method/</link><pubDate>Fri, 22 Nov 2013 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2013/11/aspnet-stoped-thread-method/</guid><description>&lt;p&gt;Asp.Net做的一个同步程序，同步的方法是通过JQuery的Ajax调用，同步过程大概要执行20多分钟，程序部署到服务器后执行一段时间后就弹出执行失败的对话框，日志记录的错误信息是“正在中止线程”。&lt;/p&gt;
&lt;h2 id="查错过程"&gt;查错过程：&lt;/h2&gt;
&lt;p&gt;1、根据“AspNet 正在中止线程“进行搜索，得到的结果基本都是跟”Response.End“有关的，但我的代码中没有Response.End，所以基本可以排除；&lt;/p&gt;
&lt;p&gt;2、因为使用JQuery的Ajax，所以猜想会不会是因为Ajax超时导致，修改代码将返回状态弹出：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290809786.webp" alt="3cefded1gw1eatnxducbjj20k0051dg8" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;发现返回的status为”error“，也尝试过将timeout设置为一个较大值，发现问题依然存在，所以可以排除是JQuery Ajax超时；&lt;/p&gt;
&lt;p&gt;3、使用Fiddler2进行监控，发现执行一段时间后报了500错误，显示的错误详细信息如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290809600.webp" alt="3cefded1gw1eatnxcw1mrj20f607st9e" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;到了这一步就好办了，可以知道是httpRuntime超时了，配置Webconfig就可以了，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290809727.webp" alt="3cefded1gw1eatnxep1sfj20gb031wet" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;设置好好后发不到服务器，再次运行程序，问题解决。&lt;/p&gt;
&lt;p&gt;奇怪的是在本机运行的时候即使没有设置executionTimeout也不会出现问题，原因是在本机的Webconfig中的compilation节点的有个debug属性设置为true，发布后的Webconfig中的compilation没有debug节点，当debug属性为false时，httpRuntime的executionTimeout属性才会生效。&lt;/p&gt;</description></item><item><title>HTML解析组件HtmlAgilityPack使用</title><link>https://fwhyy.com/2013/09/using-htmlagilitypack/</link><pubDate>Sun, 15 Sep 2013 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2013/09/using-htmlagilitypack/</guid><description>&lt;p&gt;HtmlAgilityPack是一个开源的解析HTML元素的类库，最大的特点是可以通过XPath来解析HMTL，如果您以前用C#操作过XML，那么使用起HtmlAgilityPack也会得心应手。目前最新版本为1.4.6,下载地址如下：&lt;/p&gt;
&lt;p&gt;&lt;a href="http://htmlagilitypack.codeplex.com/"&gt;http://htmlagilitypack.codeplex.com/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="使用介绍"&gt;使用介绍&lt;/h2&gt;
&lt;p&gt;下面以一个简单的例子来介绍下HtmlAgilityPack的使用，对于Asp.Net程序开发的网站要做模拟登录的时候，除了要知道用户名文本框和密码文本框的name属性值外，还需要知道页面的__VIEWSTATE、__EVENTVALIDATION这两个隐藏控件的值，以及提交按钮的name属性，下面看看怎样使用HtmlAgilityPack来获得这个额外的值。&lt;/p&gt;
&lt;p&gt;1、在项目中添加对HtmlAgilityPack.dll的引用&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290704832.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2、在Aspx页面中放几个文本框控件和一个按钮控件&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290704038.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3、按钮的后台事件如下&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;protected void btnHtml_Click(object sender, EventArgs e)
{
 if (tbUrl.Text.Length &amp;gt; 0)
 {
 HtmlWeb htmlWeb = new HtmlWeb();
 HtmlDocument htmlDoc = htmlWeb.Load(this.tbUrl.Text);
 HtmlNode htmlNode = htmlDoc.DocumentNode.SelectSingleNode(&amp;#34;//input[@id=&amp;#39;__VIEWSTATE&amp;#39;]&amp;#34;);
 string viewStateValue = htmlNode.Attributes[&amp;#34;value&amp;#34;].Value;
 htmlNode = htmlDoc.DocumentNode.SelectSingleNode(&amp;#34;//input[@id=&amp;#39;__EVENTVALIDATION&amp;#39;]&amp;#34;);
 string eventValidation = htmlNode.Attributes[&amp;#34;value&amp;#34;].Value;
 htmlNode = htmlDoc.DocumentNode.SelectSingleNode(&amp;#34;//input[@type=&amp;#39;submit&amp;#39;]&amp;#34;);
 string submitName = htmlNode.Attributes[&amp;#34;name&amp;#34;].Value;

 tbViewState.Text = viewStateValue;
 tbEventValidation.Text = eventValidation;
 tbSubmitName.Text = submitName;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;4、以博客园的登录界面为例，获取后的界面如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290705365.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://pan.baidu.com/share/link?shareid=71500880&amp;amp;uk=2902808695"&gt;示例下载&lt;/a&gt;&lt;/p&gt;</description></item><item><title>SqlServer2008R2用Windows身份登录18456错误解决</title><link>https://fwhyy.com/2013/09/sqlserver2008r2-windows-login-18456-error/</link><pubDate>Sat, 07 Sep 2013 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2013/09/sqlserver2008r2-windows-login-18456-error/</guid><description>&lt;p&gt;重装系统后发现SqlServer2008R2使用Windows身份验证不能进行连接，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302000357.webp" alt="07070635-ce750450dc434a518651c5d3b77f9402" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;以前经常会碰到SqlServer 身份验证连接失败，Windows身份验证的连接失败还是第一次，试了下SqlServer 身份验证可以正常连接，sa账号连接进去后，在安全性-》登录名下没有发现当前登录用户的账号，在登录名上点击邮件，新建登录名即可：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302000426.webp" alt="07070636-ed428dd377a147e99a2e428551933309" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>jQuery知识总结</title><link>https://fwhyy.com/2013/04/jquery-knowledge-summary/</link><pubDate>Sat, 13 Apr 2013 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2013/04/jquery-knowledge-summary/</guid><description>&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;jQuery一直都在用，但都是在用时查查手册，并没有系统的学过，最近组内做jQuery交流，花了几天时间系统了学习了下，做了个PPT，本文是根据PPT总结而来，有些地方做了些补充。希望对jQuery初学者有些帮助。&lt;/p&gt;
&lt;h2 id="jquery简介"&gt;jQuery简介&lt;/h2&gt;
&lt;h3 id="简介"&gt;简介&lt;/h3&gt;
&lt;p&gt;jQuery是一个兼容多浏览器的javascript库，核心理念是write less,do more(写的更少,做的更多)。 jQuery在2006年1月由美国人John Resig在纽约的barcamp发布，吸引了来自世界各地的众多javascript高手加入，现在由Dave Methvin率领团队进行开发。如今， jQuery已经成为最流行的javascript库，在世界前10000个访问最多的网站中，有超过55%在使用jQuery 。【摘自百度百科】&lt;/p&gt;
&lt;h3 id="下载地址"&gt;下载地址&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://jquery.com/"&gt;http://jquery.com/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="源码地址"&gt;源码地址&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/jquery/jquery"&gt;https://github.com/jquery/jquery&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;可以通过 &lt;code&gt;git clone git://github.com/jquery/jquery.git&lt;/code&gt;来获取源码。&lt;/p&gt;
&lt;h3 id="在线文档"&gt;在线文档&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.ostools.net/apidocs/apidoc?api=jquery"&gt;http://www.ostools.net/apidocs/apidoc?api=jquery &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ostools.net/"&gt;http://www.ostools.net/&lt;/a&gt;上有各种在线工具，在此推荐下。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="使用jquery"&gt;使用jQuery&lt;/h3&gt;
&lt;p&gt;使用jQuery首先需要在页面中进行引用，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;script type=”text/javascript” src=”Scripts/jquery-1.8.1.min.js”&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;使用的代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$(document).ready(function () {
 $(&amp;#34;#div1&amp;#34;).html(&amp;#34;hello world&amp;#34;);
});

$(function () {
 $(&amp;#34;#btnOK&amp;#34;).bind(&amp;#34;click&amp;#34;, function () { 

 });
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码相当于window.onload，不过跟window.onload还是有一些区别，后面会以表格的形式来展现他们的区别。在jQuery中到处可以见到$符号，这是jQuery里的一种简写，$(&amp;quot;#btnOK&amp;quot;)和jQuery(&amp;quot;#btnOK&amp;quot;)是等价的。&lt;/p&gt;
&lt;h3 id="windowonload和documentready的区别"&gt;window.onload和$(document).ready()的区别&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;&lt;/th&gt;
					&lt;th&gt;WINDOW.ONLOAD&lt;/th&gt;
					&lt;th&gt;$(DOCUMENT).READY()&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;执行时间&lt;/td&gt;
					&lt;td&gt;网页所有内容加载完后执行&lt;/td&gt;
					&lt;td&gt;DOM结构加载完后就执行，效率更高&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;编写个数&lt;/td&gt;
					&lt;td&gt;1个&lt;/td&gt;
					&lt;td&gt;多个，多个的执行顺序取决于函数的顺序以及引用文件的顺序&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;是否支持简写&lt;/td&gt;
					&lt;td&gt;不支持&lt;/td&gt;
					&lt;td&gt;简写形式为：$(function(){});&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="dom对象和jquery对象转换"&gt;DOM对象和jQuery对象转换&lt;/h3&gt;
&lt;p&gt;获取DOM对象代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;//获取DOM对象
var div1 = document.getElementById(&amp;#34;div1&amp;#34;);

div1.innerHTML = &amp;#34;oec2003&amp;#34;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;获取jQuery对象代码如下:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;//获取jQuery对象
var div1 = $(&amp;#34;#div1&amp;#34;);

div1.html(&amp;#34;oec2003&amp;#34;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;jQuery对象转DOM对象&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;//因为ajQuery对象是一个数组对象，所以转换为DOM对象时要用索引的形式

var $div1 = $(&amp;#34;#div1&amp;#34;); //jQuery对象

var div1 = $div1[0]; //转换为了DOM对象

var div2 = $div1.get(0); //和上面一行效果一样

div1.innerHTML = &amp;#34;oec2003&amp;#34;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;DOM对象转jQuery对象&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;//DOM对象转jQuery只需用$包装即可

var div1 = document.getElementById(&amp;#34;div1&amp;#34;);

var $div1 = $(div1); //转换为了jQuery对象

$div1.html(&amp;#34;oec2003&amp;#34;);
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="解决冲突"&gt;解决冲突&lt;/h3&gt;
&lt;p&gt;有时会有jQuery和其他的库或自己写的一些公共脚本文件一起使用的场景，就有可能会出现$冲突的问题，冲突的解决分两种情况：&lt;/p&gt;
&lt;p&gt;1、jQuery库在其他库之后引用，如下所示：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;script type=”text/javascript” src=”Scripts/jquery-1.8.1.min.js”&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script type=”text/javascript” src=”Scripts/common.js”&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在common.js中有对$重新定义，代码如下：&lt;/p&gt;</description></item><item><title>IIS7上传出现乱码问题解决</title><link>https://fwhyy.com/2013/03/iis7-upload-issue/</link><pubDate>Fri, 22 Mar 2013 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2013/03/iis7-upload-issue/</guid><description>&lt;p&gt;最近查一个bug，客户那边将上传超过30兆的文件时，上传页面出现乱码，如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300703232.webp" alt="1" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;系统默认是只能上传10兆以内的文件，客户自己修改了webconfig文件后发现此问题。&lt;/p&gt;
&lt;p&gt;通过Fiddler2跟踪页面得出乱码内容为“您要找的资源已被删除、已更名或暂时不可用”，然后通过Google得出结论如下：&lt;/p&gt;
&lt;p&gt;在IIS7中出了修改webconfig的配置外还需要修改&lt;code&gt;C:\Windows\System32\inetsrv\config\schema \IIS_schema.xml&lt;/code&gt;文件，该文件中的默认设置为30兆，根据需要修改默认值大小即可：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300703951.webp" alt="2" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>SQL查询-将列转换成字符串（for xml path）</title><link>https://fwhyy.com/2013/03/sql-query-for-xml-path/</link><pubDate>Tue, 19 Mar 2013 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2013/03/sql-query-for-xml-path/</guid><description>&lt;h2 id="背景"&gt;背景&lt;/h2&gt;
&lt;p&gt;最近做一报表，因为查询的SQL很长很复杂，导致直接查询出现异常，后来想到将大量重复的只是查询条件不同的子查询放到函数中去做，无奈需要的参数不能传进函数中，因为参数格式类似如：&amp;lsquo;ProjGUID1&amp;rsquo;,&amp;lsquo;ProjGUID2&amp;rsquo; 这样，这是报表工具生成的，无法修改。现在就要想办法让参数能传进函数中或是换用其他的方式。&lt;/p&gt;
&lt;h2 id="思路"&gt;思路&lt;/h2&gt;
&lt;p&gt;1、首先想到的是用存储过程，但是在报表工具中调试不通，存储过程不能得到有效的执行，可能是根本就不支持存储过程；&lt;/p&gt;
&lt;p&gt;2、将参数作为in的条件，查询出符合条件的GUID，返回的是一个表，然后循环表的行记录，拼接GUID传入函数，但是报表工具中的SQL不支持定义变量和临时表，此方法也行不通；&lt;/p&gt;
&lt;p&gt;3、利用SQL语句的For Xml 将GUID查询成一个XML结构的字符串，但传入函数中后解析该XML需要用到系统存储过程sp_xml_preparedocument ，函数中并不支持调用存储过程，此路也不通。关于SQL中解析XML可以参见我之前的博文《&lt;a href="http://blog.fwhyy.com/2011/07/use-sp_xml_preparedocument-processing-xml-documents/"&gt;使用sp_xml_preparedocument处理XML文档&lt;/a&gt;》。&lt;/p&gt;
&lt;h2 id="解决方法"&gt;解决方法&lt;/h2&gt;
&lt;p&gt;上面说到了SQL的For Xml可以将查询的列转换成XML结构的字符串，还有一种方法可以将查询的字段转换成以特定符号隔开的字符串，那就是For Xml Path：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT TOP 2 CONVERT(VARCHAR(40),ProjGUID)+&amp;#39;,&amp;#39; FROM p_Project FOR XML PATH(&amp;#39;&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的语句得到的结果如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;BAA95B67-FC41-4A78-AF1C-014BBE0AC368,37641496-23AA-46CB-9817-027AA120F5C6,
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;至此问题解决，这样的字符串是可以传进函数的，只需将最后的逗号去掉即可。&lt;/p&gt;</description></item><item><title>在Asp.Net中使用jQueryEasyUI</title><link>https://fwhyy.com/2012/11/using-jqueryeasyui-in-aspnet/</link><pubDate>Sun, 25 Nov 2012 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2012/11/using-jqueryeasyui-in-aspnet/</guid><description>&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;最近做一个小工具，列表显示页面准备使用jQuery的UI框架，因为之前知道有jQWidgets这个框架,所以直接就下载下来使用了,&lt;a href="http://www.jqwidgets.com/"&gt;jQWidgets&lt;/a&gt;的功能很强大,Demo和文档也非常详细,但使用后发现有几个问题就果断放弃了使用jQWidgets:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;页面加载速度比较慢&lt;/li&gt;
&lt;li&gt;当列表字段过多出现横向滚动条时,拖动滚动条非常卡(在IE下都很卡,Chrome好点)&lt;/li&gt;
&lt;li&gt;分页取数稍显麻烦,也可能是我没研究透。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;经过一番比较选择了&lt;a href="http://www.jeasyui.com/"&gt;jQueryEasUI&lt;/a&gt;，目前最新版本为1.3.1：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.jeasyui.com/download/index.php"&gt;官方下载&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.jeasyui.com/demo/main/index.php"&gt;官方演示&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.jeasyui.com/documentation/index.php"&gt;官方文档&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;其实是用类似的框架，看看官网的文档也就OK了，本文是我最近是用jQueryEasyUI的一个总结，也可以让初使用jQueryEasyUI的朋友少走弯路。&lt;/p&gt;
&lt;h2 id="下载引用"&gt;下载引用&lt;/h2&gt;
&lt;p&gt;下载后解压的文件目录如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290653234.webp" alt="2012-11-22_212942" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;demo：JQueryEasyUI的一些示例页面，在项目使用可以将该目录删除&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;locale：该目录中是一些本地化文件，用来支持不同的语言，如中文可以引用其中的easyui-lang-zh_CN.js&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;plugins和src：这两个目录中是支持JQueryEasyUI各种功能的js文件&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;themes：主题目录，目录中有三种主题，default、gray和metro，另外还有一个icons目录和icon.css，在页面使用引用icon.css即可。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用jQueryEasyUI需要引用四个文件，两个css和两个js文件：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;link rel=&amp;#34;stylesheet&amp;#34; type=&amp;#34;text/css&amp;#34; href=&amp;#34;../Scripts/jqueryeasyui/themes/gray/easyui.css&amp;#34; /&amp;gt;
&amp;lt;link rel=&amp;#34;stylesheet&amp;#34; type=&amp;#34;text/css&amp;#34; href=&amp;#34;../Scripts/jqueryeasyui/themes/icon.css&amp;#34; /&amp;gt;
&amp;lt;script type=&amp;#34;text/javascript&amp;#34; src=&amp;#34;../Scripts/jqueryeasyui/jquery-1.8.0.min.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&amp;#34;text/javascript&amp;#34; src=&amp;#34;../Scripts/jqueryeasyui/jquery.easyui.min.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果需要使用本地化 还需要引用：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;script type=&amp;#34;text/javascript&amp;#34; src=&amp;#34;../Scripts/jqueryeasyui/locale/easyui-lang-zh_CN.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="jqueryeasyui-grid的分页"&gt;jQueryEasyUI Grid的分页&lt;/h2&gt;
&lt;p&gt;根据官网的文档可以很容易的构建Grid，期初我没有引用本地化文件easyui-lang-zh_CN.js，列表的分页栏显示出来是英文的，在网上查阅后得知可以用代码的方式重新构建分页栏：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;//设置分页控件 var p = $(&amp;#39;#dg&amp;#39;).datagrid(&amp;#39;getPager&amp;#39;);
$(p).pagination({
 pageSize: 10, //每页显示的记录条数，默认为10 
 pageList: [10, 20, 30, 40, 50], //可以设置每页记录条数的列表 beforePageText: &amp;#39;第&amp;#39;, //页数文本框前显示的汉字 
 afterPageText: &amp;#39;页 共 {pages} 页&amp;#39;,
 displayMsg: &amp;#39;当前显示 {from} - {to} 条记录 共 {total} 条记录&amp;#39;
 /*onBeforeRefresh:function(){ $(this).pagination(&amp;#39;loading&amp;#39;); 
 alert(&amp;#39;before refresh&amp;#39;); $(this).pagination(&amp;#39;loaded&amp;#39;); }*/
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;后来发现只需要引用本地化文件easyui-lang-zh_CN.js后分页栏就自动显示为中文了。引用本地化文件还可以解决日历控件格式的问题，所以如果是做中文系统建议还是在页面中引用本地化文件。&lt;/p&gt;
&lt;h2 id="jqueryeasyui控件的取值"&gt;jQueryEasyUI控件的取值&lt;/h2&gt;
&lt;p&gt;使用JQuery取控件的值很简单，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$(&amp;#34;#CstName&amp;#34;).val();
$(&amp;#34;#TaskNo&amp;#34;).val(),
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果要使用jQueryEasyUI的日历控件、下拉控件或其他的一些控件，给普通的input、select控件添加一个class即可：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;input id=&amp;#34;FeedBackDate&amp;#34; name=&amp;#34;FeedBackDate&amp;#34; class=&amp;#34;easyui-datebox&amp;#34; maxlength=&amp;#34;10&amp;#34;
 style=&amp;#34;width: 150px;&amp;#34; /&amp;gt;
&amp;lt;select id=&amp;#34;IsKfCl&amp;#34; class=&amp;#34;easyui-combobox&amp;#34; name=&amp;#34;IsKfCl&amp;#34; style=&amp;#34;width:150px;&amp;#34;&amp;gt; 
 &amp;lt;option value=&amp;#34;&amp;#34;&amp;gt;&amp;lt;/option&amp;gt; 
 &amp;lt;option value=&amp;#34;是&amp;#34;&amp;gt;是&amp;lt;/option&amp;gt; 
 &amp;lt;option value=&amp;#34;否&amp;#34;&amp;gt;否&amp;lt;/option&amp;gt; 
&amp;lt;/select&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;现在取这些控件的值需要使用下面的方法：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$(&amp;#34;#FeedBackDate&amp;#34;).datebox(&amp;#34;getValue&amp;#34;);
$(&amp;#34;#IsKfCl&amp;#34;).combobox(&amp;#34;getValue&amp;#34;);
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="grid-toolbar的两种方式"&gt;Grid ToolBar的两种方式&lt;/h2&gt;
&lt;p&gt;通常在Grid列表控件的上方会添加一些按钮如：新增、编辑、删除等，如下面效果：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290653327.webp" alt="2012-11-25_144045_thumb" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在jQueryEasyUI中可以使用ToolBar来实现，ToolBar可以在DataGrid初始化时定义，如下：&lt;/p&gt;</description></item><item><title>在VS2010中使用Git【图文】</title><link>https://fwhyy.com/2012/11/using-git-in-vs2010/</link><pubDate>Tue, 13 Nov 2012 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2012/11/using-git-in-vs2010/</guid><description>&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;在之前的一片博客《&lt;a href="http://blog.fwhyy.com/2012/02/use-git-manage-github-project-on-windows/"&gt;Windows 下使用Git管理Github项目&lt;/a&gt;》中简单介绍了在Windows环境中使用Git管理Github项目，但是是使用命令行来进行操作的，本文将简单介绍下在VS2010中怎样使用Git，并来管理Github上的项目。&lt;/p&gt;
&lt;h2 id="准备"&gt;准备&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;安装Git命令行，下载地址：&lt;a href="http://code.google.com/p/msysgit/downloads/list"&gt;http://code.google.com/p/msysgit/downloads/list&lt;/a&gt;，其实如果没有安装Git命令行，在安装Git Extensions时会有两个勾选项，其中一个就是Git命令行（msysGit ）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;安装Git Extensions，下载地址：&lt;a href="http://sourceforge.net/projects/gitextensions/"&gt;http://sourceforge.net/projects/gitextensions/&lt;/a&gt; ，安装过程中会有两个勾选项msysGit 和 KDiff3，如果已经安装了Git命令行可以不勾选msysGit，KDiff3 是一个文件对比工具，在分支合并时会用到，建议勾选，安装完后也可以设置成其他的对比工具，比如：BCompare&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;安装VS的插件Git Source Control Provider，在VS2010的扩展管理中可以找到&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在VS中设置源代码控制位Git Source Control Provider。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="创建项目并添加到git"&gt;创建项目并添加到Git&lt;/h2&gt;
&lt;p&gt;使用VS2010创建一个名为GitHelloWorld的项目，在解决方案上点击右键，点击“Git –New Repository”：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290706491.webp" alt="20130513_210905" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;这时看项目所在的目录，会添加一个名为.git的隐藏目录和一个名为.gitignore的文件，除此外不会有任何多余的文件，相比VSS和SVN等源码管理工具要“干净”很多：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290706471.webp" alt="20130513_212332" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;这时会发现解决方案中的文件上并没有出现源码管理的图标，在解决方案上右击，点击Git菜单中的Refresh就OK了：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290706765.webp" alt="20130513_214629" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201290706673.webp" alt="20130513_215023_thumb" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;上面右图中的文件前的图标为加号，表示文件还没有被添加到版本库中，可以使用Git菜单中的Commit来进行提交：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290706012.webp" alt="20130513_221212" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;现在就可以对代码进行编辑了，当我们在文件中添加自己的代码后，文件的状态并不会改变，当保存文件后，文件就显示为签出状态。通常第一次通过Commit将代码加入到源码库后，建议重启VS，否则有时文件的签入签出状态得不到及时更新，如果发现状态没有及时更新也可以用Git菜单下的Refresh来进行更新。&lt;/p&gt;
&lt;p&gt;Git菜单上的Browse命令可以查看各个提交版本的信息：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290707331.webp" alt="20130513_230857" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;或是在解决方案上右击，选择“Git -History”也可以查看版本信息，是在VS中的标签页中以图形化展示：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290707672.webp" alt="20130514_064929" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;通过上面的介绍我们可以简单的使用Git来管理代码了，下面接着来说怎样将代码推送到Github中&lt;/p&gt;
&lt;p&gt;首先需要在Github中创建一个新的repository，命名为GitHelloWorld，创建完成后如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290707307.webp" alt="20130514_065931" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;上图中红色框中的就是新建的GitHelloWorld的地址，通过这个地址我们就可以将本地代码推送到GitHub中，在VS中点击Git菜单下的Push命令：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290707811.webp" alt="20130514_073305" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;如果推送成功会看到如下提示框：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290707684.webp" alt="20130514_073354_thumb" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;这时刷新GitHub中的页面可以看到项目已经添加到GitHub中了：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290708761.webp" alt="20130514_194240_thumb" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;到这儿就介绍完怎样在VS中将代码放入到Git库，并将代码推送到GitHub。下面介绍下已知一个GitHub的源码地址，怎样把代码拉到本地，比如刚刚推送到GitHub中的GtiHelloWorld的地址是&lt;code&gt;git://github.com/oec2003/GitHelloWorld.git&lt;/code&gt;，现在使用这个地址将代码拉到本地。&lt;/p&gt;
&lt;h2 id="从github拉代码到本地"&gt;从GitHub拉代码到本地&lt;/h2&gt;
&lt;p&gt;打开VS2010，点击Git菜单的Clone repository：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290708283.webp" alt="20130515_212658_thumb" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在弹出的克隆对话框中输入相应的信息：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290708972.webp" alt="20130515_214044" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“克隆”按钮，如果成功克隆的话会弹出如下信息框：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290708621.webp" alt="20130515_214127_thumb" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;就这么简单，现在代码已经被拉到E盘的GitHelloWorld目录中了。还有一种方法就是直接打开Git Extensions，点击“克隆档案库”可以达到同样的效果。现在就可以使用VS2010开始我们的Git之旅了，关于分支、标签等深入一点的内容在后面的博文中会介绍。&lt;/p&gt;</description></item><item><title>VS2010和VS2008使用不同编译方式在64位机器生成注册表对比</title><link>https://fwhyy.com/2012/10/gen-reg-in-vs2010-and-vs2008/</link><pubDate>Sun, 14 Oct 2012 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2012/10/gen-reg-in-vs2010-and-vs2008/</guid><description>&lt;p&gt;最近写一个小工具用到了使用C#来进行注册表的操作，使用C#来进行注册表的操作需要引入命名空间Microsoft.Win32，关于操作注册表的帮助类可以参考RegHelper.cs。下面分别使用VS2010和VS2008使用Any CPU、X64、X86和Itanium进行编译，运行在32位机器和64位机器进行对比。看下面一段代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;string subkey = @&amp;#34;software\FW\UserInfo&amp;#34;;
RegHelper reg = new RegHelper(subkey, RegDomain.LocalMachine);
reg.CreateSubKey(subkey);
Console.ReadLine();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面代码的本意是在注册表中创建&lt;code&gt;HKEY_LOCAL_MACHINE\SOFTWARE\FW\UserInfo&lt;/code&gt; 节点，在32位机器中没有什么问题，可以正常的生产节点，但在64位机器上，不同的VS版本，使用不同的编译模式，会产生不一样的结果。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300649603.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>C# &amp; .NET 1.0-4.0</title><link>https://fwhyy.com/2012/09/c-net-1-0-4-0/</link><pubDate>Sun, 02 Sep 2012 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2012/09/c-net-1-0-4-0/</guid><description>&lt;p&gt;学习和使用.NET平台已有六七个年头了，05年开始学习.NET的时候，当时网上的资源不像现在这样丰富，所以去电脑城买了张盗版的VS2005的光盘，安装时才发现是VS2003，当时有一种被坑的感觉，但也正是如此，让我有了一个完整的.NET的学习生涯。&lt;/p&gt;
&lt;p&gt;从我从业的经历来看VS2003和VS2008是使用的比较多的，一些历史遗留的老项目由种种原因没有升级，依然在使用VS2003。我现在所在的公司也只使用VS2003和VS2008这两种开发工具，尽管TFS已经是2010了。很多时候公司觉得够用也就不去升级开发工具了。从1.0到4.0的变化主要体现在DotNet平台、语言和开发工具这三个方面。本文只是概括性的讲述在每个版本里都有些什么新的特性。先看下面的一张表格，描述的不同版本的出生年份、对应的VS版本和CLR的版本。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290756052.webp" alt="2012-07-04_230408" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;上图中需要注意的一点是：2.0 3.0 3.5的CLR版本都是2.0。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;在1.1版本中，从语言的角度就是基本的面向对象的语法，可以说任何一般C#语言的书籍都包含了C#1的所有内容。工具方面VS2003已经很强大了，即便是到了现在的VS2012，我们80%时候用到的也只不过是20%的功能。&lt;/p&gt;
&lt;p&gt;在VS2003中创建ASP.NET项目默认是跟IIS相关联的，从VSS中拉VS2003的代码时需要先在IIS中创建好站点，端口要和VSS中代码的相对应，但有时会出现很多问题。我一般的做法是将代码拉到本地后，修改解决方案文件中的路径为本地路径，然后修改项目文件中的ProjectType为Local，默认是Web，就可以很顺利打开项目了。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;2.0中对应VS2005我用的也不多，因为很快就被VS2008替代了，不过在语言方面却带来了很多新的东西。&lt;/p&gt;
&lt;p&gt;★C#2中最重要的一个特性应该就是泛型。泛型的用处就是在一些场景下可以减少强制转换来提高性能。在C#1中就有很多的强制转换，特别是对一些集合进行遍历时，如ArrayList、HashTable，因为他们是为不同数据类型设计的集合，所以他们中键和值的类型都是object，这就意味着会平凡发生装箱拆箱的才做。C#2中有了泛型，所以我们可以使用List&lt;T&gt;、Dictionary&amp;lt;Tkey,TValue&amp;gt; 。泛型能够带来很好的编译时类型检查，也不会有装箱拆箱的才做，因为类型是在使用泛型的时候就已经指定了。&lt;/p&gt;
&lt;p&gt;DotNet已经通过了很多的泛型类型供我们使用，如上面提到的List&lt;T&gt;,Dictionary&amp;lt;Tkey,TValue&amp;gt;,我们也可以自己来创建泛型类型(类、接口、委托、结构)或是方法。在定义泛型类型或时可以通过定义泛型约束来对泛型参数进行限制，更好的使用编译时检查。泛型约束是通过关键字where来实现的，C#2中的泛型约束有4种：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;引用类型约束：确保类型实参是引用类型，使用where T:class来表示；&lt;/li&gt;
&lt;li&gt;值类型约束：确保类型实参是值类型，使用where T:truct来表示；&lt;/li&gt;
&lt;li&gt;构造函数类型约束，使用where T:new()来表示；&lt;/li&gt;
&lt;li&gt;转换类型约束：约束类型实参是另外的一种类型，例如：where T:IDisposable 。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;★C#2提供了分部类（Partil）。分部类可以允许我们在多个文件中为一个类型编写代码，在Asp.Net2.0中用的极为广泛。新建一个Aspx页面，页面的CodeBehind和页面中的控件的定义就是通过分部类来实现的。如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public partial class _Default : System.Web.UI.Page 
public partial class _Default 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;分布类使用关键字partial来定义，当一个类中的代码非常多时，可以使用分部类来进行拆分，这对代码的阅读很有好处，而且不会影响调用。&lt;/p&gt;
&lt;p&gt;★C#2中增加了静态类，静态类中的公用方法必须也是静态的，可以由类名直接调用，不需要实例化，比较适用于编写一些工具类。如System.Math类就是静态类。工具类有一些特点，如：所有成员都是静态的、不需要被继承、不需要进行实例化。在C#1中我们可以通过如下代码来实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;//声明为密封类防止被继承 
public sealed class StringHelper
{
 //添加私有无参构造函ˉ数防止被实例化，如果不添加私有构造函数 //会自动生成共有无参构造函数 
 private StringHelper(){};
 public static int StringToInt32(string input)
 {
 int result=0;
 Int32.TryParse(input, out result);
 return result;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;C#2中可以使用静态类来实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public static class StringHelper
{
 public static int StringToInt32(string input)
 {
 int result=0;
 Int32.TryParse(input, out result);
 return result;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;★在C#1中声明属性，属性中的get和set的访问级别是和属性一致，要么都是public要么都是private，如果要实现get和set有不同的访问级别，则需要用一种变通的方式，自己写GetXXX和SetXXX方法。在C#2中可以单独设置get和set的访问级别，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;private string name;
public string Name
{
 get { return name; }
 private set { name = value; }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;需要注意的是，不能讲属性设置为私有的，而将其中的get或是set设置成公有的，也不能给set和get设置相同的访问级别，当set和get的访问级别相同时，我们可以直接设置在属性上。&lt;/p&gt;
&lt;p&gt;★命名空间可以用来组织类，当不同的命名空间中有相同的类时，可以使用完全限定名来防止类名的冲突，C#1中可以使用空间别名来简化书写，空间别名用using关键字实现，看下面一个例子:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;namespace NameSpaceDemo1
{
 public class ClassDemo{}
}
namespace NameSpaceDemo2
{
 public class ClassDemo{}
}
using Demo1 = NameSpaceDemo1;
using Demo2 = NameSpaceDemo2;
namespace WebApplication2
{
 public partial class _Default : System.Web.UI.Page 
 {
 protected void Page_Load(object sender, EventArgs e)
 {
 Demo1.ClassDemo c1 = new Demo1.ClassDemo();
 Demo2.ClassDemo c2 = new Demo2.ClassDemo();
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果我们在使用中添加了名为Demo1或是Demo2的类，那么空间别名的使用就会受到影响，在C#1中就得使用完全限定名了。在C#2中可以用“::”符号来解决，如下面代码：&lt;/p&gt;</description></item><item><title>JS中的Replace方法</title><link>https://fwhyy.com/2012/04/the-replace-method-in-js/</link><pubDate>Mon, 16 Apr 2012 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2012/04/the-replace-method-in-js/</guid><description>&lt;p&gt;最近查一个bug，原因是JS中的Replace方法造成的，当将一个字符串中有处需要替换时，一般会用到JS中的Replace方法，Replace方法的第一个参数如果是传的字符串，只会替换第一处。代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;var str = &amp;#34;0CEA65D5-DB8E-4876-A6F8-C88AC7F0E185,E846C244-8A19-4374-879B-0B1DC08D1747,6CB3EBA4-1E22-4E4D-8800-AE31130B6F5D&amp;#34;;
alert(str.replace(&amp;#34;,&amp;#34;,&amp;#34;&amp;#39;,&amp;#39;&amp;#34;));
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码本意是将用逗号隔开的GUID的逗号替换成’,’，但实际结果只将第一个逗号替换了。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302116081.webp" alt="2012-04-16_230940" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;解决这个问题只需将replace的第一个参数使用正则的方式即可，代码如下:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;var reg = new RegExp(&amp;#34;,&amp;#34;,&amp;#34;g&amp;#34;);
var str = &amp;#34;0CEA65D5-DB8E-4876-A6F8-C88AC7F0E185,E846C244-8A19-4374-879B-0B1DC08D1747,6CB3EBA4-1E22-4E4D-8800-AE31130B6F5D&amp;#34;;
alert(str.replace(reg,&amp;#34;&amp;#39;,&amp;#39;&amp;#34;));
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;结果如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302116958.webp" alt="2012-04-16_231320" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>取汉子拼音首字母的C#和VB.Net方法</title><link>https://fwhyy.com/2012/03/take-the-first-initials-method-of-csharp-and-vbnet/</link><pubDate>Sun, 04 Mar 2012 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2012/03/take-the-first-initials-method-of-csharp-and-vbnet/</guid><description>&lt;p&gt;最近修改了项目中的一个bug，是因为取汉子拼音首字母的方法有问题导致一些字的首字母获取错误，在网上找了一些现成的方法进行测试，发现下面的方法虽然比较笨，但准确率还是挺高。&lt;/p&gt;
&lt;h2 id="c代码"&gt;C#代码&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt; 
 /// 获得一个字符串的汉语拼音码
 /// &amp;lt;/summary&amp;gt; 
 /// &amp;lt;param name=&amp;#34;strText&amp;#34;&amp;gt;字符串&amp;lt;/param&amp;gt; 
 /// &amp;lt;returns&amp;gt;汉语拼音码,该字符串只包含大写的英文字母&amp;lt;/returns&amp;gt; 
 public static string GetChineseSpell(string strText)
 {
 if (strText == null || strText.Length == 0)
 return strText;
 System.Text.StringBuilder myStr = new System.Text.StringBuilder();
 foreach (char vChar in strText)
 {
 // 若是字母则直接输出 
 if ((vChar &amp;gt;= &amp;#39;a&amp;#39; &amp;amp;&amp;amp; vChar &amp;lt;= &amp;#39;z&amp;#39;) || (vChar &amp;gt;= &amp;#39;A&amp;#39; &amp;amp;&amp;amp; vChar &amp;lt;= &amp;#39;Z&amp;#39;))
 myStr.Append(char.ToUpper(vChar));
 else if ((int)vChar &amp;gt;= 19968 &amp;amp;&amp;amp; (int)vChar &amp;lt;= 40869)
 {
 // 若字符Unicode编码在编码范围则 查汉字列表进行转换输出 
 foreach (string strList in strChineseCharList)
 {
 if (strList.IndexOf(vChar) &amp;gt; 0)
 {
 myStr.Append(strList[0]);
 break;
 }
 }
 }
 }
 return myStr.ToString();
 }// GetChineseSpell 

 private static string[] strChineseCharList = 
 { 
 &amp;#34;A阿啊锕嗄厑哎哀唉埃挨溾锿鎄啀捱皑凒溰嘊敳皚癌毐昹嗳矮蔼躷噯藹譪霭靄艾伌爱砹硋隘嗌塧嫒愛碍暧瑷僾壒嬡懓薆曖璦鴱皧瞹馤鑀鱫安侒峖桉氨庵谙萻腤鹌蓭誝鞌鞍盦馣鮟盫韽啽雸垵&amp;#34; , 
 &amp;#34;A俺唵埯铵隌揞罯銨犴岸按荌案胺豻堓婩暗貋儑錌黯肮岇昂昻枊盎醠凹坳垇柪軪爊敖厫隞嗷嗸嶅廒滶獒獓遨熬璈蔜翱聱螯翶謷翺鳌鏖鰲鷔鼇芺袄媪镺襖岙扷岰傲奡奥嫯慠骜奧嶴澳懊擙謸鏊&amp;#34; , 
 &amp;#34;B八仈巴叭扒朳玐吧夿岜芭疤哵捌笆粑紦羓蚆釟豝鲃魞叐犮抜坺妭拔茇炦癹胈釛菝詙跋軷魃把靶坝弝爸垻罢鲅鮁覇矲霸壩灞欛挀掰白百佰柏栢捭竡粨摆擺襬呗拝败拜唄敗稗粺鞁薭贁兡瓸扳&amp;#34; , 
 &amp;#34;B攽班般颁斑搬斒瘢螁癍辬阪坂岅昄板版瓪钣粄舨鈑蝂魬办半伴扮姅怑拌绊秚絆鉡靽辦瓣邦峀垹帮捠梆浜邫幇幚縍幫鞤绑綁榜膀玤蚌傍棒谤塝稖蒡蜯磅镑艕謗勹包佨孢苞胞笣煲龅蕔褒闁齙&amp;#34; , 
 &amp;#34;B窇嫑雹宝怉饱保鸨珤堡堢媬葆寚飹飽褓駂鳵緥鴇賲藵寳寶靌勽报抱豹趵菢鲍靤骲暴髱虣儤曓爆忁鑤萡陂卑杯盃桮悲揹碑鹎藣鵯喺北鉳贝狈貝邶备昁牬苝背钡俻倍悖狽被偝偹梖珼鄁備僃惫&amp;#34; , 
 &amp;#34;B焙軰辈愂碚禙蓓蛽犕褙誖骳輩鋇憊糒鞴鐾奔泍贲倴渀逩犇锛錛本苯奙畚楍坌捹桳笨撪輽伻崩绷閍嵭嘣綳繃甭埲菶琫鞛泵迸塴甏镚蹦鏰屄毴逼豍鲾鵖鰏柲荸鼻嬶匕比夶朼佊吡妣沘疕彼柀秕&amp;#34; , 
 &amp;#34;B俾笔粊舭筆鄙聛貏匂币必毕闭佖坒庇诐邲妼怭畀畁哔毖珌疪荜陛毙狴畢袐铋婢庳敝梐萆萞閇閉堛弻弼愊愎湢皕禆筚詖貱赑嗶彃楅滗滭煏痹腷蓖蓽蜌裨跸閟飶幣弊熚獙碧箅綼蔽鄪馝幤潷獘&amp;#34; , 
 &amp;#34;B罼襅駜髲壁嬖廦篦篳縪薜觱避鮅斃濞臂蹕髀奰璧鄨饆繴襞襣鏎鞸韠躃躄魓贔鐴驆鷝鷩鼊边砭笾编煸甂箯編蝙獱邉鍽鳊邊鞭鯾鯿籩炞贬扁窆匾惼碥稨褊糄鴘藊卞弁忭抃汳汴苄釆峅便变変昪&amp;#34; , 
 &amp;#34;B覍揙缏遍辡艑辧辨辩辫辮變彪标飑髟猋脿墂幖滮骠標熛膘瘭镖飙飚儦颷瀌爂臕贆鏢镳飆飇飈飊鑣表婊裱諘褾錶檦俵鳔鰾憋鳖鱉鼈虌龞別别咇莂蛂徶襒蟞蹩瘪癟彆邠宾彬傧斌椕滨缤槟瑸賓&amp;#34; , 
 &amp;#34;B賔镔儐濒濱濵虨豳瀕霦繽蠙鑌顮氞摈殡膑髩擯鬂殯臏髌鬓髕鬢仌氷冰兵栟掤梹鋲檳丙邴陃怲抦秉苪昺柄炳饼窉蛃棅禀鈵鞆餅餠燷并並併幷垪庰倂栤病竝偋傡寎摒誁鮩靐癶拨波玻剥盋袯钵&amp;#34; , 
 &amp;#34;B饽啵紴缽脖菠鉢僠嶓播餑蹳驋鱍仢伯孛驳帛泊狛瓝侼勃胉郣亳挬浡秡钹铂舶博渤葧鹁愽搏鈸鉑馎鲌僰煿牔箔膊艊馛駁踣鋍镈薄駮鮊懪礡簙鎛餺鵓犦欂襮礴鑮跛箥簸孹擘檗糪譒蘗蔔峬庯逋&amp;#34; , 
 &amp;#34;B钸晡鈽誧餔轐醭卜卟补哺捕補鳪鸔不布佈步咘怖歨歩钚勏埗悑部埠瓿廍蔀踄篰餢簿玢佛夯宀疒瀑&amp;#34; , 
 &amp;#34;C嚓擦礤礸遪猜才材财財戝裁采倸埰婇寀彩採睬跴綵踩菜棌蔡縩乲参飡骖湌嬠餐驂残蚕惭殘慚蝅慙蠶蠺惨慘噆憯黪黲灿粲儏澯薒燦璨爘仓仺伧沧苍倉舱傖凔嵢滄獊蒼濸艙螥罉藏欌鑶賶撡操&amp;#34; , 
 &amp;#34;C糙曺曹嘈嶆漕蓸槽褿艚螬鏪艹艸草愺騲肏襙册侧厕恻测荝敇萗惻測策萴筞蓛墄箣憡嵾膥岑梣涔噌层層竲驓蹭硛硳岾猠乽叉芆杈肞臿訍偛嗏插馇銟锸艖疀鍤餷垞查査茬茶嵖搽猹靫槎察碴檫&amp;#34; , 
 &amp;#34;C衩镲鑔奼汊岔侘诧姹差紁拆钗釵犲侪柴祡豺喍儕虿袃瘥蠆囆辿觇梴掺搀鋓幨婵谗孱棎湹禅馋嬋煘缠獑蝉誗鋋廛潹潺緾磛毚鄽镡瀍儳劖蟾酁嚵壥巉瀺纏纒躔镵艬讒鑱饞产刬旵丳浐剗谄產産&amp;#34; , 
 &amp;#34;C铲阐蒇剷嵼滻幝蕆諂閳簅冁繟醦鏟闡囅灛讇忏硟摲懴颤懺羼韂伥昌娼淐猖菖阊晿椙琩裮锠錩鲳鯧鼚兏肠苌尝偿常徜瓺萇甞腸嘗嫦瑺膓鋿償嚐蟐鲿鏛鱨厂场昶惝敞僘厰廠氅鋹怅玚畅倡鬯唱&amp;#34; , 
 &amp;#34;C悵暢畼誯韔抄弨怊欩钞焯超鈔繛牊晁巢巣朝鄛漅嘲潮窲罺轈吵炒眧煼麨巐仦耖觘车車砗唓莗硨蛼扯偖撦屮彻坼迠烢聅掣硩頙徹撤澈勶瞮爡抻郴棽琛嗔諃賝尘臣忱沉辰陈茞宸烥莐敐晨訦谌&amp;#34; , 
 &amp;#34;C揨煁蔯塵樄瘎霃螴諶薼麎曟鷐趻硶碜墋夦磣踸贂闯衬疢称龀趁榇稱齓齔嚫谶襯讖阷泟柽爯棦浾偁蛏铛牚琤赪憆摚靗撐撑緽橕瞠赬頳檉竀穪蟶鏳鏿饓丞成呈承枨诚郕城宬峸洆荿乘埕挰珹掁&amp;#34; , 
 &amp;#34;C窚脭铖堘惩棖椉程筬絾裎塍塖溗碀誠畻酲鋮澂澄橙檙鯎瀓懲騬悜逞骋庱睈騁秤吃妛杘侙哧彨蚩鸱瓻眵笞訵嗤媸摛痴瞝螭鴟鵄癡魑齝攡麶彲黐弛池驰迟岻茌持竾荎淔筂貾遅馳墀踟篪謘尺叺&amp;#34; , 
 &amp;#34;C呎肔侈卶齿垑胣恥耻蚇豉欼歯裭鉹褫齒彳叱斥灻赤饬抶勅恜炽翄翅敕烾痓啻湁傺痸腟鉓雴憏翤遫慗瘛翨熾懘趩饎鶒鷘充冲忡沖茺浺珫翀舂嘃摏憃憧衝罿艟蹖虫崇崈隀宠铳銃抽瘳篘犨犫仇&amp;#34; , 
 &amp;#34;C俦帱栦惆绸菗畴絒愁皗稠筹酧酬踌雔嬦懤燽雠疇躊讎讐丑丒吜杽侴瞅醜矁魗臭遚殠出岀初摴樗貙齣刍除厨滁蒢豠锄榋耡蒭蜍趎雏犓廚篨橱懨幮櫉蟵躇櫥蹰鶵躕杵础椘储楮禇楚褚濋儲檚璴&amp;#34; , 
 &amp;#34;C礎齭齼亍処处竌怵拀绌豖竐珿絀傗琡鄐搐触踀閦儊憷橻斶歜臅黜觸矗搋膗揣啜嘬踹巛川氚穿剶瑏传舡船圌遄椽歂暷輲舛荈喘僢汌串玔钏釧賗刅囱疮窓窗牎摐牕瘡窻床牀噇傸磢闖创怆刱剏&amp;#34; , 
 &amp;#34;C剙愴吹炊龡垂桘陲捶菙棰槌锤錘顀旾杶春萅堾媋暙椿槆瑃箺蝽橁櫄鰆鶞纯陙唇浱莼淳脣犉滣蒓鹑漘醇醕鯙偆萶惷睶賰踳蠢踔戳辵娖惙涰绰逴辍酫綽輟龊擉磭歠嚽齪鑡呲玼疵趀偨词珁垐柌&amp;#34; , 
 &amp;#34;C祠茈茨瓷詞辝慈甆辞磁雌鹚糍辤飺餈嬨濨鴜礠辭鶿鷀此佌皉朿次佽刺刾庛茦栨莿絘蛓赐螆賜嗭从匆囪苁忩枞茐怱悤焧葱漗聡蔥骢暰樬瑽璁聦聪瞛篵聰蟌繱鏦騘驄丛従婃孮徖悰淙琮慒誴賨&amp;#34; , 
 &amp;#34;C賩樷藂叢灇欉爜謥凑湊楱腠辏輳粗觕麁麄麤徂殂促猝媨瘄蔟誎趗憱醋瘯簇縬蹙鼀蹴蹵顣汆撺镩蹿攛躥鑹攅櫕巑窜熶篡殩簒竄爨崔催凗墔慛摧榱獕磪鏙乼漼璀皠忰疩翆脃脆啐啛悴淬萃毳焠&amp;#34; , 
 &amp;#34;C瘁粹翠膵膬竁襊臎邨村皴澊竴存刌忖寸籿搓瑳遳磋撮蹉醝髊虘嵯嵳痤矬蒫鹾鹺齹脞剉剒厝夎挫莝莡措逪棤锉蓌错銼刂刹畜曾膪澶骣粢&amp;#34; , 
 &amp;#34;D詫襜燀譂奲虰坘蚳赿跮揰裯儔幬篅搥錞踧吋咑哒耷畣搭嗒褡噠墶达妲怛垯炟羍荙匒笪答詚跶瘩靼薘鞑燵繨蟽躂鐽龖龘打大亣眔橽呆獃懛歹傣代汏轪侢垈岱帒甙绐迨带待怠柋殆玳贷帯軑埭&amp;#34; , 
 &amp;#34;D帶紿袋逮軩瑇叇曃緿鮘鴏戴艜黛簤瀻霴襶靆丹妉单担眈砃耼耽郸聃躭媅殚瘅匰箪褝鄲頕儋勯殫襌簞聸刐狚玬瓭胆衴疸紞掸馾澸黕膽旦但帎沊泹诞柦疍啖啗弹惮淡萏蛋啿氮腅蜑觛窞誕噉髧&amp;#34; , 
 &amp;#34;D憚憺澹禫駳鴠甔癚嚪贉霮饏当珰裆筜當儅噹澢璫襠簹艡蟷挡党谠擋譡灙讜氹凼圵宕砀垱荡档菪瓽雼碭瞊趤壋檔璗盪礑刀叨屶忉氘舠釖鱽魛捯导岛陦倒島捣祷禂搗隝嶋嶌槝導隯壔嶹擣蹈禱&amp;#34; , 
 &amp;#34;D到悼盗菿椡盜道稲噵稻衜檤衟翿軇瓙纛恴得淂悳惪锝嘚徳德鍀的揼扥扽灯登豋噔嬁燈璒竳簦艠覴蹬等戥邓凳鄧隥墱嶝瞪磴镫櫈鐙仾低彽袛啲埞羝隄堤趆嘀滴镝磾鞮鏑廸狄肑籴苖迪唙敌涤&amp;#34; , 
 &amp;#34;D荻梑笛觌靮滌嫡蔋蔐頔魡敵嚁藡豴糴鸐氐厎诋邸阺呧坻底弤抵柢砥掋菧軧聜骶鯳地弟旳杕玓怟枤俤帝埊娣递逓偙梊焍眱祶第菂谛釱棣睇缔蒂僀禘腣鉪馰墑墬碲蔕慸甋締嶳螮嗲敁掂傎厧嵮&amp;#34; , 
 &amp;#34;D滇槙瘨颠蹎巅癫巓巔攧癲齻典奌点婰敟椣碘蒧蕇踮电佃甸阽坫店垫扂玷钿婝惦淀奠琔殿蜔電墊壂橂澱靛磹癜簟驔刁叼汈刟虭凋奝弴彫蛁琱貂碉殦瞗雕鮉鲷簓鼦鯛鵰屌弔伄吊钓窎訋掉釣铞&amp;#34; , 
 &amp;#34;D鈟竨銱雿瘹窵鋽鑃爹跌褺苵迭垤峌恎绖胅瓞眣耊戜谍堞幉揲畳絰耋詄叠殜牃牒镻嵽碟蜨褋艓蝶疂蹀鲽曡疉疊氎嚸丁仃叮帄玎甼疔盯钉耵酊靪顶頂鼎嵿薡鐤订饤矴定訂飣啶萣椗腚碇锭碠聢&amp;#34; , 
 &amp;#34;D錠磸顁丟丢铥颩銩东冬咚岽東苳昸氡倲鸫埬娻崬涷笗菄氭蝀鮗鼕鯟鶇鶫董嬞懂箽蕫諌动冻侗垌姛峒恫挏栋洞胨迵凍戙胴動崠硐棟腖働駧霘剅唗都兜兠蔸橷篼艔斗乧阧抖陡蚪鈄豆郖浢荳逗&amp;#34; , 
 &amp;#34;D饾鬥梪脰酘痘閗窦鬦餖斣闘竇鬪鬬鬭嘟督醏毒涜读渎椟牍犊裻読蝳獨錖凟匵嬻瀆櫝殰牘犢瓄皾騳黩讀豄贕韣髑鑟韇韥黷讟厾独笃堵帾琽赌睹覩賭篤芏妒杜肚妬度荰秺渡靯镀螙殬鍍蠧蠹偳&amp;#34; , 
 &amp;#34;D媏端鍴短段断塅缎葮椴煅瑖腶碫锻緞毈簖鍛斷躖籪叾垖堆塠嵟痽頧鴭鐜队对兑対祋怼陮碓綐對憝濧薱镦懟瀩譈鐓譵吨惇敦墩墪壿撴獤噸撉犜礅蹲蹾驐盹趸躉伅沌炖盾砘逇钝顿遁鈍頓碷遯&amp;#34; , 
 &amp;#34;D潡踲多咄哆剟崜毲裰嚉夺铎剫掇敓敚敪痥鈬奪凙踱鮵鐸朵朶哚垛挅挆埵缍椯趓躱躲綞亸鬌嚲刴剁沲陊饳垜尮桗堕舵惰跢跥跺飿嶞憜墯鵽卩亻赕铫町铤夂丶&amp;#34; , 
 &amp;#34;E娾砵妸妿娿屙讹囮迗俄娥峨峩涐莪珴訛皒睋鈋锇鹅蛾磀誐頟额額鵝鵞譌枙砈婀騀鵈厄歺戹阨呃扼苊阸呝砐轭咢垩峉匎恶砨蚅饿偔卾悪硆谔軛鄂阏堮崿愕湂萼豟軶遌遏廅搹琧腭僫蝁锷鹗蕚&amp;#34; , 
 &amp;#34;E遻頞颚餓噩擜覨諤餩鍔鳄歞顎櫮鰐鶚讍鑩齶鱷奀恩蒽峎摁鞥仒乻旕儿而侕陑峏洏荋栭胹袻鸸粫輀鲕隭髵鮞鴯轜尔耳迩洱饵栮毦珥铒餌駬薾邇趰二弍弐佴刵咡贰貮衈貳誀嗯唔诶&amp;#34; , 
 &amp;#34;F颰墢鼥韛朌頒報賁獖祊埄偪胇貶昞眪袚撥柭襏舩发沷発發彂髪橃醗乏伐姂垡疺罚阀栰傠筏瞂罰閥罸藅佱法砝鍅灋珐琺髮帆忛番勫噃墦嬏幡憣旙旛翻藩轓颿飜鱕凡凢凣匥杋柉矾籵钒舤烦舧&amp;#34; , 
 &amp;#34;F笲釩棥煩緐樊蕃橎燔璠薠繁襎繙羳蹯瀿礬蘩鐇蠜鷭反仮払辺返氾犯奿汎泛饭范贩畈訉軓梵盕笵販軬飯飰滼嬎範嬔瀪方邡坊芳枋牥钫淓蚄堏鈁錺鴋防妨房肪埅鲂魴仿访纺昉昘瓬眆倣旊紡舫&amp;#34; , 
 &amp;#34;F訪髣鶭放飞妃非飛啡婓婔渄绯菲扉猆靟裶緋蜚霏鲱餥馡騑騛鯡飝肥淝暃腓蜰蟦匪诽奜悱斐棐榧翡蕜誹篚吠废杮沸狒肺昲费俷剕厞疿屝萉廃費痱镄廢蕟曊癈鼣濷櫠鐨靅分吩帉纷芬昐氛竕紛&amp;#34; , 
 &amp;#34;F翂棻訜躮酚鈖雰朆餴饙坟妢岎汾枌炃肦梤羒蚠蚡棼焚蒶馚隫墳幩蕡魵鳻橨燌燓豮鼢羵鼖豶轒鐼馩黂粉瞓黺份坋弅奋忿秎偾愤粪僨憤奮膹糞鲼瀵鱝丰风仹凨凬妦沣沨凮枫封疯盽砜風峯峰偑&amp;#34; , 
 &amp;#34;F桻烽琒崶渢溄猦葑锋楓犎蜂瘋碸僼篈鄷鋒檒豐鎽鏠酆寷灃靊飌麷冯捀逢堸綘缝艂縫讽覂唪諷凤奉甮俸湗焨煈赗鳯鳳鴌賵蘕瓰覅仏坲梻紑缶否缹缻雬鴀夫伕邞呋姇枎玞肤怤柎砆荂衭娐荴旉&amp;#34; , 
 &amp;#34;F紨趺酜麸稃跗鈇筟綒孵敷麩糐麬麱懯乀弗伏凫甶冹刜孚扶芙芣芾咈岪帗彿怫拂服泭绂绋苻茀俘垘枹柫氟洑炥玸畉畐祓罘茯郛韨鳬哹栿浮畗砩莩蚨匐桴涪烰琈符笰紱紼翇艴菔虙袱幅絥罦葍&amp;#34; , 
 &amp;#34;F福粰綍艀蜉辐鉘鉜颫鳧榑稪箙複韍幞澓蝠髴鴔諨踾輻鮄癁鮲黻鵩鶝抚甫府弣拊斧俌郙俯釜釡捬辅椨焤盙腑滏腐輔簠黼父讣付妇负附咐坿竎阜驸复祔訃負赴蚥袝偩冨副婏婦蚹傅媍富復萯蛗&amp;#34; , 
 &amp;#34;F覄詂赋椱缚腹鲋禣褔赙緮蕧蝜蝮賦駙縛輹鮒賻鍑鍢鳆覆馥鰒猤攵犭&amp;#34; , 
 &amp;#34;G玵閞鳺旮伽嘠钆尜嘎噶錷尕玍尬魀该陔垓姟峐荄晐赅畡祴該豥賅賌忋改絠鎅丐乢匃匄杚钙盖溉葢鈣戤概蓋槩槪漑瓂干甘芉迀杆玕肝坩泔苷柑竿疳酐粓亁凲尲尴筸漧尶尷魐皯秆衦赶敢笴稈&amp;#34; , 
 &amp;#34;G感澉趕橄擀簳鳡鱤旰盰矸绀倝凎淦紺詌骭幹檊赣灨冈罓冮刚岗纲肛岡牨疘缸钢剛罡堈掆釭棡犅堽綱罁鋼鎠崗港杠焵筻槓戆皋羔高皐髙槔睾膏槹橰篙糕餻櫜韟鷎鼛鷱夰杲菒稁搞缟槁獔稿镐&amp;#34; , 
 &amp;#34;G縞藁檺吿告勂诰郜峼祮祰锆筶禞誥鋯戈圪纥戓疙牱哥胳袼鸽割搁彁歌滒戨閤鴐鴚擱謌鴿鎶呄佮匌阁革敋格鬲愅臵葛隔嗝塥滆觡搿槅膈閣镉韐骼諽鮯櫊韚轕鞷騔鰪哿舸个各虼個硌铬箇獦给&amp;#34; , 
 &amp;#34;G根跟哏亘艮茛揯搄更刯庚畊浭耕掶菮椩焿絚赓鹒緪縆賡羹鶊郠哽埂峺挭绠耿莄梗綆鲠骾鯁亙堩啹喼嗰工弓公功攻杛供糼肱宫宮恭蚣躬龚匑塨幊觥躳匔碽髸觵龔巩汞拱拲栱珙輁鞏共贡貢慐&amp;#34; , 
 &amp;#34;G熕兝兣勾佝沟钩袧缑鈎緱褠篝簼鞲韝岣狗苟枸玽耇耉笱耈豿坸构诟购垢姤茩冓够夠訽媾彀搆遘雊煹觏撀覯購估咕姑孤沽泒柧轱唂唃罛鸪笟菇菰蛄蓇觚軱軲辜酤毂箍箛嫴篐橭鮕鴣轂鹘古汩&amp;#34; , 
 &amp;#34;G诂谷股峠牯骨罟羖逧钴傦啒脵蛊蛌尳愲硲詁馉榾鼓鼔嘏榖皷穀糓薣濲臌餶瀔盬瞽固故凅顾堌崓崮梏牿棝祻雇痼稒锢頋僱錮鲴鯝顧瓜刮苽胍鸹歄焻煱颪劀緺銽鴰騧冎叧呱剐剮啩寡卦坬诖挂&amp;#34; , 
 &amp;#34;G掛罣罫褂詿乖拐枴柺箉怪恠关观官冠覌倌棺蒄窤瘝癏観鳏觀鱞馆痯筦管輨舘錧館躀鳤毌贯泴悺惯掼涫悹祼慣摜遦樌盥罆鏆灌爟瓘礶鹳罐鑵鱹光灮侊炗炚炛咣垙姯茪桄烡珖胱僙輄銧黆欟广&amp;#34; , 
 &amp;#34;G広犷俇逛撗归圭妫龟规邽皈茥闺帰珪亀硅袿媯椝瑰郌摫閨鲑嬀槻槼璝瞡鬶瓌櫷宄轨庋佹匦诡陒垝癸軌鬼庪祪匭晷湀蛫觤詭厬簋蟡刽刿攰柜炅攱贵桂椢筀貴蓕跪瞆劊劌撌槶禬簂櫃鳜鱥衮惃&amp;#34; , 
 &amp;#34;G绲袞辊滚蓘滾蔉磙輥鲧鮌鯀棍棞睴璭謴呙埚郭啯崞聒鈛锅墎瘑嘓彉蝈鍋彍囯囶囻国圀國帼掴幗慖摑漍聝蔮虢馘果惈淉猓菓馃椁褁槨綶蜾裹餜鐹过桧咯莞呷&amp;#34; , 
 &amp;#34;H餲淲豩豰俿腄墮吪魤犿浲侅郂絯忓攼仠桿汵榦臯鎬暠犵挌蛤厷愩唝羾詬鶻淈鹄鈷縎鵠怘趏潅雚洸襘鞼緄腘膕粿輠過铪丷哈嗨孩骸海胲烸塰酼醢亥骇害氦嗐餀駭駴嚡饚乤兯佄顸哻蚶酣頇谽&amp;#34; , 
 &amp;#34;H憨馠魽鼾邗含邯函凾虷唅圅娢浛崡晗梒涵焓寒嵅韩甝筨爳蜬澏鋡韓厈罕浫喊蔊豃鬫汉屽扞汗闬旱垾悍捍晘涆猂莟晥焊琀菡釬閈皔睅傼蛿颔撖蜭暵銲鋎憾撼翰螒頷顄駻雗瀚鶾魧苀斻杭垳绗&amp;#34; , 
 &amp;#34;H笐航蚢颃貥筕絎頏沆蒿嚆薅竓蚝毫椃嗥獆噑豪嘷獋儫曍嚎壕濠籇蠔譹好郝号昊昦哠恏浩耗晧淏傐皓聕號暤暭澔皜皞皡薃皥颢灏顥鰝灝兞诃呵喝訶嗬蠚禾合何劾咊和姀河峆曷柇盇籺阂哬敆&amp;#34; , 
 &amp;#34;H核盉盍荷啝涸渮盒秴菏萂龁惒粭訸颌楁詥鉌阖鲄熆閡鹖麧澕篕翮魺闔齕覈鶡皬鑉龢佫垎贺寉焃湼賀煂碋褐赫鹤翯壑癋爀鶴齃靍靎鸖靏黒黑嘿潶嬒拫痕鞎佷很狠詪恨亨哼悙涥脝姮恆恒桁烆&amp;#34; , 
 &amp;#34;H珩胻鸻横橫衡鴴鵆蘅鑅堼囍乊乥叿灴轰哄訇烘軣焢硡薨輷嚝鍧轟仜弘妅红吰宏汯玒纮闳宖泓玜苰垬娂洪竑荭虹浤紘翃耾硔紭谹鸿渱竤粠葒葓鈜閎綋翝谼潂鉷鞃魟篊鋐彋蕻霐黉霟鴻黌晎嗊&amp;#34; , 
 &amp;#34;H讧訌撔澋澒銾侯矦喉帿猴葔瘊睺篌糇翭骺鍭餱鯸吼犼后郈厚垕後洉逅候鄇堠豞鲎鲘鮜鱟乎匢虍呼垀忽昒曶泘苸烀轷匫唿惚淴虖軤雽嘑寣滹雐歑囫抇弧狐瓳胡壶壷斛焀喖壺媩湖猢絗葫楜煳&amp;#34; , 
 &amp;#34;H瑚嘝蔛鹕槲箶糊蝴衚魱縠螜醐頶觳鍸餬瀫鬍鰗鶘鶦鶮乕汻虎浒唬萀琥虝箎錿鯱互弖戶户戸冱冴帍护沍沪岵怙戽昈枑祜笏粐婟扈瓠綔鄠嫭嫮摢滬蔰槴熩鳸簄鍙鹱護鳠韄頀鱯鸌花芲埖婲椛硴&amp;#34; , 
 &amp;#34;H糀誮錵蘤华哗姡骅铧滑猾嘩撶璍螖鏵驊鷨化划杹画话崋桦婳畫嬅畵話劃摦槬樺嫿澅諙諣黊繣蘳怀徊淮槐褢踝懐褱懷櫰耲蘹坏壊壞蘾欢歓鴅嚾懽獾歡貛讙驩还环峘洹荁桓萈萑堚寏絙雈羦貆&amp;#34; , 
 &amp;#34;H锾阛寰缳環豲鍰鹮糫繯轘闤鬟睆缓緩攌幻奂肒奐宦唤换浣涣烉患梙焕逭喚嵈愌換渙痪煥瑍豢漶瘓槵鲩擐澣瞣藧鯇鯶鰀巟肓荒衁塃慌皇偟凰隍黃黄喤堭媓崲徨惶湟葟遑楻煌瑝墴潢獚锽熿璜&amp;#34; , 
 &amp;#34;H篁艎蝗癀磺穔諻簧蟥鍠餭鳇趪鐄騜鰉鱑鷬怳恍炾宺晃晄奛谎幌愰詤縨謊櫎皩兤滉榥曂皝鎤灰灳诙咴恢拻挥洃虺晖烣珲豗婎媈揮翚辉隓暉楎琿禈詼幑睳噅噕翬輝麾徽隳瀈鰴囘回囬佪廻廽恛&amp;#34; , 
 &amp;#34;H洄茴迴烠逥痐蛔蛕蜖鮰悔螝毇檓燬譭卉屷汇会讳泋哕浍绘芔荟诲恚恵烩贿彗晦秽喙惠絵缋翙阓匯彙彚毀毁滙詯賄僡嘒蔧誨圚寭慧憓暳槥潓蕙徻橞獩璤薈薉諱頮檅檜燴篲藱餯嚖懳瞺穢繢蟪&amp;#34; , 
 &amp;#34;H櫘繪翽譓闠鐬靧譿顪昏昬荤婚涽阍惽棔睧睯閽忶浑馄渾魂繉鼲诨俒倱圂掍混焝溷慁觨諢吙耠锪劐鍃豁攉騞佸活秮火伙邩钬鈥夥沎或货咟俰捇眓获剨祸貨惑旤湱禍嗀奯濩獲霍檴謋穫镬嚯瀖&amp;#34; , 
 &amp;#34;H耯藿蠖嚿曤臛癨矐鑊夻行砉圜&amp;#34; , 
 &amp;#34;J皀髉畟筴簎笒覘樔伡俥鋤雛處諔堲蠀覿茤岋紇裓構颳夬叏獷臩臦昋鱖妎悎饸紅鵍丌讥击刉叽饥乩刏圾机玑肌芨矶鸡枅咭迹剞唧姬屐积笄飢基绩喞嵆嵇犄筓缉赍勣嗘畸跻鳮僟箕銈嘰撃槣樭&amp;#34; , 
 &amp;#34;J畿稽賫躸齑墼憿機激璣積錤隮磯簊績羁賷櫅耭雞譏韲鶏譤癪躋鞿鷄齎羇虀鑇覉鑙齏羈鸄覊亼及伋吉岌彶忣汲级即极亟佶郆卽叝姞急狤皍笈級揤疾觙偮卙庴脨谻戢棘極殛湒集塉嫉愱楫蒺蝍&amp;#34; , 
 &amp;#34;J趌辑槉耤膌銡嶯潗瘠箿蕀蕺鞊鹡橶檝螏輯襋蹐鍓艥籍轚鏶霵鶺鷑雦雧几己丮妀犱泲虮挤脊掎鱾幾戟嵴麂魢撠擠穖彑旡计记伎纪坖妓忌技芰芶际剂季哜垍峜既洎济紀茍計剤紒继觊記偈寂寄&amp;#34; , 
 &amp;#34;J徛悸旣梞祭惎臮葪兾痵継蓟裚跡際墍暨漃漈禝稩穊誋跽霁鲚暩稷諅鲫冀劑曁穄薊襀髻檕繋罽覬鮆檵蹟鵋齌廭懻癠糭蘎骥鯚瀱繼蘮鱀蘻霽鰶鰿鱭驥加夹抸佳泇迦枷毠浃珈家痂梜笳耞袈猳葭&amp;#34; , 
 &amp;#34;J跏犌腵鉫嘉镓糘豭貑鎵麚圿扴岬郏荚郟恝莢戛铗戞蛱颊蛺跲餄鋏頬頰鴶鵊甲玾胛斚贾钾婽斝椵賈鉀榎槚瘕檟价驾架假嫁幏榢稼駕嗧戋奸尖幵坚歼间冿戔肩艰姦姧兼监堅惤猏笺菅菺湔牋犍&amp;#34; , 
 &amp;#34;J缄葌葏間搛椷煎瑊睷缣蒹箋樫熞緘蕑蕳鲣鹣熸篯縑鋻艱鞬馢麉瀐鞯殱礛覸鵳瀸殲籛韀鰹囏虃韉囝拣枧俭柬茧倹挸捡笕减剪检湕趼揀検減睑硷裥詃锏弿瑐简絸谫彅戩戬碱儉翦檢藆襇襉謇蹇&amp;#34; , 
 &amp;#34;J瞼簡繭謭鬋鰎鹸瀽蠒鐗鐧鹻譾襺鹼见件侟建饯剑洊牮荐贱俴健剣涧珔舰剱徤渐谏釼寋旔楗毽溅腱臶践賎鉴键僭榗劍劎墹澗箭糋諓賤趝踐踺劒劔橺薦鍵餞瞷磵礀螹鍳擶繝覵艦轞鑑鑒鑬鑳江&amp;#34; , 
 &amp;#34;J姜将茳浆畕豇葁翞僵漿螀壃缰薑橿殭螿鳉疅礓疆繮韁鱂讲奖桨傋蒋奨奬蔣槳獎耩膙講顜匞匠夅弜杢降洚绛弶袶絳畺酱摾滰嵹犟糡醤糨醬櫤謽艽芁交郊姣娇峧浇茭骄胶椒焦蛟跤僬嘄虠鲛嬌&amp;#34; , 
 &amp;#34;J嶕嶣憍膠蕉膲礁穚鮫鹪簥蟭鐎鷦鷮櫵臫角佼挢狡绞饺晈笅皎矫脚铰搅筊剿勦敫煍腳賋摷暞踋鉸餃儌劋撹徼敽敿缴曒璬矯皦鵤孂纐攪灚鱎叫呌挍訆珓轿较敎教窖滘嘂嘦斠漖酵噍嬓獥藠趭轎&amp;#34; , 
 &amp;#34;J醮譥皭釂阶疖皆接掲痎秸階喈嗟堦媘揭脻街煯稭鞂蝔擑癤鶛孑尐节讦刦刧劫岊昅刼劼杰衱诘拮洁结迼桀桝莭訐婕崨捷袺傑結颉嵥楶滐睫節蜐詰鉣魝截榤碣竭蓵鲒潔羯誱踕幯嶻擮礍鍻巀櫭&amp;#34; , 
 &amp;#34;J蠞蠘蠽姐毑媎解飷檞丯介岕庎忦戒芥屆届斺玠界畍疥砎衸诫借蚧徣堺楐琾蛶骱犗誡褯魪藉巾今斤钅兓金釒津矜砛衿觔珒紟惍琎堻琻筋璡鹶黅襟仅卺巹紧堇菫僅谨锦嫤廑漌盡緊蓳馑槿瑾錦&amp;#34; , 
 &amp;#34;J謹饉劤尽劲妗近进侭枃勁浕荩晉晋浸烬赆祲進煡缙寖搢溍禁靳瑨僸凚殣觐儘噤縉賮嚍壗嬧濜藎燼璶覲贐齽坕京泾经茎亰秔荆荊婛惊旌旍猄経菁晶稉腈睛粳經兢精聙橸鲸鵛鯨鶁麖鼱驚麠井&amp;#34; , 
 &amp;#34;J丼阱刭宑汫汬肼剄穽颈景儆幜憬璄憼暻燝璟璥頸蟼警妌净弪径迳浄胫凈弳徑痉竞逕婙婧桱梷淨竟竫敬痙傹靖境獍誩静頚曔镜靜瀞鏡競竸冋坰扃埛絅駉駫蘏冏囧迥侰炯逈浻烱煚窘颎綗僒煛&amp;#34; , 
 &amp;#34;J熲澃燛褧蘔丩勼纠朻究糺鸠糾赳阄萛啾揪揫鬏鬮九久乆乣奺汣杦灸玖舏韭紤酒镹韮匛旧臼咎疚柩柾倃桕厩救就廄匓舅僦廏廐慦殧舊鹫鯦麔匶齨鷲欍凥抅匊居拘泃狙苴驹倶挶疽痀罝陱娵婅&amp;#34; , 
 &amp;#34;J婮崌掬梮涺椐琚腒锔裾雎艍蜛諊踘鋦駒鴡鞠鞫鶋局泦侷狊桔毩淗焗菊郹椈毱湨犑輂粷躹閰橘檋駶鵙蹫鵴巈蘜鶪驧咀沮举矩莒挙椇筥榉榘蒟龃聥舉踽擧櫸欅襷句巨讵姖岠怇拒洰苣邭具拠昛&amp;#34; , 
 &amp;#34;J歫炬秬钜俱倨冣剧粔耟蚷袓埧埾惧据詎距焣犋鉅飓虡豦锯愳窭聚駏劇勮屦踞鮔壉懅據澽遽鋸屨颶簴躆醵懼爠姢娟捐涓裐鹃勬鋑镌鎸鵑鐫蠲卷呟帣埍菤锩臇錈奆劵倦勌桊狷绢隽淃瓹眷鄄睊&amp;#34; , 
 &amp;#34;J絭罥睠慻蔨餋羂噘撅撧屩屫亅孒孓决刔氒诀抉芵玦玨挗珏砄绝虳觉倔欮崛掘斍桷殌覐觖訣赽趹厥絕絶覚趉鈌劂瑴谲嶡嶥憰熦爴獗瘚蕝蕨鴂鴃憠橛橜镼爵臄镢蟨蟩爑譎蹶蹷嚼矍覺鐝灍爝觼&amp;#34; , 
 &amp;#34;J彏戄攫玃鷢欔矡龣貜钁军君均汮袀軍钧莙蚐桾皲菌鈞碅筠皸皹覠銁銞鲪麇鍕鮶呁俊郡陖埈峻捃晙浚馂骏珺畯竣箟蜠儁寯懏餕燇駿鵔鵕鵘纟挟廴&amp;#34; , 
 &amp;#34;K錒嵦濭骯奟喫噄鉺朏胐阬槀稾藳溝絓鰥卝丱硄廣胿膭歸楇鉿妔薧蚵毼袔齁恗搰華磆蕐會澮璯餛秳漷監譼槛檻捁撟悈脛踁駃咔咖喀卡佧垰胩裃鉲开奒揩衉锎鐦凯剀垲恺闿铠凱剴慨蒈塏愷楷&amp;#34; , 
 &amp;#34;K輆暟锴鍇鎧闓颽忾炌欬烗勓嘅鎎乫刊栞勘龛堪戡龕冚坎侃砍莰偘惂塪輡竷轗看衎崁墈阚瞰磡矙忼砊粇康嫝嵻慷漮槺穅糠躿鏮鱇扛摃亢伉匟邟囥抗犺闶炕钪鈧閌尻髛攷考拷洘栲烤铐犒銬鲓&amp;#34; , 
 &amp;#34;K靠鮳鯌匼坷苛柯牁珂科胢轲疴趷钶嵙棵痾萪軻颏搕犐稞窠鈳榼薖颗樖瞌磕蝌頦醘顆髁礚壳咳翗嶱可岢炣渇嵑敤渴克刻剋勀勊客峇恪娔尅课堁氪骒缂嗑愙溘锞碦緙課錁礊騍肎肯肻垦恳啃豤&amp;#34; , 
 &amp;#34;K墾錹懇掯裉褃劥吭坑硁牼铿硻誙銵鍞鏗巪乬唟厼怾空倥埪崆悾硿箜躻錓鵼孔恐控鞚廤抠芤眍剾彄瞘口劶叩扣怐敂冦宼寇釦窛筘滱蔲蔻瞉簆鷇刳郀枯哭桍堀崫圐跍窟骷鮬狜苦楛库俈绔庫秙&amp;#34; , 
 &amp;#34;K焅袴喾絝裤瘔酷褲嚳夸姱舿侉咵垮銙挎胯跨骻蒯擓巜凷圦块快侩郐哙狯脍塊筷鲙儈鄶廥獪膾旝糩鱠宽寛寬髋鑧髖梡款窽窾匡劻诓邼匩哐恇洭筐筺誆軭狂狅诳軖軠誑鵟夼儣懭邝圹纩况旷岲&amp;#34; , 
 &amp;#34;K況矿昿贶框眖砿眶絋絖貺軦鉱鋛鄺壙黋懬曠爌矌礦穬纊鑛亏刲岿悝盔窥聧窺虧闚顝蘬奎晆逵鄈頄馗喹揆葵骙戣暌楏楑魁睽蝰頯櫆藈鍨鍷騤夔蘷虁躨卼傀煃跬頍蹞尯匮欳喟媿愦愧溃蒉馈匱&amp;#34; , 
 &amp;#34;K嘳嬇憒篑聩聭蕢樻殨餽簣聵籄鐀鑎坤昆晜堃堒婫崐崑猑菎裈焜琨髠裩锟髡鹍尡潉蜫褌髨熴瑻醌錕鲲臗騉鯤鵾鶤悃捆阃壸梱祵硱稇裍壼稛綑閫閸困涃睏扩拡括挄栝桰筈萿葀蛞阔廓頢濶闊鞟&amp;#34; , 
 &amp;#34;K韕懖霩鞹鬠穒&amp;#34; , 
 &amp;#34;L冫勑粚誺銐寵娕坔釘詻鄜膚鬴茖蛒鎘鉻羮篢睔腂蘫谾瘣暕撿諫倞靓靚牞摎樛畂寠窶垃拉柆啦翋菈邋旯砬揦磖喇藞嚹剌溂腊揧楋瘌蜡蝋辢辣蝲臈攋爉臘鬎櫴瓎镴鯻蠟鑞鞡来來俫倈崃徕涞莱&amp;#34; , 
 &amp;#34;L郲婡崍庲徠梾淶猍萊逨棶琜筙铼箂錸騋鯠鶆麳唻赉睐睞赖賚濑賴頼顂癞鵣瀨瀬籁藾癩襰籟兰岚拦栏婪嵐葻阑蓝谰澜褴儖斓篮燣藍襕镧闌璼襤譋幱攔瀾灆籃繿蘭斕欄礷襴囒灡籣欗讕躝襽鑭&amp;#34; , 
 &amp;#34;L钄韊览浨揽缆榄漤罱醂壈懒覧擥嬾懶孄覽孏攬欖爦纜烂滥燗嚂濫爁爛爤瓓灠糷啷勆郎郞欴狼莨嫏廊桹琅蓈榔瑯硠稂锒筤艆蜋郒螂躴鋃鎯駺悢朗阆朖烺塱蓢樃誏閬朤埌浪蒗唥捞粩撈劳労牢&amp;#34; , 
 &amp;#34;L狫窂哰唠崂浶勞痨铹僗嶗憥朥癆磱簩蟧醪鐒顟髝老佬咾姥恅荖栳珯硓铑蛯銠潦橑鮱轑涝烙嗠耢酪嫪憦澇橯耮軂仂阞乐叻忇扐氻艻玏泐竻砳勒楽韷簕鳓鰳饹餎雷嫘缧蔂樏畾檑縲镭櫑瓃羸礧&amp;#34; , 
 &amp;#34;L纍罍蘲鐳轠壨鑘靁虆鱩欙纝鼺厽耒诔垒塁絫傫誄磊蕌磥蕾儡壘癗藟櫐矋礨灅蠝蘽讄儽鑸鸓肋泪洡类涙淚累酹銇頛頪擂錑攂礌颣類纇蘱禷嘞脷塄棱楞碐稜踜薐冷倰堎愣睖唎刕厘剓梨狸离荲&amp;#34; , 
 &amp;#34;L莉骊悡梸犁菞喱棃犂鹂剺漓睝筣缡艃蓠蜊嫠孷樆璃盠竰糎蔾褵鋫鲡黎篱縭罹錅蟍謧醨嚟藜邌離鯏鏫鯬鵹黧囄灕蘺蠡蠫孋廲劙鑗穲籬驪鱺鸝礼李里俚峛哩娌峲浬逦理裡锂粴裏豊鋰鲤澧禮鯉&amp;#34; , 
 &amp;#34;L蟸醴鳢邐鱧欚力历厉屴立吏朸丽利励呖坜沥苈例岦戾枥疠苙隶俐俪栃栎疬砅茘荔赲轹郦娳悧栗栛栵涖猁珕砺砾秝莅唳婯悷琍笠粒粝蚸蛎傈凓厤棙痢蛠詈跞雳塛慄搮溧蒚蒞鉝鳨厯厲暦歴瑮&amp;#34; , 
 &amp;#34;L綟蜧勵曆歷篥隷鴗巁檪濿癘磿隸鬁儮曞櫔爄犡禲蠇嚦壢攊瀝瓅礪藶櫪爏瓑皪盭礫糲蠣儷癧礰鷅麜囇轢欐讈轣攭瓥靂鱱靋瓈俩倆嫾奁连帘怜涟莲連梿联裢亷嗹廉慩漣蓮匲奩覝劆匳噒憐磏聨&amp;#34; , 
 &amp;#34;L聫褳鲢濂濓縺翴聮薕螊櫣聯臁蹥謰鎌镰簾蠊鬑鐮鰱籢籨敛琏脸裣摙槤璉蔹嬚斂歛臉鄻襝羷练娈炼恋浰殓堜媡湅萰链僆楝煉瑓潋練澰錬殮鍊鏈瀲鰊戀纞簗良俍凉梁涼椋辌粮粱墚綡踉樑輬糧&amp;#34; , 
 &amp;#34;L両两兩唡啢掚脼裲緉蜽魉魎亮哴谅辆喨晾湸量煷輌諒輛鍄蹽辽疗聊僚寥嵺廖憀膋嘹嫽寮嶚嶛憭撩敹獠缭遼暸燎璙窷膫竂镣鹩屪廫簝蟟豂賿蹘爎鐐髎飉鷯钌釕鄝蓼爒镽了尥炓料尞撂瞭咧毟&amp;#34; , 
 &amp;#34;L挘埓列劣冽劽姴峢挒洌茢迾埒浖烈烮捩猎猟蛚裂煭睙聗趔巤颲儠鮤鴷擸獵犣躐鬛鬣鱲邻林临啉崊惏淋晽琳粦痳碄箖粼鄰隣嶙潾獜遴斴暽燐璘辚霖瞵磷臨繗翷麐轔壣瀶鏻鳞驎麟鱗菻亃稟僯&amp;#34; , 
 &amp;#34;L凛凜撛廩廪懍懔澟檁檩癛癝顲吝恡悋赁焛賃蔺橉甐膦閵疄藺蹸躏躙躪轥拎伶刢灵囹坽夌姈岭岺彾泠狑苓昤朎柃玲瓴凌皊砱秢竛铃陵鸰婈崚掕棂淩琌笭紷绫羚翎聆舲菱蛉衑祾詅跉軨蓤裬鈴&amp;#34; , 
 &amp;#34;L閝零龄綾蔆輘霊駖澪蕶錂霗魿鲮鴒鹷燯霛霝齢瀮酃鯪孁蘦齡櫺醽靈欞爧麢龗阾袊领領嶺令另呤炩溜熘刘沠畄浏流留旈琉畱硫裗媹嵧旒蒥蓅遛馏骝榴瑠飗劉瑬瘤磂镏駠鹠橊璢疁镠癅蟉駵嚠&amp;#34; , 
 &amp;#34;L懰瀏藰鎏鎦餾麍鏐飀鐂騮飅鰡鶹驑柳栁桞珋桺绺锍綹熮罶鋶橮羀嬼六翏塯廇澑磟鹨蹓霤雡飂鬸鷚瓼甅囖龙屸咙泷茏昽栊珑胧眬砻笼聋隆湰嶐槞漋癃窿篭嚨巃巄蘢鏧霳曨朧櫳爖瓏矓礱礲襱&amp;#34; , 
 &amp;#34;L籠聾蠪蠬龓豅躘鑨靇鸗陇垄垅拢儱隴壟壠攏竉哢梇硦徿贚娄偻婁喽溇蒌僂楼嘍廔慺蔞遱樓熡耧蝼瞜耬艛螻謱軁髅鞻髏嵝搂塿嶁摟漊甊篓簍陋屚漏瘘镂瘺瘻鏤露噜撸嚕擼卢庐芦垆枦泸炉栌&amp;#34; , 
 &amp;#34;L胪轳舮鸬玈舻颅鈩鲈魲盧嚧壚廬攎瀘獹璷蘆櫨爐瓐臚矑籚纑罏艫蠦轤鑪顱髗鱸鸕黸卤虏挔捛掳鹵硵鲁虜塷滷蓾樐澛魯擄橹磠镥瀂櫓氌艣鏀艪鐪鑥圥甪陆侓坴彔录峍勎赂辂陸娽淕淥渌硉菉&amp;#34; , 
 &amp;#34;L逯鹿椂琭祿禄僇剹勠滤盝睩碌稑賂路塶廘摝漉箓粶蔍戮樚熝膔膟觮趢踛辘醁潞穋蕗錄録錴璐簏螰鴼濾簶蹗轆騄鹭簬簵鏕鯥鵦鵱麓鏴騼籙觻虂鷺氇驴闾榈閭馿膢櫚藘曥鷜驢吕呂侣郘侶旅梠&amp;#34; , 
 &amp;#34;L焒祣稆铝屡絽缕屢膂膐褛鋁履褸儢穞縷穭寽垏律哷虑率绿嵂氯葎綠緑慮箻勴繂櫖爈鑢孪峦挛栾鸾脔滦銮鵉圝奱孌孿巒攣曫欒灓羉臠圞灤虊鑾癴癵鸞卵乱釠亂掠略畧锊圙鋝鋢抡掄仑伦囵沦&amp;#34; , 
 &amp;#34;L纶侖轮倫陯圇婨崘崙惀淪菕棆腀碖綸蜦踚輪磮錀鯩稐耣论埨溣論捋頱囉罗啰猡脶萝逻椤腡锣箩骡镙螺羅覶鏍儸覼騾玀蘿邏欏鸁籮鑼饠驘剆倮砢蓏裸躶瘰蠃臝攞曪癳泺峈洛络荦骆珞笿絡落&amp;#34; , 
 &amp;#34;L摞漯犖雒駱鮥鵅纙鱳&amp;#34; , 
 &amp;#34;M絔硥苾牑訬仯哋尒尓爾坆呒撫羙秏狢貈貉湏惛殙貇氂犛厸龍龒嘸呣妈媽嬤嬷麻痲嫲蔴犘蟆蟇马犸玛码蚂馬溤獁遤瑪碼螞鎷鷌鰢亇杩祃閁骂唛傌睰嘜榪禡罵駡礣鬕吗嗎嘛埋霾买荬買嘪蕒鷶&amp;#34; , 
 &amp;#34;M劢迈佅売麦卖脉脈麥衇勱賣邁霡霢颟顢姏悗蛮慲摱馒樠瞒瞞鞔饅鳗鬗鬘鰻蠻屘満睌满滿螨襔蟎鏋矕曼僈谩墁幔慢漫獌缦蔄蔓熳澷镘縵蟃謾鏝蘰牤邙吂忙汒芒杗杧盲厖恾笀茫哤娏浝牻硭釯&amp;#34; , 
 &amp;#34;M铓痝蛖鋩駹蘉莽莾茻壾漭蟒蠎匁猫貓毛矛枆牦茅旄渵軞酕蛑锚緢髦蝥錨蟊鶜冇卯戼峁泖茆昴铆笷蓩鉚冃皃芼冐茂冒眊贸耄袤覒媢帽貿鄚愗暓楙毷瑁瞀貌鄮蝐懋唜庅嚒濹嚰么癦沒没枚玫苺&amp;#34; , 
 &amp;#34;M栂眉脄莓梅珻脢郿堳媒嵋湄湈猸睂葿楣楳煤瑂禖腜塺槑酶镅鹛鋂霉徾鎇矀攗蘪鶥攟黴毎每凂美挴浼媄嵄渼媺镁嬍燘躾鎂黣妹抺沬昧祙袂眛媚寐痗跊鬽煝睸魅篃蝞嚜椚门扪玣钔門閅捫菛璊&amp;#34; , 
 &amp;#34;M穈鍆虋闷焖悶暪燜懑懣们們掹擝氓甿虻冡庬罞萌萠夢溕盟甍儚橗瞢蕄蝱鄳鄸幪懞濛獴曚朦檬氋矇礞鯍艨鹲矒靀饛顭鸏勐猛瓾蒙锰艋蜢錳懵蠓鯭鼆孟梦夣懜霥踎咪瞇冞弥祢迷猕谜蒾詸謎醚&amp;#34; , 
 &amp;#34;M擟糜縻麊麋靡獼麛爢戂攠蘼醾醿鸍釄米羋芈侎弭洣敉粎脒眯渳葞蝆蔝銤孊灖糸汨宓泌觅峚祕宻秘密淧覓覔幂谧塓幎覛嘧榓滵漞熐蔤蜜鼏冪樒幦濗藌謐櫁簚羃芇眠婂绵媔棉綿緜臱蝒嬵檰櫋&amp;#34; , 
 &amp;#34;M矈矊矏丏汅免沔黾俛勉眄娩偭冕勔喕愐湎缅葂腼緬鮸靣面糆麪麫麺麵喵苗媌描瞄鹋嫹鶓鱙杪眇秒淼渺缈篎緲藐邈妙庙竗庿廟吀咩哶孭灭搣滅蔑薎鴓幭懱瀎篾櫗蠛衊鑖鱴瓱民垊姄岷怋旻旼&amp;#34; , 
 &amp;#34;M玟苠珉盿冧罠崏捪琘琝缗暋瑉痻碈鈱緍緡錉鍲皿冺刡闵抿泯勄敃闽悯敏笢笽湣閔愍敯黽閩僶慜憫潣簢鳘蠠鰵名明鸣洺眀茗冥朙眳铭鄍嫇溟猽蓂暝榠銘鳴瞑螟覭佲姳凕慏酩命掵詺谬缪繆謬&amp;#34; , 
 &amp;#34;M摸嚤尛谟嫫馍摹模膜麼麽摩魹橅磨糢謨謩擵饃嚩蘑髍魔劘饝抹懡麿末劰圽妺怽歿殁沫茉陌帞昩枺皌眜眿砞秣莈莫眽粖絈袹蛨貃嗼塻寞漠蓦貊銆墨嫼暯瘼瞐瞙镆魩黙縸默貘藦蟔鏌爅驀礳纆&amp;#34; , 
 &amp;#34;M耱乮哞牟侔劺恈洠眸谋鉾謀鍪鴾麰某母毪獏氁亩牡姆拇峔牳畆畒胟畝畞砪畮鉧踇木仫目凩沐狇坶炑牧苜毣莯蚞钼募萺雮墓幕幙慔楘睦鉬慕暮艒霂穆鞪旀丆椧渑&amp;#34; , 
 &amp;#34;N懝抝拗秅莀袲唸毭咹児兒耏聏峊廾嫨跈聻茮澆涳巙崀尦竜袮彌镾濔瀰乜樢拏拿誽镎鎿乸哪雫内那吶妠纳肭娜衲钠納袦捺笝豽軜貀嗱蒳靹魶腉熋孻乃奶艿氖疓妳廼迺倷釢嬭奈柰耐萘渿鼐褦&amp;#34; , 
 &amp;#34;N螚錼囡男抩枏枬侽南娚畘莮难喃遖暔楠煵諵難赧揇湳萳腩蝻戁婻囔乪嚢囊鬞馕欜饢擃曩攮灢儾齉孬檂呶怓挠峱硇铙猱蛲詉碙嶩夒鐃巎獿垴恼悩脑匘脳堖惱嫐瑙腦碯闹婥淖閙鬧讷呐眲訥呢&amp;#34; , 
 &amp;#34;N馁腇餒鮾鯘氝焾嫩能莻鈪銰啱妮尼坭怩泥籾倪屔秜郳铌埿婗淣猊蚭棿跜鈮蜺觬貎霓鲵鯢麑齯臡伱伲你拟抳狔苨柅旎晲馜儞隬擬薿檷鑈氼迡昵胒逆匿痆眤堄惄嫟愵溺睨腻暱縌膩嬺拈年秊哖&amp;#34; , 
 &amp;#34;N秥鲇鮎鲶鵇黏鯰捻辇撚撵碾輦簐攆躎卄廿念姩埝娘嬢酿醸釀鸟茑袅嫋裊蔦嬝褭嬲尿脲捏揑帇圼苶枿陧涅聂臬啮惗隉敜嗫嵲踂摰踗踙镊镍嶭篞臲錜颞蹑鎳闑孼孽櫱籋蘖齧巕糱糵蠥囓讘躡鑷&amp;#34; , 
 &amp;#34;N顳脌囜您拰宁咛拧狞柠聍寍寕寜寧儜凝嚀嬣擰獰薴檸聹鑏鬡鸋橣矃佞侫泞甯寗澝濘妞牛牜忸扭沑狃纽杻炄钮紐鈕靵农侬哝浓脓秾農儂辳噥憹濃蕽禯膿穠襛醲欁繷弄挊挵癑齈羺譨啂槈耨鎒&amp;#34; , 
 &amp;#34;N鐞譳奴孥驽笯駑伮努弩砮胬怒傉搙女钕籹釹衂恧朒衄疟虐瘧奻渜暖煗餪硸黁燶郍挪梛傩搻儺橠诺喏掿逽搦锘榒稬諾糑懦懧糥穤糯恁蔫&amp;#34; , 
 &amp;#34;O吽摳噢哦筽夞乯鞰讴欧殴瓯鸥塸歐熰甌膒鴎櫙藲鏂鷗吘呕偶腢耦蕅藕怄沤慪漚&amp;#34; , 
 &amp;#34;P钯鈀跁罷猈螌褩闆湴牓棓徬鎊剝襃铇袌鉋鮑琲絣痭琣逬跰螕鎞粃枈痺辟稫箆鞞猵萹拚徧緶辯骉蔈颮麃藨謤穮驃驫摽汃砏璸鉼碆磻犻苩瓟桲淿湐猼馞嚗髆蚾獛鵏吥荹鈈郶茷籓膰趽彷衯夆馮&amp;#34; , 
 &amp;#34;P摓垺妚尃豧巿襆襥脯蜅秿鈲窌攈脟濼尨眫冖覕屰妑皅趴舥啪葩杷爬耙琶筢潖帊帕怕袙拍俳徘排猅棑牌箄輫簰犤哌派湃蒎鎃磗眅畨潘攀爿柈盘跘媻幋蒰搫槃磐縏蹒瀊蟠蹣鎜鞶坢冸判沜泮炍&amp;#34; , 
 &amp;#34;P叛牉盼畔袢詊溿頖鋬鵥襻鑻乓汸沗肨胮雱滂膖霶厐庞逄旁舽嫎篣螃鳑龎龐鰟蠭嗙耪覫髈炐胖抛拋脬刨咆垉庖狍炮炰爮袍匏蚫軳鞄褜麅跑奅泡疱皰砲萢麭礟礮呸怌肧柸胚衃醅阫陪陫培毰赔&amp;#34; , 
 &amp;#34;P锫裴裵賠錇俖伂沛佩帔姵斾旆浿珮配笩蓜辔馷嶏霈轡喷噴濆歕瓫盆湓葐呠翉翸喯匉怦抨泙恲胓砰梈烹硑軯閛漰嘭駍磞芃朋挷竼倗莑堋弸彭棚椖傰塜塳搒漨硼稝蓬鹏槰樥熢憉澎輣篷膨錋韸&amp;#34; , 
 &amp;#34;P髼蟚蟛鬅纄韼鵬騯鬔鑝捧淎皏剻掽椪碰踫浌巼闏乶喸丕伓伾批纰邳坯怶披抷炋狉狓砒悂秛秠紕铍旇翍耚豾鈚鈹鉟銔劈磇駓髬噼錃錍魾憵礔礕闢霹皮阰芘岯枇毞肶毗毘疲笓蚍郫陴啤埤崥蚽&amp;#34; , 
 &amp;#34;P豼椑焷琵脾腗榌鲏罴膍蜱隦魮壀鮍篺螷貔簲羆鵧朇鼙蠯匹庀仳圮苉脴痞銢諀鴄擗噽癖嚭屁淠渒揊媲嫓睤睥潎僻澼甓疈譬鷿鸊片囨偏媥犏篇翩鶣骈胼腁楄楩賆諚骿蹁駢騈覑谝貵諞骗魸騗騙&amp;#34; , 
 &amp;#34;P剽彯漂缥飘磦旚縹翲螵犥飃飄魒瓢薸闝殍瞟篻醥皫顠票僄勡嘌嫖徱慓氕撇撆暼瞥丿苤鐅嫳姘拼礗穦馪驞玭贫貧琕嫔频頻嬪薲嚬矉颦顰品榀朩牝汖娉聘乒甹俜涄砯艵竮頩平评凭呯坪岼苹郱&amp;#34; , 
 &amp;#34;P屏帡枰洴玶荓娦瓶屛帲淜萍蚲塀幈焩甁缾聠蓱蛢評軿鲆凴慿箳輧憑鮃檘簈蘋钋坡岥泼娝釙颇溌酦潑醱鏺婆嘙蔢鄱皤謈櫇叵尀钷笸鉕駊廹岶迫敀昢洦珀哱烞破砶粕蒪頗魄剖颒抔抙捊掊裒箁&amp;#34; , 
 &amp;#34;P咅哣婄犃兺哛仆攴扑抪炇巬巭柨陠痡铺駇噗撲鋪擈鯆圤匍莆菩菐葡蒱蒲僕酺墣璞濮瞨穙镤贌纀鏷朴圃埔浦烳普圑溥暜谱潽樸氆諩檏镨譜蹼鐠舖舗曝&amp;#34; , 
 &amp;#34;Q摮磝朁鸧鶬鼜詧軙儭櫬趍袳創敠匚釓隑矼肐鉤扢琯矔鸛龜氿肣馯抲頜礉隺渹舙酄攲敧稘毄緝觭禨鄿鐖饑焏踖躤蟣済萕濟袷唊脥價靬鳒鰜鶼鑯揃葥漸摪彊勥焳燋湫湬蟜譑峤嶠潐噭椄疌倢偼&amp;#34; , 
 &amp;#34;Q媫蛣楬鮚荕埐嶜厪墐慬歏濅涇鶄捄趄跔鮈跼趜弆瞿鐻捲弮蚗傕鶌躩麏麕焌箘開欿歁殻揢挳硜矻誇厱熑燫艌鳥毆七迉沏妻柒倛凄栖桤缼郪娸悽戚捿桼淒萋朞期欺紪褄僛嘁慽榿槭漆緀慼磎諆&amp;#34; , 
 &amp;#34;Q霋蹊魌鏚鶈亓祁齐圻岐岓芪其奇斉歧祈肵疧竒剘斊旂耆脐蚑蚚颀埼崎帺掑淇渏猉畦萁跂軝釮骐骑棊棋琦琪祺蛴愭碁碕褀頎鬾鬿旗粸綥綦綨緕蜝蜞璂禥蕲踑螧鲯懠濝藄檱櫀簱臍騎騏鳍蘄鯕&amp;#34; , 
 &amp;#34;Q鵸鶀麒籏纃艩蠐鬐騹魕鰭玂麡乞邔企屺岂芑启呇杞玘盀唘豈起啓啔啟婍绮晵棨綮諬簯闙气讫気汔迄弃汽矵芞呮泣炁盵咠契砌荠栔訖唭欫夡愒棄湆湇葺碛摖暣甈碶噐憇器憩磜磧薺礘罊蟿掐&amp;#34; , 
 &amp;#34;Q葜拤跒酠鞐圶冾帢恰洽殎硈愘髂千仟阡奷扦汘芊迁佥岍杄汧茾竏钎拪牵粁悭蚈谸铅婜牽釺谦雃僉愆签骞鹐搴摼撁箞諐遷褰顅檶攐攑櫏簽鏲鵮攓騫鐱鬜鬝籤韆仱岒忴扲拑乹前钤歬虔钱钳乾&amp;#34; , 
 &amp;#34;Q偂掮揵軡媊鈐鉗墘榩箝銭潜橬錢黔鎆黚騝濳騚灊籖鰬浅肷淺嵰慊遣蜸潛谴缱繾譴鑓欠刋芡茜倩悓堑傔嵌棈椠皘蒨塹歉蔳儙槧篏輤篟壍嬱縴呛羌戕戗斨枪玱猐琷跄嗴椌獇腔嗆溬蜣锖嶈戧槍&amp;#34; , 
 &amp;#34;Q牄瑲羫锵篬錆蹌镪蹡鎗鏘鏹強强墙嫱蔷樯漒蔃墻嬙檣牆謒艢蘠抢羟搶羥墏摤繈襁繦炝唴熗羻兛瓩悄硗郻鄗嵪跷鄡鄥劁敲踍锹墝碻頝墽幧橇缲磽鍫鍬繑趬蹺蹻乔侨荍荞桥硚喬僑槗谯嘺嫶憔&amp;#34; , 
 &amp;#34;Q蕎鞒樵橋犞癄瞧礄藮譙趫鐈鞽顦巧釥愀髜俏诮陗峭帩窍殼翘誚髚僺撬鞘竅翹躈切苆癿茄聺且厒妾怯匧窃倿悏挈洯惬淁笡愜蛪朅箧緁锲魥篋踥穕藒鍥鯜鐑竊籡亲侵钦衾骎菳媇嵚誛嶔親顉駸&amp;#34; , 
 &amp;#34;Q鮼寴庈芩芹埁珡矝秦耹菦蚙捦琴琹禽鈙雂勤嗪溱靲噙擒斳鳹懄檎澿瘽螓懃蠄坅昑笉梫赾寑锓寝寢鋟螼吢吣抋沁唚菣揿搇撳瀙藽靑青氢轻倾卿郬圊氫淸清傾廎蜻輕鲭鑋夝甠剠勍情殑硘晴棾&amp;#34; , 
 &amp;#34;Q氰葝暒擏樈擎檠黥苘顷请庼頃漀請檾謦庆凊掅碃箐靘慶磬儬濪罄櫦宆跫銎卭邛穷穹茕桏笻筇赹惸焪焭琼舼蛩蛬煢熍睘瞏窮儝憌橩璚藑竆藭丘丠邱坵恘秋秌寈蚯媝萩楸鹙篍緧蝵穐趥鳅蟗鞦&amp;#34; , 
 &amp;#34;Q鞧蘒鰌鰍鶖龝叴囚扏犰玌朹肍求虬泅虯俅觓訄訅酋唒浗紌莍逎逑釚梂殏毬球赇釻崷巯湭皳盚遒煪絿蛷裘巰觩賕璆蝤銶醔鮂鼽鯄鵭蠤鰽搝糗区曲佉匤岖诎阹驱坥屈岴抾浀祛胠袪區蛆躯筁粬&amp;#34; , 
 &amp;#34;Q蛐詘趋嶇駆憈敺誳駈麹髷趨麯軀麴黢驅鰸鱋佢劬斪朐菃衐鸲淭渠絇葋軥蕖璖磲螶鴝璩翵蟝鼩蘧匷忂灈戵欋氍籧臞癯蠷衢躣蠼鑺鸜取竘娶紶詓竬龋齲厺去刞呿迲郥耝阒觑趣閴麮闃覰覷鼁覻&amp;#34; , 
 &amp;#34;Q峑悛圈圏棬駩騡鐉全权佺诠姾泉洤荃拳牷辁啳埢婘惓痊硂铨湶犈筌絟腃葲搼楾瑔觠詮輇蜷銓権踡縓醛闎鳈鬈孉巏鰁權齤蠸颧顴犬汱畎烇绻綣虇劝券巻牶椦勧韏勸炔缺蒛瘸却埆崅悫雀硞确&amp;#34; , 
 &amp;#34;Q阕塙搉皵阙鹊愨榷墧慤毃確趞燩闋礐闕鵲礭夋囷峮逡宭帬裙羣群裠郄&amp;#34; , 
 &amp;#34;R吺兊兌熯卪坈繚髳挐鈉柟蟯臑抐內涊蹨孃菍莥獳檽蹃亽罖囕呥肰衻袇蚦袡蚺然髥嘫髯燃繎冄冉姌苒染珃媣蒅穣瀼獽禳瓤穰躟鬤壌嚷壤攘爙让懹譲讓荛饶桡橈襓饒犪扰娆隢擾绕遶繞惹热熱&amp;#34; , 
 &amp;#34;R人仁壬忈朲忎秂芢鈓魜銋鵀忍荏栠栣荵秹稔綛躵刃刄认仞仭讱任屻扨纫妊杒牣纴肕轫韧饪姙紉衽紝訒軔梕袵絍腍靭靱韌飪認餁扔仍辸礽芿陾日驲囸釰鈤馹戎肜栄狨绒茙茸荣容峵毧烿媶嵘&amp;#34; , 
 &amp;#34;R絨羢嫆搈搑摉榵溶蓉榕榮熔瑢穁蝾褣镕氄縙融螎駥髶嬫嶸爃鎔瀜曧蠑冗宂傇軵穃厹禸柔粈媃揉渘葇瑈腬糅蝚蹂輮鍒鞣瓇騥鰇鶔楺煣韖肉宍嶿邚如侞帤茹桇袽铷渪筎蒘銣蕠儒鴑嚅嬬孺濡薷&amp;#34; , 
 &amp;#34;R鴽曘燸襦蠕颥醹顬鱬汝肗乳辱鄏入扖込杁洳嗕媷溽缛蓐鳰褥縟擩堧撋壖阮朊软耎偄軟媆愞瑌腝嫰碝緛蝡輭瓀礝桵甤緌蕤蕊蕋橤繠蘂蘃芮枘蚋锐瑞睿叡壡闰润閏閠潤橍叒若偌弱鄀婼渃焫楉&amp;#34; , 
 &amp;#34;R嵶蒻箬篛爇鰙鰯鶸&amp;#34; , 
 &amp;#34;S鉍灬杓攃偲纔參叄叅喰傪穇懆鄵拺笧粣鎈褨剎摻攙摌顫塲場綝乗娍匙飭埫醻敊猭漺輴縒棇楤漎憁缞縗鎝単單擔伔僤宲鍉遞遰挕阇闍陏蘴棴丨鞨咶鏸韢閄靃濈櫼帴菨嫅潏麗攦療蕯瀧氀稤蠰&amp;#34; , 
 &amp;#34;S娞淰掱忯圱圲凵廧薔鐰韒鞩嫀殸棯葚挼仨桬撒洒訯靸潵卅飒脎萨摋隡馺颯薩櫒栍毢愢揌塞毸腮嘥噻鳃顋嗮赛僿賽簺虄三弎叁毵毶厁毿犙鬖壭伞傘散糁糂馓橵糝糣糤繖鏒饊俕閐桒桑槡嗓搡&amp;#34; , 
 &amp;#34;S磉褬颡鎟顙丧喪掻慅搔溞骚缫臊鳋颾騒鰠鱢扫掃嫂埽瘙氉矂髞色栜涩啬渋铯歮琗嗇瑟歰銫澁懎擌濇濏瘷穑澀璱瀒穡繬穯轖鏼譅飋裇聓森槮襂僧鬙閪縇杀沙纱乷砂唦挱猀粆紗莎铩痧硰蔱裟&amp;#34; , 
 &amp;#34;S樧魦鲨閷鎩鯊鯋繺傻儍繌倽唼啥帹萐喢歃煞翜翣閯霎筛篩簁簛晒曬山彡邖圸删刪杉杣芟姗衫钐埏狦珊舢痁脠軕笘閊跚剼搧嘇幓煽蔪潸澘曑檆膻鯅羴羶闪陕炶陝閃晱煔睒熌覢讪汕疝苫扇訕&amp;#34; , 
 &amp;#34;S赸傓善椫銏骟僐鄯墠墡缮嬗擅敾樿膳磰謆赡繕蟮譱贍鐥饍騸鳝灗鱔伤殇商觞傷墒慯滳蔏殤熵螪觴謪鬺裳垧扄晌赏賞鑜丄上仩尙尚恦绱緔弰捎梢烧焼稍旓筲艄蛸輎蕱燒髾鮹勺芍柖玿韶少劭&amp;#34; , 
 &amp;#34;S卲邵绍哨娋袑紹綤潲奢猞赊畲輋賒賖檨舌佘蛇蛥舍捨厍设社舎厙射涉涻渉設赦弽慑摄滠慴摵蔎蠂韘騇懾灄麝欇申屾扟伸身侁呻妽籶绅罙诜柛氠珅穼籸娠峷甡眒砷堔深紳兟椮葠裑訷罧蓡詵&amp;#34; , 
 &amp;#34;S甧蔘燊薓駪鲹鯓鵢鯵鰺神榊鉮鰰邥弞抌沈审矤哂矧宷谂谉婶渖訠審諗頣魫曋瞫嬸瀋覾讅肾侺昚甚胂涁眘渗祳脤腎愼慎椹瘆蜃滲鋠瘮升生阩呏声斘昇枡泩苼殅牲珄竔胜陞曻陹笙湦焺甥鉎聲&amp;#34; , 
 &amp;#34;S鍟鼪鵿绳憴澠譝省眚偗渻圣晟晠剰盛剩勝貹嵊聖墭榺蕂橳賸尸失师呞虱诗邿鸤屍施浉狮師絁湤湿葹溮溼獅蒒蓍詩瑡酾鳲蝨鳾褷鲺鍦鯴鰤鶳襹籭釃十饣什石辻佦时竍识实実旹飠峕拾炻祏蚀&amp;#34; , 
 &amp;#34;S食埘時莳寔湜遈塒嵵溡蒔榯蝕鉽篒鲥鮖鼫鼭鰣史矢乨豕使始驶兘屎笶榁鉂駛士氏礻世丗仕市示卋式叓事侍势呩柹视试饰冟室恀恃拭是枾柿眂贳适栻烒眎眡舐轼逝铈視釈崼弑揓谥貰释勢嗜&amp;#34; , 
 &amp;#34;S弒煶睗筮觢試軾鈰飾舓誓奭噬嬕澨諟諡遾餝螫簭籂襫鰘兙瓧収收手守垨首艏寿受狩兽售授绶痩膄壽瘦綬夀獣獸鏉书殳抒纾叔杸枢陎姝柕倏倐書殊紓掓梳淑焂菽軗鄃疎疏舒摅毹毺綀输跾踈&amp;#34; , 
 &amp;#34;S樞蔬輸橾鮛攄瀭鵨尗秫婌孰赎塾熟璹贖暏暑黍署鼠鼡蜀潻薯曙癙襡糬襩籔蠴鱪鱰朮术戍束沭述侸怷树竖荗恕庶庻絉蒁術裋数竪腧墅漱潄數澍豎樹濖錰鏣鶐虪刷唰耍誜衰摔甩帅帥蟀卛闩拴&amp;#34; , 
 &amp;#34;S閂栓涮腨双滝霜雙孀骦孇騻欆礵鷞鹴艭驦鸘爽塽慡樉縔鏯灀谁脽誰氵水氺閖帨涗涚祱税裞睡吮楯顺舜順蕣橓瞚瞤瞬鬊说妁烁朔铄欶硕矟嗍搠蒴嗽槊碩鎙厶丝司糹私咝泀俬思恖鸶媤斯絲缌&amp;#34; , 
 &amp;#34;S蛳楒禗鉰飔凘厮榹禠罳銯锶嘶噝廝撕澌緦蕬螄鍶蟖蟴颸騦鐁鷥鼶死巳亖四罒寺汜伺似佀兕姒泤祀価孠泗饲驷俟娰柶牭梩洍涘肂飤笥耜釲竢覗嗣肆貄鈻飼禩駟蕼儩騃瀃螦乺忪松枀枩娀柗倯&amp;#34; , 
 &amp;#34;S凇梥崧庺淞菘嵩硹蜙憽檧濍鬆怂悚捒耸竦傱愯嵷慫聳駷讼宋诵送颂訟頌誦餸鎹凁捜鄋嗖廀廋搜溲獀蒐蓃馊飕摗锼艘螋醙鎪餿颼騪叟傁嗾瞍擞薮擻藪櫢瘶苏甦酥稣窣穌鯂蘇蘓櫯囌俗玊夙诉&amp;#34; , 
 &amp;#34;S泝肃洬涑珟素速殐粛骕傃粟訴谡嗉塐塑嫊愫溯溸肅遡鹔僳愬榡膆蔌觫趚遬憟樎樕潥鋉餗縤璛簌藗謖蹜驌鱐鷫狻痠酸匴祘笇筭蒜算夊芕虽倠哸浽荽荾眭葰滖睢熣濉鞖雖绥隋随遀綏隨瓍膸瀡&amp;#34; , 
 &amp;#34;S髄髓亗岁砕祟粋谇埣嵗脺遂歲歳煫碎隧嬘澻穂誶賥檖燧璲禭穗穟繀襚邃旞繐繸鐆譢鐩孙狲荪飧搎猻蓀飱槂蕵薞畃损笋隼損榫箰鎨巺潠唆娑莏傞挲桫梭睃嗦羧蓑摍缩趖簑簔縮髿鮻所唢索琐&amp;#34; , 
 &amp;#34;S琑惢锁嗩暛溑瑣鎍鎖鎻鏁逤溹蜶厦忄莘疋栅属&amp;#34; , 
 &amp;#34;T諳啚裧儃禪蟬繵閶瞋鐺珵侱漦爞綢籌俶埱蓴鶉鈶撘迏迖沓荅逹溚達鎉韃呔蚮軚貸癉撣嘾彈餤黨攩欓逿蕩簜蘯闣朷焘燾僜奃髢詆弚苐媂諦顚顛鈿调蓧啑惵趃奵忊墥峝湩詷钭鋀褍蜳橔囤庉憞&amp;#34; , 
 &amp;#34;T燉軃鋨鞈騩咍漢宊她冂燑轁墤謉饋噋擴斄伖鍩奤嵜鉆汭蟺鱓愓漡苕萔姼忕徥褆扌涭瑹儵稅磃鋖枱他它牠祂咜趿铊塌榙溻褟蹹侤塔墖獭鮙鳎獺鰨挞狧闼崉涾搨遝遢阘榻毾禢撻澾誻踏嚃錔嚺&amp;#34; , 
 &amp;#34;T濌蹋鞜闒鞳闥譶躢襨囼孡骀胎台邰坮抬苔炱炲跆鲐箈臺颱儓鮐嬯擡薹檯籉太冭夳忲汰态肽钛泰粏舦酞鈦溙態燤坍贪怹啴痑舑貪摊滩嘽潬瘫擹攤灘癱坛昙倓谈郯婒惔弾覃榃痰锬谭墰墵憛潭&amp;#34; , 
 &amp;#34;T談醈壇曇檀顃罈藫壜譚貚醰譠罎鷤忐坦袒钽菼毯鉭嗿憳憻暺醓璮叹炭埮探傝湠僋嘆碳舕歎賧汤铴嘡劏羰蝪薚镗蹚鏜鐋鞺鼞饧坣唐堂傏啺棠鄌塘嵣搪溏蓎隚榶漟煻瑭禟膅樘磄糃膛橖篖糖螗&amp;#34; , 
 &amp;#34;T踼糛螳赯醣鎕餹闛饄鶶帑倘偒淌傥耥躺镋鎲儻戃曭爣矘钂烫摥趟燙仐夲弢涛绦掏絛詜嫍幍慆搯滔槄瑫韬飸縚縧濤謟鞱韜饕迯咷洮逃桃陶啕梼淘绹萄祹裪綯蜪鞀醄鞉鋾錭駣檮騊鼗讨套討畓&amp;#34; , 
 &amp;#34;T忑忒特貣脦铽慝鋱蟘膯鼟疼痋幐腾誊漛滕邆縢螣駦謄儯藤騰籐鰧籘虅驣霯唞朰剔梯锑踢銻鷈鷉厗绨偍珶啼崹惿提渧稊缇罤遆鹈嗁瑅綈碮徲漽緹蕛蝭题趧蹄醍謕蹏鍗鳀題鮷鵜騠鯷鶗鶙体挮&amp;#34; , 
 &amp;#34;T躰骵軆體戻屉剃洟倜悌涕逖悐惕掦逷惖揥替楴裼褅殢髰嚏鬀瓋鬄籊天兲婖添酟靔黇靝田屇沺恬畋畑胋畠甛甜菾湉填搷阗碵緂磌窴鴫璳闐鷆鷏忝殄倎唺悿捵淟晪琠腆觍痶睓舔餂覥賟錪靦掭&amp;#34; , 
 &amp;#34;T瑱睼舚旫佻庣挑祧聎芀条岧岹迢祒條笤蓚龆樤蜩鋚鞗髫鲦螩鯈鎥齠鰷宨晀朓脁窕誂窱嬥眺粜絩覜趒跳頫糶贴萜貼铁蛈僣鴩鐡鐵驖呫帖飻餮厅庁汀艼听耓厛烃烴綎鞓聴聼廰聽廳邒廷亭庭莛&amp;#34; , 
 &amp;#34;T停婷嵉渟筳葶蜓楟榳閮霆聤蝏諪鼮圢侹娗挺涏梃烶珽脡艇颋誔鋌頲濎乭囲炵通痌嗵蓪樋熥仝同佟彤峂庝哃狪茼晍桐浵烔砼蚒眮秱铜童粡絧衕酮鉖僮勭銅餇鲖潼曈朣橦氃犝膧瞳鮦统捅桶筒&amp;#34; , 
 &amp;#34;T統綂恸痛慟憅偷偸鍮头投骰頭妵紏敨斢黈蘣透凸禿秃怢突唋涋捸堗湥痜葖嶀鋵鵚鼵図图凃峹庩徒捈涂荼途屠梌揬稌塗嵞瘏筡腯蒤鈯圖圗廜跿酴馟鍎駼鵌鶟鷋鷵土圡吐汢钍釷兎迌兔莵堍菟&amp;#34; , 
 &amp;#34;T鵵湍猯煓貒团団抟團慱槫檲鏄糰鷒鷻圕疃彖湪褖推蓷藬颓隤頹頺頽魋穨蘈蹪俀脮腿僓蹆骽退娧煺蜕褪駾吞呑朜焞暾黗屯芚饨豘豚軘鲀魨霕臀臋氽畽坉乇讬托汑饦侂咃拕拖沰侻莌袥託涶脫&amp;#34; , 
 &amp;#34;T脱飥魠驮佗陀坨岮沱驼柁砣砤袉鸵紽堶跎酡碢馱槖駄踻駝駞橐鮀鴕鼧騨鼍驒鼉妥毤庹媠椭楕嫷橢鵎拓柝唾跅毻箨籜&amp;#34; , 
 &amp;#34;U辪癷袰蝊曢聣烪燞躼蒊蓞耂稥洜毜毝茒桛毮朑焽虲鶑鎼鐢艈霻闧焑屗歚徚鍂藔贘皼斏聁祍&amp;#34; , 
 &amp;#34;W趡惡噁唲陚龏萖関闗關貫窐姽恑瞶咼堝濄幠膴鋘譁瀤綄朚撝蒦嚄擭雘艧扝噲抂巋磈薶槾鄤澫堥夘呅韎雺霿沕忞鴖譕帓歾靺瞴蟱墲娒孯掔瓗渞蜹捼琞亠撱鰖屲劸哇娃徍挖洼娲畖窊媧嗗蛙搲&amp;#34; , 
 &amp;#34;W溛漥窪鼃攨瓦佤邷咓瓲砙袜嗢腽膃襪韈韤歪喎竵崴外弯剜婠帵塆湾睕蜿潫豌彎壪灣丸刓汍纨芄完岏忨抏玩笂紈捖顽烷琓貦頑邜宛倇唍挽晚盌埦婉惋晩梚绾脘菀晼椀琬皖畹碗綩綰輓踠鋔鍐&amp;#34; , 
 &amp;#34;W万卍卐杤捥腕萬翫鋄薍錽贃鎫贎尩尪尫汪亡亾兦王仼彺莣蚟网忹往徃枉罔惘菵暀棢焹蛧辋網蝄誷輞瀇魍妄忘迋旺盳望朢危威烓偎逶隇隈喴媁媙愄揋揻渨煀葨葳微椳楲溦煨詴縅蝛覣嶶薇鳂&amp;#34; , 
 &amp;#34;W癐巍鰃鰄囗为韦围帏沩违闱峗峞洈為韋桅涠唯帷惟维喡圍嵬幃湋溈爲違潍蓶鄬潙潿濰鍏闈鮠癓覹犩霺伟伪尾纬芛苇委炜玮洧娓捤浘荱诿偉偽崣梶硊萎隗骩嵔廆徫愇猥葦蒍骪骫暐椲煒瑋痿&amp;#34; , 
 &amp;#34;W腲艉韪僞碨蜲蜼鲔寪緯蔿諉踓韑頠儰濻鍡鮪壝韙颹瀢亹斖卫未位味苿畏胃軎尉硙菋谓喂媦渭猬煟墛蔚慰熭犚磑緭蝟衛懀濊璏罻衞謂餧鮇螱褽餵魏藯轊鏏霨鳚蘶饖讆躗讏躛昷塭温殟溫瑥榲&amp;#34; , 
 &amp;#34;W瘟豱鳁鎾饂鰛鰮文彣纹芠炆砇闻紋蚉蚊珳阌鈫雯瘒聞馼魰鳼鴍螡閺閿蟁闅鼤闦刎吻呚忟抆呡肳紊桽脗稳穏穩问妏汶莬問渂脕揾搵絻顐璺翁嗡鹟螉鎓鶲奣塕嵡滃蓊暡瞈聬瓮蕹甕罋齆挝倭涡&amp;#34; , 
 &amp;#34;W莴唩涹渦猧萵喔窝窩蜗蝸踒我婐婑捰仴沃肟卧臥偓媉幄握渥焥硪楃腛斡瞃濣瓁龌齷乌圬弙污邬呜杇巫屋洿诬钨趶剭窏釫鄔嗚誈誣箼螐鴮鎢鰞无毋吴吾呉芜梧洖浯茣莁珸祦鹀無禑蜈蕪璑鵐&amp;#34; , 
 &amp;#34;W鯃鼯鷡乄五午仵伍坞妩庑忤怃迕旿武玝侮俉倵捂啎娬牾珷塢摀熓碔鹉瑦舞嫵廡憮潕錻儛橆甒鵡躌兀勿务戊阢伆屼扤岉杌芴忢物矹敄误務悞悟悮粅逜晤焐婺嵍痦隖靰骛奦嵨溩雾寤熃誤鹜鋈&amp;#34; , 
 &amp;#34;W窹霚鼿霧齀蘁騖鶩&amp;#34; , 
 &amp;#34;X欸庍壆扱烲愖糦臰欪滀嘼錯廗諜摡給蚼規嶲鮭巂鬹咁譀迒茠滈欱郃螛嗃熇燺揈閧闀闂鬨銗謼滸芐觟懁郇狟澴還镮鐶儶譮孈葷轋掝擊彐蔇縘繫夾埉浹傢裌叚徦鰔梘筧礆見閒瞯鵁轇驕絞較湝&amp;#34; , 
 &amp;#34;X頡觧吤繲坙巠坓顈眗鼰鼳鋗絹獧決泬勪噱姰濬愾埳堿闞晇欵歀潰搚懢壏嘮釐溓蘝蘞稴漻衖莔禰瓕賯撓譊鉨鉩煖謳嘔盤嚊恓棲諿氣欦臤慳荨羬蕁槏伣俔嗛骹燆睄綅瓊蓲鱃魼胊卻舃碏儴勷蘘&amp;#34; , 
 &amp;#34;X纕繻灑钑鈒鰓騷雭殺榝姍釤縿莦颵姺濕宩昰笹齛咰鉥獡箾蜤燍叜宿碿潚橚孫鶽橝撢餳饀屜歒盷蓨赨緰圩韡捾夕兮忚汐西覀吸希卥昔析矽穸肸肹俙徆怸郗饻唏奚娭屖息悕晞氥浠牺狶莃唽悉&amp;#34; , 
 &amp;#34;X惜桸欷淅渓烯焁焈琋硒菥赥釸傒惁晰晳焟犀睎稀粞翕翖舾鄎厀嵠徯溪煕皙蒠锡僖榽熄熙緆蜥豨餏嘻噏嬆嬉瘜膝餙凞樨橀歙熹熺熻窸羲螅螇錫燨犠瞦礂蟋谿豀豯貕繥雟鯑鵗觹譆醯鏭隵巇曦&amp;#34; , 
 &amp;#34;X爔犧酅觽鼷蠵鸂觿鑴习郋席習袭觋媳椺蒵蓆嶍漝覡趘槢蝷薂隰檄謵鎴霫鳛飁騱騽襲鰼驨枲洗玺徙铣喜葈葸鈢屣漇蓰銑憘憙暿橲禧諰壐縰謑蟢蹝璽鱚矖纚躧匸卌戏屃系饩呬忥怬细係恄盻郤&amp;#34; , 
 &amp;#34;X欯绤細釳阋塈椞舄趇隙慀滊禊綌赩隟熂犔稧戯潟澙蕮覤戱黖戲磶虩餼鬩嚱闟霼衋虾谺傄閕敮煆颬瞎蝦鰕匣侠狎俠峡柙炠狭陜峽烚狹珨祫硖笚翈舺陿溊硤遐搳暇瑕筪碬舝辖縀蕸縖赮魻轄鍜&amp;#34; , 
 &amp;#34;X霞鎋黠騢鶷閜丅下吓圷疜夏梺廈睱諕嚇懗罅夓鏬仙仚屳先奾纤佡忺氙杴祆秈苮籼珗莶掀铦跹酰锨僊僲嘕銛鲜暹韯憸鍁繊褼韱鮮馦蹮孅廯攕譣纎鶱襳躚纖鱻伭咞闲妶弦贤咸挦涎胘娴娹婱絃&amp;#34; , 
 &amp;#34;X舷蚿衔啣痫蛝閑鹇嫌甉銜嫺嫻憪撏澖誸賢諴輱醎癇癎藖鹹礥贒鑦鷳鷴鷼冼狝显险毨烍猃蚬険赻筅尟尠搟禒蜆跣箲獫獮藓鍌燹顕幰攇櫶蘚玁韅顯灦县岘苋现线臽限姭宪県陥哯垷娊娨峴晛涀&amp;#34; , 
 &amp;#34;X莧陷現馅睍絤缐羡献粯腺僩僴綫誢撊線鋧憲橌縣錎餡豏瀗臔獻糮鏾霰鼸乡芗相香郷厢啌鄉鄊廂湘缃葙鄕楿薌箱緗膷襄忀骧麘欀瓖镶鱜鑲驤瓨佭详庠栙祥絴翔跭享亯响蚃饷晑飨想銄餉鲞嚮&amp;#34; , 
 &amp;#34;X蠁鯗響饗饟鱶向姠巷项珦象缿萫項像勨嶑曏橡襐蟓鐌鱌灱灲呺枭侾削哓枵骁宯宵庨恷消绡虓逍鸮啋婋梟焇猇萧痚痟硝硣窙翛萷销揱綃嘐歊潇箫踃嘵憢撨獢銷霄彇膮蕭魈鴞穘簘藃蟂蟏謞鴵&amp;#34; , 
 &amp;#34;X嚣瀟簫蟰髇嚻囂櫹髐鷍蠨驍毊虈洨郩崤淆訤誵小晓暁筱筿皛曉篠謏皢孝肖効咲恔俲哮效校涍笑啸傚敩滧詨嘋嘨誟嘯歗熽斅斆些楔歇蝎蠍劦协旪邪協胁垥奊恊拹挾脅脇脋衺偕斜谐猲絜翓嗋&amp;#34; , 
 &amp;#34;X愶携瑎綊熁膎勰撷擕緳缬蝢鞋諧燲擷鞵襭攜纈讗龤写冩寫藛伳灺泄泻祄绁缷卸炧炨卨娎屑屓偰徢械焎禼亵媟屟揳渫絬谢僁塮榍榭褉噧屧暬韰嶰廨懈澥獬糏薢薤邂燮褻謝夑瀉瀣爕蟹蠏齘齥&amp;#34; , 
 &amp;#34;X齂躠屭躞心邤妡忻芯辛昕杺欣盺俽惞鈊锌新歆廞噷噺嬜薪馨鑫馫枔鬵鐔伈潃阠伩囟孞炘信軐脪衅訫焮馸舋顖釁兴狌星垶骍惺猩煋瑆腥蛵觪箵篂興謃曐觲騂皨刑邢形陉侀郉哘型洐钘陘娙硎&amp;#34; , 
 &amp;#34;X裄铏鈃鉶銒鋞睲醒擤杏姓幸性荇倖莕婞悻涬塂緈嬹臖凶兄兇匈芎讻忷汹哅恟洶胷胸訩詾雄熊诇詗夐敻休俢修咻庥烋烌羞脙鸺臹貅馐樇銝髤髹鎀鮴鵂饈鏅飍苬朽綇滫糔秀岫珛绣袖琇锈溴綉&amp;#34; , 
 &amp;#34;X璓裦螑繍繡鏥鏽齅戌旴疞盱欨胥须訏顼虗虚谞媭幁揟欻虛須楈窢頊嘘稰需魆噓墟嬃歔縃蕦蝑歘諝譃魖驉鑐鬚俆徐蒣许呴姁诩冔栩珝偦許湑暊詡鄦糈醑盨旭伵序汿侐卹沀叙恤昫洫垿欰殈烅&amp;#34; , 
 &amp;#34;X珬勖勗敍敘烼绪续酗喣壻婿朂溆絮訹嗅慉煦続蓄賉槒漵潊盢瞁緒聟銊稸緖瞲藚續蓿吅轩昍咺宣晅軒梋谖喧塇媗愃愋揎萱萲暄煊瑄蓒睻儇禤箮翧蝖嬛蕿諠諼鍹駽矎翾藼蘐蠉譞鰚讂玄玹痃悬&amp;#34; , 
 &amp;#34;X旋琁蜁嫙漩暶璇檈璿懸选烜暅選癣癬怰泫昡炫绚眩袨铉琄眴衒渲絢楦鉉碹蔙镟鞙颴縼繏鏇贙疶蒆靴薛鞾穴斈乴坹学岤峃茓泶袕鸴踅學嶨澩燢觷雤鷽雪樰膤艝轌鳕鱈血吷怴泧狘疦桖烕谑趐&amp;#34; , 
 &amp;#34;X謔瀥坃勋埙焄勛塤熏窨蔒勲勳薫駨嚑壎獯薰曛燻臐矄蘍壦爋纁醺寻巡旬驯杊询峋恂洵浔紃荀栒桪毥珣偱尋循揗詢馴鄩鲟噚攳樳燂燅燖璕襑蟳鱏鱘灥卂训讯伨汛迅侚徇狥迿逊殉訊訓訙奞巽&amp;#34; , 
 &amp;#34;X殾遜愻賐噀蕈顨鑂吁&amp;#34; , 
 &amp;#34;Y叆賹礙譺靉菴媕葊痷闇鵪鶕晻洝媼澚墺驁頨瑒耛拸呾訑婸潒扚昳屵姶堊搤閼煾妋鳱輵夃焸蠱溎裷緷蟈淊嚛欥瓛輐喛揘韹熀袆煇褘蚘噦矆拁玪豜豣將侥烄僥伒莖俓泂揂圧僪貗飬妜焆鐍炏顑&amp;#34; , 
 &amp;#34;Y丂髺樂貍櫟躒輅擽嫚玅桙獶輗掜孴儗肀喦噛槷嚙钀汼齵堷踦锜錡裿綺鉛膁羗撽赺欽汓翑蝺輑橪蕘嬈嵤銳鋭挻烻剡虵縄繩鱦釶鉇箷戺謚釋哾說説爍鑠梀筍鉈珆旲錟湯匋鴺趯恌銕桯筩婾媮殕&amp;#34; , 
 &amp;#34;Y悇蛻涒扡挩捝狏迱詑彵啘乛涴妧尣燰琟維厃痏薳叞榅辒輼轀勜臒汙汚烏歍吳郚娪焬熈誒歖潝疨磍嬐薟唌湺衘崄險嶮硍羨麲詳峫鐷洩紲絏緤訢脩褎褏銹獝藇鱮楥辥廵潯丫压呀庘押鸦桠鸭孲&amp;#34; , 
 &amp;#34;Y铔椏鴉錏鴨壓鵶鐚牙伢岈芽厓枒琊笌蚜堐崕崖涯猚瑘睚衙漄齖厊庌哑唖啞痖雅瘂蕥劜圠亚穵襾讶亜犽迓亞玡垭娅挜砑俹氩埡婭掗訝揠氬猰聐圔稏窫齾咽恹剦烟珚胭偣崦淹焉菸阉湮腌傿煙&amp;#34; , 
 &amp;#34;Y鄢嫣漹嶖樮醃閹嬮篶懕臙黫讠円延闫严妍芫言訁岩昖沿炎郔姸娫狿研莚娮盐琂硏訮閆阎嵒嵓筵綖蜒塩揅楌詽碞蔅颜虤閻厳檐顏顔嚴壛巌簷櫩麙壧孍巖巗巚欕礹鹽麣夵抁沇乵兖奄俨兗匽弇&amp;#34; , 
 &amp;#34;Y衍偃厣掩眼萒郾酓嵃愝扊揜棪渰渷琰遃隒椼硽罨裺演褗戭蝘魇噞躽縯檿黡厴甗鰋鶠黤齞龑儼黬黭顩鼴巘曮魘鼹齴黶厌妟觃牪姲彥彦砚唁宴晏艳覎验偐掞焔谚隁喭堰敥焰焱猒硯葕雁椻滟鳫&amp;#34; , 
 &amp;#34;Y厭墕暥熖酽嬊谳餍鴈燄燕諺赝鬳曕鴳酀騐験嚥嬿艶贋軅爓醶騴鷃灔贗觾讌醼饜驗鷰艷灎釅驠灧讞豓豔灩央咉姎抰泱殃胦眏秧鸯鉠雵鞅鍈鴦扬羊阦阳旸杨炀佯劷氜疡钖飏垟徉昜洋羏烊珜眻&amp;#34; , 
 &amp;#34;Y陽崵崸揚蛘敭暘楊煬禓瘍諹輰鍚鴹颺鐊鰑霷鸉卬仰佒坱奍岟养炴氧痒紻傟楧軮慃氱羪養駚懩攁瀁癢礢怏柍恙样羕詇様漾樣幺夭吆妖枖祅訞喓葽楆腰鴁邀爻尧尭肴垚姚峣轺倄烑珧窑傜堯揺&amp;#34; , 
 &amp;#34;Y殽谣軺嗂媱徭愮搖摇猺遙遥摿暚榣瑤瑶銚飖餆嶢嶤徺磘窯窰餚繇謠謡鳐颻蘨顤鰩仸宎岆抭杳殀狕苭咬柼眑窅窈舀偠婹崾溔榚鴢闄騕齩鷕穾药要袎窔筄葯詏熎覞靿獟鹞薬鼼曜燿艞藥矅曣耀&amp;#34; , 
 &amp;#34;Y纅鷂讑鑰倻椰暍噎潱蠮爷耶捓揶铘爺釾鋣鎁擨也吔亪冶埜野嘢漜壄业叶曳页邺夜抴亱枼洂頁晔枽烨掖液谒堨殗腋葉鄓墷楪業馌僷曄曅歋燁擛皣瞱鄴靥嶪嶫澲謁餣嚈擫曗瞸鍱擪爗礏鎑饁鵺&amp;#34; , 
 &amp;#34;Y靨驜鸈膶岃一弌辷衤伊衣医吚壱依祎咿洢猗畩郼铱壹揖欹蛜禕嫛漪稦銥嬄噫夁瑿鹥繄檹毉醫黟譩鷖黳乁仪匜圯夷冝宐沂诒侇宜怡沶狋衪迤饴咦姨峓弬恞柂瓵荑贻迻宧巸扅栘桋眙胰袘酏痍&amp;#34; , 
 &amp;#34;Y移萓媐椬羠蛦詒貽遗暆椸誃跠頉颐飴疑儀熪遺嶬彛彜螔頤頥寲嶷簃顊鮧彝彞謻鏔籎觺讉鸃乙已以迆钇佁攺矣苡苢庡舣蚁釔倚扆笖逘偯崺旑椅鈘鉯鳦旖輢敼螘檥礒艤蟻顗轙齮乂义亿弋刈忆&amp;#34; , 
 &amp;#34;Y艺仡匇肊议阣亦伇屹异忔芅伿佚劮呓坄役抑曵杙耴苅译邑佾呭呹峄怈怿易枍泆炈绎诣驿俋奕帟帠弈枻浂玴疫羿衵轶唈垼悒挹栧欭浥浳益袣谊貤陭勚埶埸悘悥殹異羛翊翌萟訲訳豙豛逸釴隿&amp;#34; , 
 &amp;#34;Y幆敡晹棭殔湙焲蛡詍跇鈠骮亄兿意溢獈痬竩缢義肄裔裛詣勩嫕廙榏潩瘗膉蓺蜴靾駅億撎槸毅熠熤熼瘞誼镒鹝鹢黓劓圛墿嬑嬟嶧憶懌曀殪澺燚瘱瞖穓縊艗薏螠褹寱斁曎檍歝燡燱翳翼臆貖鮨&amp;#34; , 
 &amp;#34;Y癔藙藝贀鎰镱繶繹豷霬鯣鶂鶃鶍瀷蘙譯議醳醷饐囈鐿鷁鷊懿襼驛鷧虉鷾讛齸乚囙因阥阴侌垔姻洇茵荫音骃栶殷氤陰凐秵裀铟陻隂喑堙婣愔筃絪歅溵禋蒑蔭慇瘖銦磤緸鞇諲霒駰噾濦闉霠韾&amp;#34; , 
 &amp;#34;Y冘吟犾苂垠泿圁峾烎狺珢粌荶訔唫婬寅崟崯淫訡银鈝龂滛碒鄞夤蔩訚誾銀龈噖殥璌嚚檭蟫霪齗齦鷣尹引吲饮蚓隐淾釿鈏飲隠靷飮朄趛檃瘾隱嶾濥螾蘟櫽癮讔印茚洕胤垽湚猌廕酳慭癊憖憗&amp;#34; , 
 &amp;#34;Y鮣懚檼应応英偀桜珱莺啨婴媖愥渶绬朠煐瑛嫈碤锳嘤撄滎甇緓缨罂蝧賏樱璎噟罃褮霙鴬鹦嬰應膺韺甖鎣鹰鶧嚶孆孾攖瀴罌蘡櫻瓔礯譻鶯鑍纓蠳鷪軈鷹鸎鸚盁迎茔盈荥荧莹萤营萦蛍営溁溋&amp;#34; , 
 &amp;#34;Y萾僌塋楹滢蓥潆熒蝇瑩蝿嬴營縈螢濙濚濴藀覮謍赢巆攍攚瀛瀠瀯蠅櫿灐籝灜贏籯矨郢梬颍颕颖摬影潁瘿穎頴巊廮鐛癭映暎硬媵膡鞕瀅譍哟唷喲佣拥痈邕庸傭嗈鄘雍墉嫞慵滽槦牅噰壅擁澭&amp;#34; , 
 &amp;#34;Y郺镛臃癕雝鏞鳙廱灉饔鱅鷛癰喁颙顒鰫永甬咏怺泳俑勇勈栐埇悀柡涌恿傛惥愑湧硧詠塎嵱彮愹蛹慂踊禜鲬踴鯒用苚砽醟优忧攸呦怮泑幽悠麀滺憂優鄾嚘懮瀀櫌纋耰尢尤由沋犹邮怞油肬怣&amp;#34; , 
 &amp;#34;Y斿柚疣峳浟秞莜莤莸逌郵铀偤蚰訧逰游猶遊鱿楢猷鲉輏駀蕕蝣魷輶鮋櫾邎友有丣卣苃酉羑庮羐莠梄聈脜铕湵蒏禉蜏銪槱牖牗黝又右幼佑侑孧狖糿哊囿姷宥峟牰祐诱迶唀梎蚴亴貁釉酭誘鼬&amp;#34; , 
 &amp;#34;Y扜纡迂迃穻陓紆虶唹淤盓渝瘀箊于亐予邘伃余妤扵杅欤玗玙於盂臾衧鱼俞兪禺竽舁茰荢娛娯娱狳谀酑馀渔萸釪隃隅雩魚堣堬崳嵎嵛愉揄楰湡畬畭硢腴逾骬愚楡榆歈牏瑜艅虞觎漁睮窬舆褕&amp;#34; , 
 &amp;#34;Y歶羭蕍蝓諛雓餘魣嬩懙澞覦踰歟璵螸輿鍝礖謣髃鮽旟籅騟鯲鰅鷠鸆与伛宇屿羽雨俁俣挧禹语圄峿祤偊匬圉庾敔鄅萭萮铻傴寙斞楀瑀瘐與語窳鋙龉噳嶼貐斔麌蘌齬玉驭聿芋芌妪忬饫育郁彧&amp;#34; , 
 &amp;#34;Y昱狱秗茟俼峪栯浴砡钰预喐域堉悆惐欲淢淯袬谕逳阈喅喩喻媀寓庽御棛棜棫焴琙矞裕遇飫馭鹆愈滪煜稢罭蒮蓣誉鈺預嫗嶎戫毓獄瘉緎蜟蜮輍銉隩噊慾稶蓹薁豫遹鋊鳿澦燏燠蕷諭錥閾鴥鴧&amp;#34; , 
 &amp;#34;Y鴪儥礇禦魊鹬癒礜穥篽繘醧鵒櫲饇蘛譽轝鐭霱欎驈鬻籞鱊鷸鸒欝軉鬰鬱灪籲爩囦鸢剈冤弲悁眢鸳寃渁渆渊渕惌淵葾棩蒬蜎鹓箢鳶蜵駌鋺鴛嬽鵷灁鼘鼝元贠邧员园沅杬垣爰貟原員圆笎蚖袁&amp;#34; , 
 &amp;#34;Y厡酛圎援湲猨缘鈨鼋園圓塬媴嫄源溒猿獂蒝榞榬辕緣縁蝝蝯魭橼羱薗螈謜轅黿鎱櫞邍騵鶢鶰厵远盶逺遠夗肙妴苑怨院垸衏傆媛掾瑗禐愿裫褑褤噮願曰曱约約箹矱彟彠月戉刖岄抈礿岳枂玥&amp;#34; , 
 &amp;#34;Y恱钥悅悦蚎蚏軏钺阅捳跀跃粤越鈅粵鉞閱閲嬳樾篗嶽龠籆瀹蘥黦爚禴躍籥鸑籰龥鸙蒀煴蒕熅奫蝹赟頵馧贇云勻匀伝呍囩妘抣沄纭芸昀畇眃秐郧涢紜耘耺鄖雲愪氲溳筼蒷氳熉澐蕓鋆橒篔縜&amp;#34; , 
 &amp;#34;Y繧允阭夽抎狁玧陨荺殒喗鈗隕殞褞馻磒霣齫齳孕运枟郓恽晕鄆酝傊惲愠缊運慍暈腪韫韵熨緼蕰蕴縕薀賱醖醞餫藴韗韞蘊韻這&amp;#34; , 
 &amp;#34;Z敱捗囃謲匨蔵冊側厠廁嶒扠挿揷蹅茝僝欃倀长仧長镸鼌鼂謿謓迧陳鈂趂朾脀憕徎胵絺泜歭遟遲迣徸漴褈緟蝩蟲紬搊椆詶薵偢芻鉏蕏傳鶨倕埀箠鎚純湻辶腏趠齱骴薋泚跐從蓯樅熜緫潀潈潨&amp;#34; , 
 &amp;#34;Z酢噈欑穳篹嶉槯伜倅紣綷顇墫拵踆睉蔖剳蹛黱酖亶翢篴拞牴觝啇摕蝃踶點鳭調藋喋臷鰈眰鼑枓剢耑磓隊腞夛仛喥柮樲胕阝贛戇滜睪牫贑嫢啈楖嚌璾鯽穧椾碊鳽餰栫袸濺瀳鏩繳擳竧鳩砠蓻&amp;#34; , 
 &amp;#34;Z齟怚跙脧雋捔逫嵁沴酈譧驡狵沵摨聶囁釽亝祇蚔齊磩鈆謙綪繰菬埥軽鯖伹岨恮跧甽繅洓篸箑摂攝鉐實識亊鉃適銴檡薥藷鸀尌虒睟簨駘菭襢犆媞薙嚔鐟塡怗聑跕鉄鉵獞穜潳剬剸塼摶漙篿尵&amp;#34; , 
 &amp;#34;Z旽啍忳飩杔馲驝陁萚蘀聉顡醀錗撾扸杫咥枮鮝鞢鋅鮏鯹鎐蓔捙偞擖杝妷秇栺軼乑斦浧銿鈾圫汋帀匝沞咂拶沯桚紥紮鉔魳臜臢杂砸韴雑磼襍雜囐雥災灾甾哉栽烖菑渽溨睵賳宰载崽載再在扗&amp;#34; , 
 &amp;#34;Z洅傤酨儎縡兂糌簪簮鐕咱偺喒昝寁撍儧攒儹攢趱趲暂暫賛赞錾鄼濽蹔酂瓉贊鏨瓒酇囋灒讃瓚禶襸讚饡牂羘赃賍臧賘贓髒贜驵駔奘弉脏塟葬銺臓臟傮遭糟蹧醩凿鑿早枣栆蚤棗璅澡璪薻藻灶&amp;#34; , 
 &amp;#34;Z皁皂唕唣造梍喿慥煰艁噪簉燥竃譟趮躁竈啫伬则択沢择泎泽责迮則唶啧帻笮舴責溭矠嘖嫧幘箦蔶樍歵諎赜擇澤皟瞔簀耫礋襗謮賾蠌齚齰鸅仄夨庂汄昃昗捑崱稄贼賊鲗蠈鰂鱡怎谮譖譛囎曽&amp;#34; , 
 &amp;#34;Z増鄫增憎缯橧熷璔矰磳罾繒譄鱛锃鋥甑赠贈吒迊咋抯挓柤哳偧喳揸渣溠楂劄皶箚樝觰皻譇齄齇扎札甴轧軋闸蚻铡煠牐閘霅鍘譗厏苲眨砟搩鲊鲝踷鮓鮺乍灹诈咤奓柵炸宱痄蚱詐搾摣榨醡夈&amp;#34; , 
 &amp;#34;Z粂捚斋斎摘榸齋宅翟窄鉙债砦債寨瘵沾毡旃栴粘蛅飦惉詀趈詹閚谵噡嶦薝邅霑氈氊瞻鹯旜譫饘鳣驙魙鱣鸇讝拃斩飐展盏崭斬琖搌盞嶃嶄榐辗颭嫸醆橏蹍輾皽黵占佔战栈桟站偡绽菚棧湛戦&amp;#34; , 
 &amp;#34;Z綻嶘輚戰虥虦覱轏蘸驏张弡張章傽鄣嫜彰慞漳獐粻蔁遧暲樟璋餦蟑鏱騿鱆麞仉涨涱掌漲幥礃鞝鐣丈仗扙帐杖胀账粀帳脹痮障墇嶂幛賬瘬瘴瞕佋钊妱巶招昭炤盄釗啁鉊駋窼鍣爫找沼瑵召兆&amp;#34; , 
 &amp;#34;Z诏枛垗狣赵笊肁旐棹罀詔照罩箌肇肈趙曌燳鮡櫂瞾羄蜇嫬遮厇折歽矺砓籷虴哲埑粍袩啠悊晢晣辄喆棏蛰詟谪摺輒樀磔輙銸辙蟄嚞謫謺鮿轍讁襵讋者锗赭褶鍺这柘浙淛嗻蔗樜鹧蟅鷓贞针侦&amp;#34; , 
 &amp;#34;Z浈珍珎貞帪栕桢眞真砧祯針偵敒桭酙寊湞葴遉搸斟楨獉甄禎蒖蓁鉁靕榛槇殝瑧碪禛潧箴樼澵臻薽錱轃鍖鍼籈鱵屒诊抮枕姫弫昣胗轸畛疹眕袗紾聄萙裖覙診軫嫃缜稹駗縝縥辴鬒黰圳阵纼侲&amp;#34; , 
 &amp;#34;Z挋陣鸩振朕栚紖眹赈塦揕絼蜄敶誫賑鋴镇震鴆鎭鎮黮凧争佂姃征怔爭峥挣炡狰烝眐钲埩崝崢掙猙睁聇铮媜揁筝徰睜蒸鉦徴箏徵踭篜錚鬇癥氶抍糽拯掟塣晸愸撜整正证诤郑帧政症幀証鄭諍&amp;#34; , 
 &amp;#34;Z鴊證之支卮汁芝吱巵汥枝知织肢徔栀祗秓秖胑胝衹衼倁疷祬秪脂隻梔戠椥臸搘禔綕榰蜘馶鳷謢鴲織蘵鼅禵执侄坧直姪値值聀釞埴執职植殖禃絷跖瓡墌摭馽嬂慹漐踯樴膱縶職蟙蹠蹢軄躑止&amp;#34; , 
 &amp;#34;Z只凪劧旨阯址坁帋扺汦沚纸芷抧祉茋咫恉指枳洔砋轵淽疻紙訨趾軹黹酯藢襧阤至芖志忮扻豸制厔垁帙帜治炙质郅俧峙庢庤挃柣栉洷祑陟娡徏挚晊桎狾秩致袟贽轾乿偫徝掷梽猘畤痔秲秷窒&amp;#34; , 
 &amp;#34;Z紩翐袠觗貭铚鸷傂崻彘智滞痣蛭骘寘廌搱滍稙稚筫置跱輊锧雉墆槜滯潌疐瘈製覟誌銍幟憄摯潪熫稺膣觯質踬鋕旘瀄緻隲駤鴙儨劕懥擲擿櫛穉螲懫贄櫍瓆觶騭鯯礩豑騺驇躓鷙鑕豒中伀汷刣&amp;#34; , 
 &amp;#34;Z妐彸迚忠泈炂终柊盅衳钟舯衷終鈡幒蔠锺螤鴤螽鍾鼨蹱鐘籦肿种冢喠尰塚歱煄腫瘇種踵仲众妕狆祌茽衶重蚛偅眾堹媑筗衆諥州舟诌侜周洀洲炿诪烐珘辀郮婤徟淍矪週鸼喌粥赒輈銂賙輖霌&amp;#34; , 
 &amp;#34;Z駲嚋盩謅鵃騆譸妯轴軸碡肘帚疛菷晭睭箒鯞纣伷呪咒宙绉冑咮昼紂胄荮晝皱酎粙葤詋甃僽皺駎噣縐骤籀籕籒驟朱劯侏诛邾洙茱株珠诸猪硃袾铢絑蛛誅跦槠潴蝫銖橥諸豬駯鮢鴸瀦藸櫧櫫鼄&amp;#34; , 
 &amp;#34;Z鯺蠩竹泏竺炢笁茿烛窋逐笜舳瘃蓫燭蠋躅鱁劚孎灟斸曯欘爥蠾钃主宔拄砫罜陼渚煑煮詝嘱濐麈瞩屬囑矚伫佇住助纻芧苎坾杼注苧贮迬驻壴柱柷殶炷祝疰眝祩竚莇秼紵紸羜著蛀嵀筑註貯跓&amp;#34; , 
 &amp;#34;Z軴铸筯鉒飳馵墸箸翥樦鋳駐築篫霔麆鑄抓檛膼簻髽爪拽跩专叀専砖專鄟嫥瑼甎膞颛磚諯蟤顓鱄转孨転竱轉灷啭堟蒃瑑僎赚撰篆馔縳襈賺譔饌囀籑妆庄妝庒荘娤桩莊湷粧装裝樁糚丬壮壯状&amp;#34; , 
 &amp;#34;Z狀壵梉焋幢撞戅隹追骓椎锥錐騅鵻沝坠笍娷缀惴甀缒畷硾膇墜綴赘縋諈醊錣餟礈贅轛鑆宒迍肫窀谆諄衠准埻凖準綧訰稕卓拙炪倬捉桌棁涿棳琸窧槕穛穱蠿圴彴犳灼叕妰茁斫浊丵浞烵诼酌&amp;#34; , 
 &amp;#34;Z啄啅娺梲着斮晫椓琢斱硺窡罬撯擆斲禚劅諁諑鋜濁篧擢斀斵濯櫡謶镯鐯鵫灂蠗鐲籗鷟籱仔孖孜茊兹咨姕姿茲栥玆紎赀资崰淄秶缁谘赼嗞孳嵫椔湽滋葘辎鄑孶禌觜貲資趑锱稵緇鈭镃龇輜鼒&amp;#34; , 
 &amp;#34;Z澬諮趦輺錙髭鲻鍿鎡頾頿鯔鶅齍鰦齜籽子吇姉姊杍矷秄胏呰秭耔虸笫梓釨啙紫滓訾訿榟橴字自芓茡倳剚恣牸渍眥眦胔胾漬唨宗倧综骔堫嵏嵕惾棕猣腙葼朡椶嵸稯綜緃熧緵翪艐蝬踨踪磫豵&amp;#34; , 
 &amp;#34;Z蹤騌鬃騣鬉鬷鯮鯼鑁总偬捴惣愡揔搃傯蓗摠総縂燪總鍯鏓纵昮疭倊猔碂粽糉瘲縦錝縱邹驺诹郰陬掫菆棷棸鄒箃緅諏鄹鲰鯫黀騶齺赱走鯐奏揍媰租菹葅蒩卆足卒哫崒崪族傶稡箤踤踿镞鏃诅&amp;#34; , 
 &amp;#34;Z阻组俎爼珇祖組詛靻鎺謯劗躜鑚躦鑽繤缵纂纉籫纘钻揝攥厜朘嗺樶蟕纗嶊嘴噿濢璻枠栬絊酔晬最祽罪辠酻蕞醉嶵檇鋷錊檌穝欈尊嶟遵樽繜罇鶎鐏鳟鱒鷷僔噂撙譐捘銌昨秨莋捽椊葃稓筰鈼&amp;#34; , 
 &amp;#34;Z左佐繓作坐阼岝岞怍侳柞祚胙唑座袏做葄蓙飵糳咗&amp;#34; 
 };
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="vbnet代码"&gt;VB.Net代码&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; &amp;#39;/ &amp;lt;summary&amp;gt; 
 &amp;#39;/ 获得一个字符串的汉语拼音码 
 &amp;#39;/ &amp;lt;/summary&amp;gt; 
 &amp;#39;/ &amp;lt;param name=&amp;#34;strText&amp;#34;&amp;gt;字符串&amp;lt;/param&amp;gt; 
 &amp;#39;/ &amp;lt;returns&amp;gt;汉语拼音码,该字符串只包含大写的英文字母&amp;lt;/returns&amp;gt; 
 Public Shared Function GetChineseSpell(ByVal strText As String) As String
 If strText = Nothing Or strText.Length = 0 Then
 Return strText
 End If
 Dim myStr As System.Text.StringBuilder = New System.Text.StringBuilder()
 Dim vChar As Char
 For Each vChar In strText
 &amp;#39; 若是字母则直接输出 
 If (vChar &amp;gt;= &amp;#34;a&amp;#34;c And vChar &amp;lt;= &amp;#34;z&amp;#34;c) Or (vChar &amp;gt;= &amp;#34;A&amp;#34;c And vChar &amp;lt;= &amp;#34;Z&amp;#34;c) Then
 myStr.Append(vChar)
 ElseIf Microsoft.VisualBasic.AscW(vChar) &amp;gt;= 19968 And Microsoft.VisualBasic.AscW(vChar) &amp;lt;= 40869 Then
 &amp;#39; 若字符Unicode编码在编码范围则 查汉字列表进行转换输出 
 Dim strList As String
 For Each strList In strChineseCharList
 If strList.IndexOf(vChar) &amp;gt; 0 Then
 myStr.Append(strList(0))
 Exit For
 End If
 Next
 End If
 Next
 Return myStr.ToString()
 End Function
 &amp;#39; GetChineseSpell 

 Private Shared strChineseCharList() As String = {&amp;#34;A阿啊锕嗄厑哎哀唉埃挨溾锿鎄啀捱皑凒溰嘊敳皚癌毐昹嗳矮蔼躷噯藹譪霭靄艾伌爱砹硋隘嗌塧嫒愛碍暧瑷僾壒嬡懓薆曖璦鴱皧瞹馤鑀鱫安侒峖桉氨庵谙萻腤鹌蓭誝鞌鞍盦馣鮟盫韽啽雸垵&amp;#34;, &amp;#34;A俺唵埯铵隌揞罯銨犴岸按荌案胺豻堓婩暗貋儑錌黯肮岇昂昻枊盎醠凹坳垇柪軪爊敖厫隞嗷嗸嶅廒滶獒獓遨熬璈蔜翱聱螯翶謷翺鳌鏖鰲鷔鼇芺袄媪镺襖岙扷岰傲奡奥嫯慠骜奧嶴澳懊擙謸鏊&amp;#34;, &amp;#34;B八仈巴叭扒朳玐吧夿岜芭疤哵捌笆粑紦羓蚆釟豝鲃魞叐犮抜坺妭拔茇炦癹胈釛菝詙跋軷魃把靶坝弝爸垻罢鲅鮁覇矲霸壩灞欛挀掰白百佰柏栢捭竡粨摆擺襬呗拝败拜唄敗稗粺鞁薭贁兡瓸扳&amp;#34;, &amp;#34;B攽班般颁斑搬斒瘢螁癍辬阪坂岅昄板版瓪钣粄舨鈑蝂魬办半伴扮姅怑拌绊秚絆鉡靽辦瓣邦峀垹帮捠梆浜邫幇幚縍幫鞤绑綁榜膀玤蚌傍棒谤塝稖蒡蜯磅镑艕謗勹包佨孢苞胞笣煲龅蕔褒闁齙&amp;#34;, &amp;#34;B窇嫑雹宝怉饱保鸨珤堡堢媬葆寚飹飽褓駂鳵緥鴇賲藵寳寶靌勽报抱豹趵菢鲍靤骲暴髱虣儤曓爆忁鑤萡陂卑杯盃桮悲揹碑鹎藣鵯喺北鉳贝狈貝邶备昁牬苝背钡俻倍悖狽被偝偹梖珼鄁備僃惫&amp;#34;, &amp;#34;B焙軰辈愂碚禙蓓蛽犕褙誖骳輩鋇憊糒鞴鐾奔泍贲倴渀逩犇锛錛本苯奙畚楍坌捹桳笨撪輽伻崩绷閍嵭嘣綳繃甭埲菶琫鞛泵迸塴甏镚蹦鏰屄毴逼豍鲾鵖鰏柲荸鼻嬶匕比夶朼佊吡妣沘疕彼柀秕&amp;#34;, &amp;#34;B俾笔粊舭筆鄙聛貏匂币必毕闭佖坒庇诐邲妼怭畀畁哔毖珌疪荜陛毙狴畢袐铋婢庳敝梐萆萞閇閉堛弻弼愊愎湢皕禆筚詖貱赑嗶彃楅滗滭煏痹腷蓖蓽蜌裨跸閟飶幣弊熚獙碧箅綼蔽鄪馝幤潷獘&amp;#34;, &amp;#34;B罼襅駜髲壁嬖廦篦篳縪薜觱避鮅斃濞臂蹕髀奰璧鄨饆繴襞襣鏎鞸韠躃躄魓贔鐴驆鷝鷩鼊边砭笾编煸甂箯編蝙獱邉鍽鳊邊鞭鯾鯿籩炞贬扁窆匾惼碥稨褊糄鴘藊卞弁忭抃汳汴苄釆峅便变変昪&amp;#34;, &amp;#34;B覍揙缏遍辡艑辧辨辩辫辮變彪标飑髟猋脿墂幖滮骠標熛膘瘭镖飙飚儦颷瀌爂臕贆鏢镳飆飇飈飊鑣表婊裱諘褾錶檦俵鳔鰾憋鳖鱉鼈虌龞別别咇莂蛂徶襒蟞蹩瘪癟彆邠宾彬傧斌椕滨缤槟瑸賓&amp;#34;, &amp;#34;B賔镔儐濒濱濵虨豳瀕霦繽蠙鑌顮氞摈殡膑髩擯鬂殯臏髌鬓髕鬢仌氷冰兵栟掤梹鋲檳丙邴陃怲抦秉苪昺柄炳饼窉蛃棅禀鈵鞆餅餠燷并並併幷垪庰倂栤病竝偋傡寎摒誁鮩靐癶拨波玻剥盋袯钵&amp;#34;, &amp;#34;B饽啵紴缽脖菠鉢僠嶓播餑蹳驋鱍仢伯孛驳帛泊狛瓝侼勃胉郣亳挬浡秡钹铂舶博渤葧鹁愽搏鈸鉑馎鲌僰煿牔箔膊艊馛駁踣鋍镈薄駮鮊懪礡簙鎛餺鵓犦欂襮礴鑮跛箥簸孹擘檗糪譒蘗蔔峬庯逋&amp;#34;, &amp;#34;B钸晡鈽誧餔轐醭卜卟补哺捕補鳪鸔不布佈步咘怖歨歩钚勏埗悑部埠瓿廍蔀踄篰餢簿玢佛夯宀疒瀑&amp;#34;, &amp;#34;C嚓擦礤礸遪猜才材财財戝裁采倸埰婇寀彩採睬跴綵踩菜棌蔡縩乲参飡骖湌嬠餐驂残蚕惭殘慚蝅慙蠶蠺惨慘噆憯黪黲灿粲儏澯薒燦璨爘仓仺伧沧苍倉舱傖凔嵢滄獊蒼濸艙螥罉藏欌鑶賶撡操&amp;#34;, &amp;#34;C糙曺曹嘈嶆漕蓸槽褿艚螬鏪艹艸草愺騲肏襙册侧厕恻测荝敇萗惻測策萴筞蓛墄箣憡嵾膥岑梣涔噌层層竲驓蹭硛硳岾猠乽叉芆杈肞臿訍偛嗏插馇銟锸艖疀鍤餷垞查査茬茶嵖搽猹靫槎察碴檫&amp;#34;, &amp;#34;C衩镲鑔奼汊岔侘诧姹差紁拆钗釵犲侪柴祡豺喍儕虿袃瘥蠆囆辿觇梴掺搀鋓幨婵谗孱棎湹禅馋嬋煘缠獑蝉誗鋋廛潹潺緾磛毚鄽镡瀍儳劖蟾酁嚵壥巉瀺纏纒躔镵艬讒鑱饞产刬旵丳浐剗谄產産&amp;#34;, &amp;#34;C铲阐蒇剷嵼滻幝蕆諂閳簅冁繟醦鏟闡囅灛讇忏硟摲懴颤懺羼韂伥昌娼淐猖菖阊晿椙琩裮锠錩鲳鯧鼚兏肠苌尝偿常徜瓺萇甞腸嘗嫦瑺膓鋿償嚐蟐鲿鏛鱨厂场昶惝敞僘厰廠氅鋹怅玚畅倡鬯唱&amp;#34;, &amp;#34;C悵暢畼誯韔抄弨怊欩钞焯超鈔繛牊晁巢巣朝鄛漅嘲潮窲罺轈吵炒眧煼麨巐仦耖觘车車砗唓莗硨蛼扯偖撦屮彻坼迠烢聅掣硩頙徹撤澈勶瞮爡抻郴棽琛嗔諃賝尘臣忱沉辰陈茞宸烥莐敐晨訦谌&amp;#34;, &amp;#34;C揨煁蔯塵樄瘎霃螴諶薼麎曟鷐趻硶碜墋夦磣踸贂闯衬疢称龀趁榇稱齓齔嚫谶襯讖阷泟柽爯棦浾偁蛏铛牚琤赪憆摚靗撐撑緽橕瞠赬頳檉竀穪蟶鏳鏿饓丞成呈承枨诚郕城宬峸洆荿乘埕挰珹掁&amp;#34;, &amp;#34;C窚脭铖堘惩棖椉程筬絾裎塍塖溗碀誠畻酲鋮澂澄橙檙鯎瀓懲騬悜逞骋庱睈騁秤吃妛杘侙哧彨蚩鸱瓻眵笞訵嗤媸摛痴瞝螭鴟鵄癡魑齝攡麶彲黐弛池驰迟岻茌持竾荎淔筂貾遅馳墀踟篪謘尺叺&amp;#34;, &amp;#34;C呎肔侈卶齿垑胣恥耻蚇豉欼歯裭鉹褫齒彳叱斥灻赤饬抶勅恜炽翄翅敕烾痓啻湁傺痸腟鉓雴憏翤遫慗瘛翨熾懘趩饎鶒鷘充冲忡沖茺浺珫翀舂嘃摏憃憧衝罿艟蹖虫崇崈隀宠铳銃抽瘳篘犨犫仇&amp;#34;, &amp;#34;C俦帱栦惆绸菗畴絒愁皗稠筹酧酬踌雔嬦懤燽雠疇躊讎讐丑丒吜杽侴瞅醜矁魗臭遚殠出岀初摴樗貙齣刍除厨滁蒢豠锄榋耡蒭蜍趎雏犓廚篨橱懨幮櫉蟵躇櫥蹰鶵躕杵础椘储楮禇楚褚濋儲檚璴&amp;#34;, &amp;#34;C礎齭齼亍処处竌怵拀绌豖竐珿絀傗琡鄐搐触踀閦儊憷橻斶歜臅黜觸矗搋膗揣啜嘬踹巛川氚穿剶瑏传舡船圌遄椽歂暷輲舛荈喘僢汌串玔钏釧賗刅囱疮窓窗牎摐牕瘡窻床牀噇傸磢闖创怆刱剏&amp;#34;, &amp;#34;C剙愴吹炊龡垂桘陲捶菙棰槌锤錘顀旾杶春萅堾媋暙椿槆瑃箺蝽橁櫄鰆鶞纯陙唇浱莼淳脣犉滣蒓鹑漘醇醕鯙偆萶惷睶賰踳蠢踔戳辵娖惙涰绰逴辍酫綽輟龊擉磭歠嚽齪鑡呲玼疵趀偨词珁垐柌&amp;#34;, &amp;#34;C祠茈茨瓷詞辝慈甆辞磁雌鹚糍辤飺餈嬨濨鴜礠辭鶿鷀此佌皉朿次佽刺刾庛茦栨莿絘蛓赐螆賜嗭从匆囪苁忩枞茐怱悤焧葱漗聡蔥骢暰樬瑽璁聦聪瞛篵聰蟌繱鏦騘驄丛従婃孮徖悰淙琮慒誴賨&amp;#34;, &amp;#34;C賩樷藂叢灇欉爜謥凑湊楱腠辏輳粗觕麁麄麤徂殂促猝媨瘄蔟誎趗憱醋瘯簇縬蹙鼀蹴蹵顣汆撺镩蹿攛躥鑹攅櫕巑窜熶篡殩簒竄爨崔催凗墔慛摧榱獕磪鏙乼漼璀皠忰疩翆脃脆啐啛悴淬萃毳焠&amp;#34;, &amp;#34;C瘁粹翠膵膬竁襊臎邨村皴澊竴存刌忖寸籿搓瑳遳磋撮蹉醝髊虘嵯嵳痤矬蒫鹾鹺齹脞剉剒厝夎挫莝莡措逪棤锉蓌错銼刂刹畜曾膪澶骣粢&amp;#34;, &amp;#34;D詫襜燀譂奲虰坘蚳赿跮揰裯儔幬篅搥錞踧吋咑哒耷畣搭嗒褡噠墶达妲怛垯炟羍荙匒笪答詚跶瘩靼薘鞑燵繨蟽躂鐽龖龘打大亣眔橽呆獃懛歹傣代汏轪侢垈岱帒甙绐迨带待怠柋殆玳贷帯軑埭&amp;#34;, &amp;#34;D帶紿袋逮軩瑇叇曃緿鮘鴏戴艜黛簤瀻霴襶靆丹妉单担眈砃耼耽郸聃躭媅殚瘅匰箪褝鄲頕儋勯殫襌簞聸刐狚玬瓭胆衴疸紞掸馾澸黕膽旦但帎沊泹诞柦疍啖啗弹惮淡萏蛋啿氮腅蜑觛窞誕噉髧&amp;#34;, &amp;#34;D憚憺澹禫駳鴠甔癚嚪贉霮饏当珰裆筜當儅噹澢璫襠簹艡蟷挡党谠擋譡灙讜氹凼圵宕砀垱荡档菪瓽雼碭瞊趤壋檔璗盪礑刀叨屶忉氘舠釖鱽魛捯导岛陦倒島捣祷禂搗隝嶋嶌槝導隯壔嶹擣蹈禱&amp;#34;, &amp;#34;D到悼盗菿椡盜道稲噵稻衜檤衟翿軇瓙纛恴得淂悳惪锝嘚徳德鍀的揼扥扽灯登豋噔嬁燈璒竳簦艠覴蹬等戥邓凳鄧隥墱嶝瞪磴镫櫈鐙仾低彽袛啲埞羝隄堤趆嘀滴镝磾鞮鏑廸狄肑籴苖迪唙敌涤&amp;#34;, &amp;#34;D荻梑笛觌靮滌嫡蔋蔐頔魡敵嚁藡豴糴鸐氐厎诋邸阺呧坻底弤抵柢砥掋菧軧聜骶鯳地弟旳杕玓怟枤俤帝埊娣递逓偙梊焍眱祶第菂谛釱棣睇缔蒂僀禘腣鉪馰墑墬碲蔕慸甋締嶳螮嗲敁掂傎厧嵮&amp;#34;, &amp;#34;D滇槙瘨颠蹎巅癫巓巔攧癲齻典奌点婰敟椣碘蒧蕇踮电佃甸阽坫店垫扂玷钿婝惦淀奠琔殿蜔電墊壂橂澱靛磹癜簟驔刁叼汈刟虭凋奝弴彫蛁琱貂碉殦瞗雕鮉鲷簓鼦鯛鵰屌弔伄吊钓窎訋掉釣铞&amp;#34;, &amp;#34;D鈟竨銱雿瘹窵鋽鑃爹跌褺苵迭垤峌恎绖胅瓞眣耊戜谍堞幉揲畳絰耋詄叠殜牃牒镻嵽碟蜨褋艓蝶疂蹀鲽曡疉疊氎嚸丁仃叮帄玎甼疔盯钉耵酊靪顶頂鼎嵿薡鐤订饤矴定訂飣啶萣椗腚碇锭碠聢&amp;#34;, &amp;#34;D錠磸顁丟丢铥颩銩东冬咚岽東苳昸氡倲鸫埬娻崬涷笗菄氭蝀鮗鼕鯟鶇鶫董嬞懂箽蕫諌动冻侗垌姛峒恫挏栋洞胨迵凍戙胴動崠硐棟腖働駧霘剅唗都兜兠蔸橷篼艔斗乧阧抖陡蚪鈄豆郖浢荳逗&amp;#34;, &amp;#34;D饾鬥梪脰酘痘閗窦鬦餖斣闘竇鬪鬬鬭嘟督醏毒涜读渎椟牍犊裻読蝳獨錖凟匵嬻瀆櫝殰牘犢瓄皾騳黩讀豄贕韣髑鑟韇韥黷讟厾独笃堵帾琽赌睹覩賭篤芏妒杜肚妬度荰秺渡靯镀螙殬鍍蠧蠹偳&amp;#34;, &amp;#34;D媏端鍴短段断塅缎葮椴煅瑖腶碫锻緞毈簖鍛斷躖籪叾垖堆塠嵟痽頧鴭鐜队对兑対祋怼陮碓綐對憝濧薱镦懟瀩譈鐓譵吨惇敦墩墪壿撴獤噸撉犜礅蹲蹾驐盹趸躉伅沌炖盾砘逇钝顿遁鈍頓碷遯&amp;#34;, &amp;#34;D潡踲多咄哆剟崜毲裰嚉夺铎剫掇敓敚敪痥鈬奪凙踱鮵鐸朵朶哚垛挅挆埵缍椯趓躱躲綞亸鬌嚲刴剁沲陊饳垜尮桗堕舵惰跢跥跺飿嶞憜墯鵽卩亻赕铫町铤夂丶&amp;#34;, &amp;#34;E娾砵妸妿娿屙讹囮迗俄娥峨峩涐莪珴訛皒睋鈋锇鹅蛾磀誐頟额額鵝鵞譌枙砈婀騀鵈厄歺戹阨呃扼苊阸呝砐轭咢垩峉匎恶砨蚅饿偔卾悪硆谔軛鄂阏堮崿愕湂萼豟軶遌遏廅搹琧腭僫蝁锷鹗蕚&amp;#34;, &amp;#34;E遻頞颚餓噩擜覨諤餩鍔鳄歞顎櫮鰐鶚讍鑩齶鱷奀恩蒽峎摁鞥仒乻旕儿而侕陑峏洏荋栭胹袻鸸粫輀鲕隭髵鮞鴯轜尔耳迩洱饵栮毦珥铒餌駬薾邇趰二弍弐佴刵咡贰貮衈貳誀嗯唔诶&amp;#34;, &amp;#34;F颰墢鼥韛朌頒報賁獖祊埄偪胇貶昞眪袚撥柭襏舩发沷発發彂髪橃醗乏伐姂垡疺罚阀栰傠筏瞂罰閥罸藅佱法砝鍅灋珐琺髮帆忛番勫噃墦嬏幡憣旙旛翻藩轓颿飜鱕凡凢凣匥杋柉矾籵钒舤烦舧&amp;#34;, &amp;#34;F笲釩棥煩緐樊蕃橎燔璠薠繁襎繙羳蹯瀿礬蘩鐇蠜鷭反仮払辺返氾犯奿汎泛饭范贩畈訉軓梵盕笵販軬飯飰滼嬎範嬔瀪方邡坊芳枋牥钫淓蚄堏鈁錺鴋防妨房肪埅鲂魴仿访纺昉昘瓬眆倣旊紡舫&amp;#34;, &amp;#34;F訪髣鶭放飞妃非飛啡婓婔渄绯菲扉猆靟裶緋蜚霏鲱餥馡騑騛鯡飝肥淝暃腓蜰蟦匪诽奜悱斐棐榧翡蕜誹篚吠废杮沸狒肺昲费俷剕厞疿屝萉廃費痱镄廢蕟曊癈鼣濷櫠鐨靅分吩帉纷芬昐氛竕紛&amp;#34;, &amp;#34;F翂棻訜躮酚鈖雰朆餴饙坟妢岎汾枌炃肦梤羒蚠蚡棼焚蒶馚隫墳幩蕡魵鳻橨燌燓豮鼢羵鼖豶轒鐼馩黂粉瞓黺份坋弅奋忿秎偾愤粪僨憤奮膹糞鲼瀵鱝丰风仹凨凬妦沣沨凮枫封疯盽砜風峯峰偑&amp;#34;, &amp;#34;F桻烽琒崶渢溄猦葑锋楓犎蜂瘋碸僼篈鄷鋒檒豐鎽鏠酆寷灃靊飌麷冯捀逢堸綘缝艂縫讽覂唪諷凤奉甮俸湗焨煈赗鳯鳳鴌賵蘕瓰覅仏坲梻紑缶否缹缻雬鴀夫伕邞呋姇枎玞肤怤柎砆荂衭娐荴旉&amp;#34;, &amp;#34;F紨趺酜麸稃跗鈇筟綒孵敷麩糐麬麱懯乀弗伏凫甶冹刜孚扶芙芣芾咈岪帗彿怫拂服泭绂绋苻茀俘垘枹柫氟洑炥玸畉畐祓罘茯郛韨鳬哹栿浮畗砩莩蚨匐桴涪烰琈符笰紱紼翇艴菔虙袱幅絥罦葍&amp;#34;, &amp;#34;F福粰綍艀蜉辐鉘鉜颫鳧榑稪箙複韍幞澓蝠髴鴔諨踾輻鮄癁鮲黻鵩鶝抚甫府弣拊斧俌郙俯釜釡捬辅椨焤盙腑滏腐輔簠黼父讣付妇负附咐坿竎阜驸复祔訃負赴蚥袝偩冨副婏婦蚹傅媍富復萯蛗&amp;#34;, &amp;#34;F覄詂赋椱缚腹鲋禣褔赙緮蕧蝜蝮賦駙縛輹鮒賻鍑鍢鳆覆馥鰒猤攵犭&amp;#34;, &amp;#34;G玵閞鳺旮伽嘠钆尜嘎噶錷尕玍尬魀该陔垓姟峐荄晐赅畡祴該豥賅賌忋改絠鎅丐乢匃匄杚钙盖溉葢鈣戤概蓋槩槪漑瓂干甘芉迀杆玕肝坩泔苷柑竿疳酐粓亁凲尲尴筸漧尶尷魐皯秆衦赶敢笴稈&amp;#34;, &amp;#34;G感澉趕橄擀簳鳡鱤旰盰矸绀倝凎淦紺詌骭幹檊赣灨冈罓冮刚岗纲肛岡牨疘缸钢剛罡堈掆釭棡犅堽綱罁鋼鎠崗港杠焵筻槓戆皋羔高皐髙槔睾膏槹橰篙糕餻櫜韟鷎鼛鷱夰杲菒稁搞缟槁獔稿镐&amp;#34;, &amp;#34;G縞藁檺吿告勂诰郜峼祮祰锆筶禞誥鋯戈圪纥戓疙牱哥胳袼鸽割搁彁歌滒戨閤鴐鴚擱謌鴿鎶呄佮匌阁革敋格鬲愅臵葛隔嗝塥滆觡搿槅膈閣镉韐骼諽鮯櫊韚轕鞷騔鰪哿舸个各虼個硌铬箇獦给&amp;#34;, &amp;#34;G根跟哏亘艮茛揯搄更刯庚畊浭耕掶菮椩焿絚赓鹒緪縆賡羹鶊郠哽埂峺挭绠耿莄梗綆鲠骾鯁亙堩啹喼嗰工弓公功攻杛供糼肱宫宮恭蚣躬龚匑塨幊觥躳匔碽髸觵龔巩汞拱拲栱珙輁鞏共贡貢慐&amp;#34;, &amp;#34;G熕兝兣勾佝沟钩袧缑鈎緱褠篝簼鞲韝岣狗苟枸玽耇耉笱耈豿坸构诟购垢姤茩冓够夠訽媾彀搆遘雊煹觏撀覯購估咕姑孤沽泒柧轱唂唃罛鸪笟菇菰蛄蓇觚軱軲辜酤毂箍箛嫴篐橭鮕鴣轂鹘古汩&amp;#34;, &amp;#34;G诂谷股峠牯骨罟羖逧钴傦啒脵蛊蛌尳愲硲詁馉榾鼓鼔嘏榖皷穀糓薣濲臌餶瀔盬瞽固故凅顾堌崓崮梏牿棝祻雇痼稒锢頋僱錮鲴鯝顧瓜刮苽胍鸹歄焻煱颪劀緺銽鴰騧冎叧呱剐剮啩寡卦坬诖挂&amp;#34;, &amp;#34;G掛罣罫褂詿乖拐枴柺箉怪恠关观官冠覌倌棺蒄窤瘝癏観鳏觀鱞馆痯筦管輨舘錧館躀鳤毌贯泴悺惯掼涫悹祼慣摜遦樌盥罆鏆灌爟瓘礶鹳罐鑵鱹光灮侊炗炚炛咣垙姯茪桄烡珖胱僙輄銧黆欟广&amp;#34;, &amp;#34;G広犷俇逛撗归圭妫龟规邽皈茥闺帰珪亀硅袿媯椝瑰郌摫閨鲑嬀槻槼璝瞡鬶瓌櫷宄轨庋佹匦诡陒垝癸軌鬼庪祪匭晷湀蛫觤詭厬簋蟡刽刿攰柜炅攱贵桂椢筀貴蓕跪瞆劊劌撌槶禬簂櫃鳜鱥衮惃&amp;#34;, &amp;#34;G绲袞辊滚蓘滾蔉磙輥鲧鮌鯀棍棞睴璭謴呙埚郭啯崞聒鈛锅墎瘑嘓彉蝈鍋彍囯囶囻国圀國帼掴幗慖摑漍聝蔮虢馘果惈淉猓菓馃椁褁槨綶蜾裹餜鐹过桧咯莞呷&amp;#34;, &amp;#34;H餲淲豩豰俿腄墮吪魤犿浲侅郂絯忓攼仠桿汵榦臯鎬暠犵挌蛤厷愩唝羾詬鶻淈鹄鈷縎鵠怘趏潅雚洸襘鞼緄腘膕粿輠過铪丷哈嗨孩骸海胲烸塰酼醢亥骇害氦嗐餀駭駴嚡饚乤兯佄顸哻蚶酣頇谽&amp;#34;, &amp;#34;H憨馠魽鼾邗含邯函凾虷唅圅娢浛崡晗梒涵焓寒嵅韩甝筨爳蜬澏鋡韓厈罕浫喊蔊豃鬫汉屽扞汗闬旱垾悍捍晘涆猂莟晥焊琀菡釬閈皔睅傼蛿颔撖蜭暵銲鋎憾撼翰螒頷顄駻雗瀚鶾魧苀斻杭垳绗&amp;#34;, &amp;#34;H笐航蚢颃貥筕絎頏沆蒿嚆薅竓蚝毫椃嗥獆噑豪嘷獋儫曍嚎壕濠籇蠔譹好郝号昊昦哠恏浩耗晧淏傐皓聕號暤暭澔皜皞皡薃皥颢灏顥鰝灝兞诃呵喝訶嗬蠚禾合何劾咊和姀河峆曷柇盇籺阂哬敆&amp;#34;, &amp;#34;H核盉盍荷啝涸渮盒秴菏萂龁惒粭訸颌楁詥鉌阖鲄熆閡鹖麧澕篕翮魺闔齕覈鶡皬鑉龢佫垎贺寉焃湼賀煂碋褐赫鹤翯壑癋爀鶴齃靍靎鸖靏黒黑嘿潶嬒拫痕鞎佷很狠詪恨亨哼悙涥脝姮恆恒桁烆&amp;#34;, &amp;#34;H珩胻鸻横橫衡鴴鵆蘅鑅堼囍乊乥叿灴轰哄訇烘軣焢硡薨輷嚝鍧轟仜弘妅红吰宏汯玒纮闳宖泓玜苰垬娂洪竑荭虹浤紘翃耾硔紭谹鸿渱竤粠葒葓鈜閎綋翝谼潂鉷鞃魟篊鋐彋蕻霐黉霟鴻黌晎嗊&amp;#34;, &amp;#34;H讧訌撔澋澒銾侯矦喉帿猴葔瘊睺篌糇翭骺鍭餱鯸吼犼后郈厚垕後洉逅候鄇堠豞鲎鲘鮜鱟乎匢虍呼垀忽昒曶泘苸烀轷匫唿惚淴虖軤雽嘑寣滹雐歑囫抇弧狐瓳胡壶壷斛焀喖壺媩湖猢絗葫楜煳&amp;#34;, &amp;#34;H瑚嘝蔛鹕槲箶糊蝴衚魱縠螜醐頶觳鍸餬瀫鬍鰗鶘鶦鶮乕汻虎浒唬萀琥虝箎錿鯱互弖戶户戸冱冴帍护沍沪岵怙戽昈枑祜笏粐婟扈瓠綔鄠嫭嫮摢滬蔰槴熩鳸簄鍙鹱護鳠韄頀鱯鸌花芲埖婲椛硴&amp;#34;, &amp;#34;H糀誮錵蘤华哗姡骅铧滑猾嘩撶璍螖鏵驊鷨化划杹画话崋桦婳畫嬅畵話劃摦槬樺嫿澅諙諣黊繣蘳怀徊淮槐褢踝懐褱懷櫰耲蘹坏壊壞蘾欢歓鴅嚾懽獾歡貛讙驩还环峘洹荁桓萈萑堚寏絙雈羦貆&amp;#34;, &amp;#34;H锾阛寰缳環豲鍰鹮糫繯轘闤鬟睆缓緩攌幻奂肒奐宦唤换浣涣烉患梙焕逭喚嵈愌換渙痪煥瑍豢漶瘓槵鲩擐澣瞣藧鯇鯶鰀巟肓荒衁塃慌皇偟凰隍黃黄喤堭媓崲徨惶湟葟遑楻煌瑝墴潢獚锽熿璜&amp;#34;, &amp;#34;H篁艎蝗癀磺穔諻簧蟥鍠餭鳇趪鐄騜鰉鱑鷬怳恍炾宺晃晄奛谎幌愰詤縨謊櫎皩兤滉榥曂皝鎤灰灳诙咴恢拻挥洃虺晖烣珲豗婎媈揮翚辉隓暉楎琿禈詼幑睳噅噕翬輝麾徽隳瀈鰴囘回囬佪廻廽恛&amp;#34;, &amp;#34;H洄茴迴烠逥痐蛔蛕蜖鮰悔螝毇檓燬譭卉屷汇会讳泋哕浍绘芔荟诲恚恵烩贿彗晦秽喙惠絵缋翙阓匯彙彚毀毁滙詯賄僡嘒蔧誨圚寭慧憓暳槥潓蕙徻橞獩璤薈薉諱頮檅檜燴篲藱餯嚖懳瞺穢繢蟪&amp;#34;, &amp;#34;H櫘繪翽譓闠鐬靧譿顪昏昬荤婚涽阍惽棔睧睯閽忶浑馄渾魂繉鼲诨俒倱圂掍混焝溷慁觨諢吙耠锪劐鍃豁攉騞佸活秮火伙邩钬鈥夥沎或货咟俰捇眓获剨祸貨惑旤湱禍嗀奯濩獲霍檴謋穫镬嚯瀖&amp;#34;, &amp;#34;H耯藿蠖嚿曤臛癨矐鑊夻行砉圜&amp;#34;, &amp;#34;J皀髉畟筴簎笒覘樔伡俥鋤雛處諔堲蠀覿茤岋紇裓構颳夬叏獷臩臦昋鱖妎悎饸紅鵍丌讥击刉叽饥乩刏圾机玑肌芨矶鸡枅咭迹剞唧姬屐积笄飢基绩喞嵆嵇犄筓缉赍勣嗘畸跻鳮僟箕銈嘰撃槣樭&amp;#34;, &amp;#34;J畿稽賫躸齑墼憿機激璣積錤隮磯簊績羁賷櫅耭雞譏韲鶏譤癪躋鞿鷄齎羇虀鑇覉鑙齏羈鸄覊亼及伋吉岌彶忣汲级即极亟佶郆卽叝姞急狤皍笈級揤疾觙偮卙庴脨谻戢棘極殛湒集塉嫉愱楫蒺蝍&amp;#34;, &amp;#34;J趌辑槉耤膌銡嶯潗瘠箿蕀蕺鞊鹡橶檝螏輯襋蹐鍓艥籍轚鏶霵鶺鷑雦雧几己丮妀犱泲虮挤脊掎鱾幾戟嵴麂魢撠擠穖彑旡计记伎纪坖妓忌技芰芶际剂季哜垍峜既洎济紀茍計剤紒继觊記偈寂寄&amp;#34;, &amp;#34;J徛悸旣梞祭惎臮葪兾痵継蓟裚跡際墍暨漃漈禝稩穊誋跽霁鲚暩稷諅鲫冀劑曁穄薊襀髻檕繋罽覬鮆檵蹟鵋齌廭懻癠糭蘎骥鯚瀱繼蘮鱀蘻霽鰶鰿鱭驥加夹抸佳泇迦枷毠浃珈家痂梜笳耞袈猳葭&amp;#34;, &amp;#34;J跏犌腵鉫嘉镓糘豭貑鎵麚圿扴岬郏荚郟恝莢戛铗戞蛱颊蛺跲餄鋏頬頰鴶鵊甲玾胛斚贾钾婽斝椵賈鉀榎槚瘕檟价驾架假嫁幏榢稼駕嗧戋奸尖幵坚歼间冿戔肩艰姦姧兼监堅惤猏笺菅菺湔牋犍&amp;#34;, &amp;#34;J缄葌葏間搛椷煎瑊睷缣蒹箋樫熞緘蕑蕳鲣鹣熸篯縑鋻艱鞬馢麉瀐鞯殱礛覸鵳瀸殲籛韀鰹囏虃韉囝拣枧俭柬茧倹挸捡笕减剪检湕趼揀検減睑硷裥詃锏弿瑐简絸谫彅戩戬碱儉翦檢藆襇襉謇蹇&amp;#34;, &amp;#34;J瞼簡繭謭鬋鰎鹸瀽蠒鐗鐧鹻譾襺鹼见件侟建饯剑洊牮荐贱俴健剣涧珔舰剱徤渐谏釼寋旔楗毽溅腱臶践賎鉴键僭榗劍劎墹澗箭糋諓賤趝踐踺劒劔橺薦鍵餞瞷磵礀螹鍳擶繝覵艦轞鑑鑒鑬鑳江&amp;#34;, &amp;#34;J姜将茳浆畕豇葁翞僵漿螀壃缰薑橿殭螿鳉疅礓疆繮韁鱂讲奖桨傋蒋奨奬蔣槳獎耩膙講顜匞匠夅弜杢降洚绛弶袶絳畺酱摾滰嵹犟糡醤糨醬櫤謽艽芁交郊姣娇峧浇茭骄胶椒焦蛟跤僬嘄虠鲛嬌&amp;#34;, &amp;#34;J嶕嶣憍膠蕉膲礁穚鮫鹪簥蟭鐎鷦鷮櫵臫角佼挢狡绞饺晈笅皎矫脚铰搅筊剿勦敫煍腳賋摷暞踋鉸餃儌劋撹徼敽敿缴曒璬矯皦鵤孂纐攪灚鱎叫呌挍訆珓轿较敎教窖滘嘂嘦斠漖酵噍嬓獥藠趭轎&amp;#34;, &amp;#34;J醮譥皭釂阶疖皆接掲痎秸階喈嗟堦媘揭脻街煯稭鞂蝔擑癤鶛孑尐节讦刦刧劫岊昅刼劼杰衱诘拮洁结迼桀桝莭訐婕崨捷袺傑結颉嵥楶滐睫節蜐詰鉣魝截榤碣竭蓵鲒潔羯誱踕幯嶻擮礍鍻巀櫭&amp;#34;, &amp;#34;J蠞蠘蠽姐毑媎解飷檞丯介岕庎忦戒芥屆届斺玠界畍疥砎衸诫借蚧徣堺楐琾蛶骱犗誡褯魪藉巾今斤钅兓金釒津矜砛衿觔珒紟惍琎堻琻筋璡鹶黅襟仅卺巹紧堇菫僅谨锦嫤廑漌盡緊蓳馑槿瑾錦&amp;#34;, &amp;#34;J謹饉劤尽劲妗近进侭枃勁浕荩晉晋浸烬赆祲進煡缙寖搢溍禁靳瑨僸凚殣觐儘噤縉賮嚍壗嬧濜藎燼璶覲贐齽坕京泾经茎亰秔荆荊婛惊旌旍猄経菁晶稉腈睛粳經兢精聙橸鲸鵛鯨鶁麖鼱驚麠井&amp;#34;, &amp;#34;J丼阱刭宑汫汬肼剄穽颈景儆幜憬璄憼暻燝璟璥頸蟼警妌净弪径迳浄胫凈弳徑痉竞逕婙婧桱梷淨竟竫敬痙傹靖境獍誩静頚曔镜靜瀞鏡競竸冋坰扃埛絅駉駫蘏冏囧迥侰炯逈浻烱煚窘颎綗僒煛&amp;#34;, &amp;#34;J熲澃燛褧蘔丩勼纠朻究糺鸠糾赳阄萛啾揪揫鬏鬮九久乆乣奺汣杦灸玖舏韭紤酒镹韮匛旧臼咎疚柩柾倃桕厩救就廄匓舅僦廏廐慦殧舊鹫鯦麔匶齨鷲欍凥抅匊居拘泃狙苴驹倶挶疽痀罝陱娵婅&amp;#34;, &amp;#34;J婮崌掬梮涺椐琚腒锔裾雎艍蜛諊踘鋦駒鴡鞠鞫鶋局泦侷狊桔毩淗焗菊郹椈毱湨犑輂粷躹閰橘檋駶鵙蹫鵴巈蘜鶪驧咀沮举矩莒挙椇筥榉榘蒟龃聥舉踽擧櫸欅襷句巨讵姖岠怇拒洰苣邭具拠昛&amp;#34;, &amp;#34;J歫炬秬钜俱倨冣剧粔耟蚷袓埧埾惧据詎距焣犋鉅飓虡豦锯愳窭聚駏劇勮屦踞鮔壉懅據澽遽鋸屨颶簴躆醵懼爠姢娟捐涓裐鹃勬鋑镌鎸鵑鐫蠲卷呟帣埍菤锩臇錈奆劵倦勌桊狷绢隽淃瓹眷鄄睊&amp;#34;, &amp;#34;J絭罥睠慻蔨餋羂噘撅撧屩屫亅孒孓决刔氒诀抉芵玦玨挗珏砄绝虳觉倔欮崛掘斍桷殌覐觖訣赽趹厥絕絶覚趉鈌劂瑴谲嶡嶥憰熦爴獗瘚蕝蕨鴂鴃憠橛橜镼爵臄镢蟨蟩爑譎蹶蹷嚼矍覺鐝灍爝觼&amp;#34;, &amp;#34;J彏戄攫玃鷢欔矡龣貜钁军君均汮袀軍钧莙蚐桾皲菌鈞碅筠皸皹覠銁銞鲪麇鍕鮶呁俊郡陖埈峻捃晙浚馂骏珺畯竣箟蜠儁寯懏餕燇駿鵔鵕鵘纟挟廴&amp;#34;, &amp;#34;K錒嵦濭骯奟喫噄鉺朏胐阬槀稾藳溝絓鰥卝丱硄廣胿膭歸楇鉿妔薧蚵毼袔齁恗搰華磆蕐會澮璯餛秳漷監譼槛檻捁撟悈脛踁駃咔咖喀卡佧垰胩裃鉲开奒揩衉锎鐦凯剀垲恺闿铠凱剴慨蒈塏愷楷&amp;#34;, &amp;#34;K輆暟锴鍇鎧闓颽忾炌欬烗勓嘅鎎乫刊栞勘龛堪戡龕冚坎侃砍莰偘惂塪輡竷轗看衎崁墈阚瞰磡矙忼砊粇康嫝嵻慷漮槺穅糠躿鏮鱇扛摃亢伉匟邟囥抗犺闶炕钪鈧閌尻髛攷考拷洘栲烤铐犒銬鲓&amp;#34;, &amp;#34;K靠鮳鯌匼坷苛柯牁珂科胢轲疴趷钶嵙棵痾萪軻颏搕犐稞窠鈳榼薖颗樖瞌磕蝌頦醘顆髁礚壳咳翗嶱可岢炣渇嵑敤渴克刻剋勀勊客峇恪娔尅课堁氪骒缂嗑愙溘锞碦緙課錁礊騍肎肯肻垦恳啃豤&amp;#34;, &amp;#34;K墾錹懇掯裉褃劥吭坑硁牼铿硻誙銵鍞鏗巪乬唟厼怾空倥埪崆悾硿箜躻錓鵼孔恐控鞚廤抠芤眍剾彄瞘口劶叩扣怐敂冦宼寇釦窛筘滱蔲蔻瞉簆鷇刳郀枯哭桍堀崫圐跍窟骷鮬狜苦楛库俈绔庫秙&amp;#34;, &amp;#34;K焅袴喾絝裤瘔酷褲嚳夸姱舿侉咵垮銙挎胯跨骻蒯擓巜凷圦块快侩郐哙狯脍塊筷鲙儈鄶廥獪膾旝糩鱠宽寛寬髋鑧髖梡款窽窾匡劻诓邼匩哐恇洭筐筺誆軭狂狅诳軖軠誑鵟夼儣懭邝圹纩况旷岲&amp;#34;, &amp;#34;K況矿昿贶框眖砿眶絋絖貺軦鉱鋛鄺壙黋懬曠爌矌礦穬纊鑛亏刲岿悝盔窥聧窺虧闚顝蘬奎晆逵鄈頄馗喹揆葵骙戣暌楏楑魁睽蝰頯櫆藈鍨鍷騤夔蘷虁躨卼傀煃跬頍蹞尯匮欳喟媿愦愧溃蒉馈匱&amp;#34;, &amp;#34;K嘳嬇憒篑聩聭蕢樻殨餽簣聵籄鐀鑎坤昆晜堃堒婫崐崑猑菎裈焜琨髠裩锟髡鹍尡潉蜫褌髨熴瑻醌錕鲲臗騉鯤鵾鶤悃捆阃壸梱祵硱稇裍壼稛綑閫閸困涃睏扩拡括挄栝桰筈萿葀蛞阔廓頢濶闊鞟&amp;#34;, &amp;#34;K韕懖霩鞹鬠穒&amp;#34;, &amp;#34;L冫勑粚誺銐寵娕坔釘詻鄜膚鬴茖蛒鎘鉻羮篢睔腂蘫谾瘣暕撿諫倞靓靚牞摎樛畂寠窶垃拉柆啦翋菈邋旯砬揦磖喇藞嚹剌溂腊揧楋瘌蜡蝋辢辣蝲臈攋爉臘鬎櫴瓎镴鯻蠟鑞鞡来來俫倈崃徕涞莱&amp;#34;, &amp;#34;L郲婡崍庲徠梾淶猍萊逨棶琜筙铼箂錸騋鯠鶆麳唻赉睐睞赖賚濑賴頼顂癞鵣瀨瀬籁藾癩襰籟兰岚拦栏婪嵐葻阑蓝谰澜褴儖斓篮燣藍襕镧闌璼襤譋幱攔瀾灆籃繿蘭斕欄礷襴囒灡籣欗讕躝襽鑭&amp;#34;, &amp;#34;L钄韊览浨揽缆榄漤罱醂壈懒覧擥嬾懶孄覽孏攬欖爦纜烂滥燗嚂濫爁爛爤瓓灠糷啷勆郎郞欴狼莨嫏廊桹琅蓈榔瑯硠稂锒筤艆蜋郒螂躴鋃鎯駺悢朗阆朖烺塱蓢樃誏閬朤埌浪蒗唥捞粩撈劳労牢&amp;#34;, &amp;#34;L狫窂哰唠崂浶勞痨铹僗嶗憥朥癆磱簩蟧醪鐒顟髝老佬咾姥恅荖栳珯硓铑蛯銠潦橑鮱轑涝烙嗠耢酪嫪憦澇橯耮軂仂阞乐叻忇扐氻艻玏泐竻砳勒楽韷簕鳓鰳饹餎雷嫘缧蔂樏畾檑縲镭櫑瓃羸礧&amp;#34;, &amp;#34;L纍罍蘲鐳轠壨鑘靁虆鱩欙纝鼺厽耒诔垒塁絫傫誄磊蕌磥蕾儡壘癗藟櫐矋礨灅蠝蘽讄儽鑸鸓肋泪洡类涙淚累酹銇頛頪擂錑攂礌颣類纇蘱禷嘞脷塄棱楞碐稜踜薐冷倰堎愣睖唎刕厘剓梨狸离荲&amp;#34;, &amp;#34;L莉骊悡梸犁菞喱棃犂鹂剺漓睝筣缡艃蓠蜊嫠孷樆璃盠竰糎蔾褵鋫鲡黎篱縭罹錅蟍謧醨嚟藜邌離鯏鏫鯬鵹黧囄灕蘺蠡蠫孋廲劙鑗穲籬驪鱺鸝礼李里俚峛哩娌峲浬逦理裡锂粴裏豊鋰鲤澧禮鯉&amp;#34;, &amp;#34;L蟸醴鳢邐鱧欚力历厉屴立吏朸丽利励呖坜沥苈例岦戾枥疠苙隶俐俪栃栎疬砅茘荔赲轹郦娳悧栗栛栵涖猁珕砺砾秝莅唳婯悷琍笠粒粝蚸蛎傈凓厤棙痢蛠詈跞雳塛慄搮溧蒚蒞鉝鳨厯厲暦歴瑮&amp;#34;, &amp;#34;L綟蜧勵曆歷篥隷鴗巁檪濿癘磿隸鬁儮曞櫔爄犡禲蠇嚦壢攊瀝瓅礪藶櫪爏瓑皪盭礫糲蠣儷癧礰鷅麜囇轢欐讈轣攭瓥靂鱱靋瓈俩倆嫾奁连帘怜涟莲連梿联裢亷嗹廉慩漣蓮匲奩覝劆匳噒憐磏聨&amp;#34;, &amp;#34;L聫褳鲢濂濓縺翴聮薕螊櫣聯臁蹥謰鎌镰簾蠊鬑鐮鰱籢籨敛琏脸裣摙槤璉蔹嬚斂歛臉鄻襝羷练娈炼恋浰殓堜媡湅萰链僆楝煉瑓潋練澰錬殮鍊鏈瀲鰊戀纞簗良俍凉梁涼椋辌粮粱墚綡踉樑輬糧&amp;#34;, &amp;#34;L両两兩唡啢掚脼裲緉蜽魉魎亮哴谅辆喨晾湸量煷輌諒輛鍄蹽辽疗聊僚寥嵺廖憀膋嘹嫽寮嶚嶛憭撩敹獠缭遼暸燎璙窷膫竂镣鹩屪廫簝蟟豂賿蹘爎鐐髎飉鷯钌釕鄝蓼爒镽了尥炓料尞撂瞭咧毟&amp;#34;, &amp;#34;L挘埓列劣冽劽姴峢挒洌茢迾埒浖烈烮捩猎猟蛚裂煭睙聗趔巤颲儠鮤鴷擸獵犣躐鬛鬣鱲邻林临啉崊惏淋晽琳粦痳碄箖粼鄰隣嶙潾獜遴斴暽燐璘辚霖瞵磷臨繗翷麐轔壣瀶鏻鳞驎麟鱗菻亃稟僯&amp;#34;, &amp;#34;L凛凜撛廩廪懍懔澟檁檩癛癝顲吝恡悋赁焛賃蔺橉甐膦閵疄藺蹸躏躙躪轥拎伶刢灵囹坽夌姈岭岺彾泠狑苓昤朎柃玲瓴凌皊砱秢竛铃陵鸰婈崚掕棂淩琌笭紷绫羚翎聆舲菱蛉衑祾詅跉軨蓤裬鈴&amp;#34;, &amp;#34;L閝零龄綾蔆輘霊駖澪蕶錂霗魿鲮鴒鹷燯霛霝齢瀮酃鯪孁蘦齡櫺醽靈欞爧麢龗阾袊领領嶺令另呤炩溜熘刘沠畄浏流留旈琉畱硫裗媹嵧旒蒥蓅遛馏骝榴瑠飗劉瑬瘤磂镏駠鹠橊璢疁镠癅蟉駵嚠&amp;#34;, &amp;#34;L懰瀏藰鎏鎦餾麍鏐飀鐂騮飅鰡鶹驑柳栁桞珋桺绺锍綹熮罶鋶橮羀嬼六翏塯廇澑磟鹨蹓霤雡飂鬸鷚瓼甅囖龙屸咙泷茏昽栊珑胧眬砻笼聋隆湰嶐槞漋癃窿篭嚨巃巄蘢鏧霳曨朧櫳爖瓏矓礱礲襱&amp;#34;, &amp;#34;L籠聾蠪蠬龓豅躘鑨靇鸗陇垄垅拢儱隴壟壠攏竉哢梇硦徿贚娄偻婁喽溇蒌僂楼嘍廔慺蔞遱樓熡耧蝼瞜耬艛螻謱軁髅鞻髏嵝搂塿嶁摟漊甊篓簍陋屚漏瘘镂瘺瘻鏤露噜撸嚕擼卢庐芦垆枦泸炉栌&amp;#34;, &amp;#34;L胪轳舮鸬玈舻颅鈩鲈魲盧嚧壚廬攎瀘獹璷蘆櫨爐瓐臚矑籚纑罏艫蠦轤鑪顱髗鱸鸕黸卤虏挔捛掳鹵硵鲁虜塷滷蓾樐澛魯擄橹磠镥瀂櫓氌艣鏀艪鐪鑥圥甪陆侓坴彔录峍勎赂辂陸娽淕淥渌硉菉&amp;#34;, &amp;#34;L逯鹿椂琭祿禄僇剹勠滤盝睩碌稑賂路塶廘摝漉箓粶蔍戮樚熝膔膟觮趢踛辘醁潞穋蕗錄録錴璐簏螰鴼濾簶蹗轆騄鹭簬簵鏕鯥鵦鵱麓鏴騼籙觻虂鷺氇驴闾榈閭馿膢櫚藘曥鷜驢吕呂侣郘侶旅梠&amp;#34;, &amp;#34;L焒祣稆铝屡絽缕屢膂膐褛鋁履褸儢穞縷穭寽垏律哷虑率绿嵂氯葎綠緑慮箻勴繂櫖爈鑢孪峦挛栾鸾脔滦銮鵉圝奱孌孿巒攣曫欒灓羉臠圞灤虊鑾癴癵鸞卵乱釠亂掠略畧锊圙鋝鋢抡掄仑伦囵沦&amp;#34;, &amp;#34;L纶侖轮倫陯圇婨崘崙惀淪菕棆腀碖綸蜦踚輪磮錀鯩稐耣论埨溣論捋頱囉罗啰猡脶萝逻椤腡锣箩骡镙螺羅覶鏍儸覼騾玀蘿邏欏鸁籮鑼饠驘剆倮砢蓏裸躶瘰蠃臝攞曪癳泺峈洛络荦骆珞笿絡落&amp;#34;, &amp;#34;L摞漯犖雒駱鮥鵅纙鱳&amp;#34;, &amp;#34;M絔硥苾牑訬仯哋尒尓爾坆呒撫羙秏狢貈貉湏惛殙貇氂犛厸龍龒嘸呣妈媽嬤嬷麻痲嫲蔴犘蟆蟇马犸玛码蚂馬溤獁遤瑪碼螞鎷鷌鰢亇杩祃閁骂唛傌睰嘜榪禡罵駡礣鬕吗嗎嘛埋霾买荬買嘪蕒鷶&amp;#34;, &amp;#34;M劢迈佅売麦卖脉脈麥衇勱賣邁霡霢颟顢姏悗蛮慲摱馒樠瞒瞞鞔饅鳗鬗鬘鰻蠻屘満睌满滿螨襔蟎鏋矕曼僈谩墁幔慢漫獌缦蔄蔓熳澷镘縵蟃謾鏝蘰牤邙吂忙汒芒杗杧盲厖恾笀茫哤娏浝牻硭釯&amp;#34;, &amp;#34;M铓痝蛖鋩駹蘉莽莾茻壾漭蟒蠎匁猫貓毛矛枆牦茅旄渵軞酕蛑锚緢髦蝥錨蟊鶜冇卯戼峁泖茆昴铆笷蓩鉚冃皃芼冐茂冒眊贸耄袤覒媢帽貿鄚愗暓楙毷瑁瞀貌鄮蝐懋唜庅嚒濹嚰么癦沒没枚玫苺&amp;#34;, &amp;#34;M栂眉脄莓梅珻脢郿堳媒嵋湄湈猸睂葿楣楳煤瑂禖腜塺槑酶镅鹛鋂霉徾鎇矀攗蘪鶥攟黴毎每凂美挴浼媄嵄渼媺镁嬍燘躾鎂黣妹抺沬昧祙袂眛媚寐痗跊鬽煝睸魅篃蝞嚜椚门扪玣钔門閅捫菛璊&amp;#34;, &amp;#34;M穈鍆虋闷焖悶暪燜懑懣们們掹擝氓甿虻冡庬罞萌萠夢溕盟甍儚橗瞢蕄蝱鄳鄸幪懞濛獴曚朦檬氋矇礞鯍艨鹲矒靀饛顭鸏勐猛瓾蒙锰艋蜢錳懵蠓鯭鼆孟梦夣懜霥踎咪瞇冞弥祢迷猕谜蒾詸謎醚&amp;#34;, &amp;#34;M擟糜縻麊麋靡獼麛爢戂攠蘼醾醿鸍釄米羋芈侎弭洣敉粎脒眯渳葞蝆蔝銤孊灖糸汨宓泌觅峚祕宻秘密淧覓覔幂谧塓幎覛嘧榓滵漞熐蔤蜜鼏冪樒幦濗藌謐櫁簚羃芇眠婂绵媔棉綿緜臱蝒嬵檰櫋&amp;#34;, &amp;#34;M矈矊矏丏汅免沔黾俛勉眄娩偭冕勔喕愐湎缅葂腼緬鮸靣面糆麪麫麺麵喵苗媌描瞄鹋嫹鶓鱙杪眇秒淼渺缈篎緲藐邈妙庙竗庿廟吀咩哶孭灭搣滅蔑薎鴓幭懱瀎篾櫗蠛衊鑖鱴瓱民垊姄岷怋旻旼&amp;#34;, &amp;#34;M玟苠珉盿冧罠崏捪琘琝缗暋瑉痻碈鈱緍緡錉鍲皿冺刡闵抿泯勄敃闽悯敏笢笽湣閔愍敯黽閩僶慜憫潣簢鳘蠠鰵名明鸣洺眀茗冥朙眳铭鄍嫇溟猽蓂暝榠銘鳴瞑螟覭佲姳凕慏酩命掵詺谬缪繆謬&amp;#34;, &amp;#34;M摸嚤尛谟嫫馍摹模膜麼麽摩魹橅磨糢謨謩擵饃嚩蘑髍魔劘饝抹懡麿末劰圽妺怽歿殁沫茉陌帞昩枺皌眜眿砞秣莈莫眽粖絈袹蛨貃嗼塻寞漠蓦貊銆墨嫼暯瘼瞐瞙镆魩黙縸默貘藦蟔鏌爅驀礳纆&amp;#34;, &amp;#34;M耱乮哞牟侔劺恈洠眸谋鉾謀鍪鴾麰某母毪獏氁亩牡姆拇峔牳畆畒胟畝畞砪畮鉧踇木仫目凩沐狇坶炑牧苜毣莯蚞钼募萺雮墓幕幙慔楘睦鉬慕暮艒霂穆鞪旀丆椧渑&amp;#34;, &amp;#34;N懝抝拗秅莀袲唸毭咹児兒耏聏峊廾嫨跈聻茮澆涳巙崀尦竜袮彌镾濔瀰乜樢拏拿誽镎鎿乸哪雫内那吶妠纳肭娜衲钠納袦捺笝豽軜貀嗱蒳靹魶腉熋孻乃奶艿氖疓妳廼迺倷釢嬭奈柰耐萘渿鼐褦&amp;#34;, &amp;#34;N螚錼囡男抩枏枬侽南娚畘莮难喃遖暔楠煵諵難赧揇湳萳腩蝻戁婻囔乪嚢囊鬞馕欜饢擃曩攮灢儾齉孬檂呶怓挠峱硇铙猱蛲詉碙嶩夒鐃巎獿垴恼悩脑匘脳堖惱嫐瑙腦碯闹婥淖閙鬧讷呐眲訥呢&amp;#34;, &amp;#34;N馁腇餒鮾鯘氝焾嫩能莻鈪銰啱妮尼坭怩泥籾倪屔秜郳铌埿婗淣猊蚭棿跜鈮蜺觬貎霓鲵鯢麑齯臡伱伲你拟抳狔苨柅旎晲馜儞隬擬薿檷鑈氼迡昵胒逆匿痆眤堄惄嫟愵溺睨腻暱縌膩嬺拈年秊哖&amp;#34;, &amp;#34;N秥鲇鮎鲶鵇黏鯰捻辇撚撵碾輦簐攆躎卄廿念姩埝娘嬢酿醸釀鸟茑袅嫋裊蔦嬝褭嬲尿脲捏揑帇圼苶枿陧涅聂臬啮惗隉敜嗫嵲踂摰踗踙镊镍嶭篞臲錜颞蹑鎳闑孼孽櫱籋蘖齧巕糱糵蠥囓讘躡鑷&amp;#34;, &amp;#34;N顳脌囜您拰宁咛拧狞柠聍寍寕寜寧儜凝嚀嬣擰獰薴檸聹鑏鬡鸋橣矃佞侫泞甯寗澝濘妞牛牜忸扭沑狃纽杻炄钮紐鈕靵农侬哝浓脓秾農儂辳噥憹濃蕽禯膿穠襛醲欁繷弄挊挵癑齈羺譨啂槈耨鎒&amp;#34;, &amp;#34;N鐞譳奴孥驽笯駑伮努弩砮胬怒傉搙女钕籹釹衂恧朒衄疟虐瘧奻渜暖煗餪硸黁燶郍挪梛傩搻儺橠诺喏掿逽搦锘榒稬諾糑懦懧糥穤糯恁蔫&amp;#34;, &amp;#34;O吽摳噢哦筽夞乯鞰讴欧殴瓯鸥塸歐熰甌膒鴎櫙藲鏂鷗吘呕偶腢耦蕅藕怄沤慪漚&amp;#34;, &amp;#34;P钯鈀跁罷猈螌褩闆湴牓棓徬鎊剝襃铇袌鉋鮑琲絣痭琣逬跰螕鎞粃枈痺辟稫箆鞞猵萹拚徧緶辯骉蔈颮麃藨謤穮驃驫摽汃砏璸鉼碆磻犻苩瓟桲淿湐猼馞嚗髆蚾獛鵏吥荹鈈郶茷籓膰趽彷衯夆馮&amp;#34;, &amp;#34;P摓垺妚尃豧巿襆襥脯蜅秿鈲窌攈脟濼尨眫冖覕屰妑皅趴舥啪葩杷爬耙琶筢潖帊帕怕袙拍俳徘排猅棑牌箄輫簰犤哌派湃蒎鎃磗眅畨潘攀爿柈盘跘媻幋蒰搫槃磐縏蹒瀊蟠蹣鎜鞶坢冸判沜泮炍&amp;#34;, &amp;#34;P叛牉盼畔袢詊溿頖鋬鵥襻鑻乓汸沗肨胮雱滂膖霶厐庞逄旁舽嫎篣螃鳑龎龐鰟蠭嗙耪覫髈炐胖抛拋脬刨咆垉庖狍炮炰爮袍匏蚫軳鞄褜麅跑奅泡疱皰砲萢麭礟礮呸怌肧柸胚衃醅阫陪陫培毰赔&amp;#34;, &amp;#34;P锫裴裵賠錇俖伂沛佩帔姵斾旆浿珮配笩蓜辔馷嶏霈轡喷噴濆歕瓫盆湓葐呠翉翸喯匉怦抨泙恲胓砰梈烹硑軯閛漰嘭駍磞芃朋挷竼倗莑堋弸彭棚椖傰塜塳搒漨硼稝蓬鹏槰樥熢憉澎輣篷膨錋韸&amp;#34;, &amp;#34;P髼蟚蟛鬅纄韼鵬騯鬔鑝捧淎皏剻掽椪碰踫浌巼闏乶喸丕伓伾批纰邳坯怶披抷炋狉狓砒悂秛秠紕铍旇翍耚豾鈚鈹鉟銔劈磇駓髬噼錃錍魾憵礔礕闢霹皮阰芘岯枇毞肶毗毘疲笓蚍郫陴啤埤崥蚽&amp;#34;, &amp;#34;P豼椑焷琵脾腗榌鲏罴膍蜱隦魮壀鮍篺螷貔簲羆鵧朇鼙蠯匹庀仳圮苉脴痞銢諀鴄擗噽癖嚭屁淠渒揊媲嫓睤睥潎僻澼甓疈譬鷿鸊片囨偏媥犏篇翩鶣骈胼腁楄楩賆諚骿蹁駢騈覑谝貵諞骗魸騗騙&amp;#34;, &amp;#34;P剽彯漂缥飘磦旚縹翲螵犥飃飄魒瓢薸闝殍瞟篻醥皫顠票僄勡嘌嫖徱慓氕撇撆暼瞥丿苤鐅嫳姘拼礗穦馪驞玭贫貧琕嫔频頻嬪薲嚬矉颦顰品榀朩牝汖娉聘乒甹俜涄砯艵竮頩平评凭呯坪岼苹郱&amp;#34;, &amp;#34;P屏帡枰洴玶荓娦瓶屛帲淜萍蚲塀幈焩甁缾聠蓱蛢評軿鲆凴慿箳輧憑鮃檘簈蘋钋坡岥泼娝釙颇溌酦潑醱鏺婆嘙蔢鄱皤謈櫇叵尀钷笸鉕駊廹岶迫敀昢洦珀哱烞破砶粕蒪頗魄剖颒抔抙捊掊裒箁&amp;#34;, &amp;#34;P咅哣婄犃兺哛仆攴扑抪炇巬巭柨陠痡铺駇噗撲鋪擈鯆圤匍莆菩菐葡蒱蒲僕酺墣璞濮瞨穙镤贌纀鏷朴圃埔浦烳普圑溥暜谱潽樸氆諩檏镨譜蹼鐠舖舗曝&amp;#34;, &amp;#34;Q摮磝朁鸧鶬鼜詧軙儭櫬趍袳創敠匚釓隑矼肐鉤扢琯矔鸛龜氿肣馯抲頜礉隺渹舙酄攲敧稘毄緝觭禨鄿鐖饑焏踖躤蟣済萕濟袷唊脥價靬鳒鰜鶼鑯揃葥漸摪彊勥焳燋湫湬蟜譑峤嶠潐噭椄疌倢偼&amp;#34;, &amp;#34;Q媫蛣楬鮚荕埐嶜厪墐慬歏濅涇鶄捄趄跔鮈跼趜弆瞿鐻捲弮蚗傕鶌躩麏麕焌箘開欿歁殻揢挳硜矻誇厱熑燫艌鳥毆七迉沏妻柒倛凄栖桤缼郪娸悽戚捿桼淒萋朞期欺紪褄僛嘁慽榿槭漆緀慼磎諆&amp;#34;, &amp;#34;Q霋蹊魌鏚鶈亓祁齐圻岐岓芪其奇斉歧祈肵疧竒剘斊旂耆脐蚑蚚颀埼崎帺掑淇渏猉畦萁跂軝釮骐骑棊棋琦琪祺蛴愭碁碕褀頎鬾鬿旗粸綥綦綨緕蜝蜞璂禥蕲踑螧鲯懠濝藄檱櫀簱臍騎騏鳍蘄鯕&amp;#34;, &amp;#34;Q鵸鶀麒籏纃艩蠐鬐騹魕鰭玂麡乞邔企屺岂芑启呇杞玘盀唘豈起啓啔啟婍绮晵棨綮諬簯闙气讫気汔迄弃汽矵芞呮泣炁盵咠契砌荠栔訖唭欫夡愒棄湆湇葺碛摖暣甈碶噐憇器憩磜磧薺礘罊蟿掐&amp;#34;, &amp;#34;Q葜拤跒酠鞐圶冾帢恰洽殎硈愘髂千仟阡奷扦汘芊迁佥岍杄汧茾竏钎拪牵粁悭蚈谸铅婜牽釺谦雃僉愆签骞鹐搴摼撁箞諐遷褰顅檶攐攑櫏簽鏲鵮攓騫鐱鬜鬝籤韆仱岒忴扲拑乹前钤歬虔钱钳乾&amp;#34;, &amp;#34;Q偂掮揵軡媊鈐鉗墘榩箝銭潜橬錢黔鎆黚騝濳騚灊籖鰬浅肷淺嵰慊遣蜸潛谴缱繾譴鑓欠刋芡茜倩悓堑傔嵌棈椠皘蒨塹歉蔳儙槧篏輤篟壍嬱縴呛羌戕戗斨枪玱猐琷跄嗴椌獇腔嗆溬蜣锖嶈戧槍&amp;#34;, &amp;#34;Q牄瑲羫锵篬錆蹌镪蹡鎗鏘鏹強强墙嫱蔷樯漒蔃墻嬙檣牆謒艢蘠抢羟搶羥墏摤繈襁繦炝唴熗羻兛瓩悄硗郻鄗嵪跷鄡鄥劁敲踍锹墝碻頝墽幧橇缲磽鍫鍬繑趬蹺蹻乔侨荍荞桥硚喬僑槗谯嘺嫶憔&amp;#34;, &amp;#34;Q蕎鞒樵橋犞癄瞧礄藮譙趫鐈鞽顦巧釥愀髜俏诮陗峭帩窍殼翘誚髚僺撬鞘竅翹躈切苆癿茄聺且厒妾怯匧窃倿悏挈洯惬淁笡愜蛪朅箧緁锲魥篋踥穕藒鍥鯜鐑竊籡亲侵钦衾骎菳媇嵚誛嶔親顉駸&amp;#34;, &amp;#34;Q鮼寴庈芩芹埁珡矝秦耹菦蚙捦琴琹禽鈙雂勤嗪溱靲噙擒斳鳹懄檎澿瘽螓懃蠄坅昑笉梫赾寑锓寝寢鋟螼吢吣抋沁唚菣揿搇撳瀙藽靑青氢轻倾卿郬圊氫淸清傾廎蜻輕鲭鑋夝甠剠勍情殑硘晴棾&amp;#34;, &amp;#34;Q氰葝暒擏樈擎檠黥苘顷请庼頃漀請檾謦庆凊掅碃箐靘慶磬儬濪罄櫦宆跫銎卭邛穷穹茕桏笻筇赹惸焪焭琼舼蛩蛬煢熍睘瞏窮儝憌橩璚藑竆藭丘丠邱坵恘秋秌寈蚯媝萩楸鹙篍緧蝵穐趥鳅蟗鞦&amp;#34;, &amp;#34;Q鞧蘒鰌鰍鶖龝叴囚扏犰玌朹肍求虬泅虯俅觓訄訅酋唒浗紌莍逎逑釚梂殏毬球赇釻崷巯湭皳盚遒煪絿蛷裘巰觩賕璆蝤銶醔鮂鼽鯄鵭蠤鰽搝糗区曲佉匤岖诎阹驱坥屈岴抾浀祛胠袪區蛆躯筁粬&amp;#34;, &amp;#34;Q蛐詘趋嶇駆憈敺誳駈麹髷趨麯軀麴黢驅鰸鱋佢劬斪朐菃衐鸲淭渠絇葋軥蕖璖磲螶鴝璩翵蟝鼩蘧匷忂灈戵欋氍籧臞癯蠷衢躣蠼鑺鸜取竘娶紶詓竬龋齲厺去刞呿迲郥耝阒觑趣閴麮闃覰覷鼁覻&amp;#34;, &amp;#34;Q峑悛圈圏棬駩騡鐉全权佺诠姾泉洤荃拳牷辁啳埢婘惓痊硂铨湶犈筌絟腃葲搼楾瑔觠詮輇蜷銓権踡縓醛闎鳈鬈孉巏鰁權齤蠸颧顴犬汱畎烇绻綣虇劝券巻牶椦勧韏勸炔缺蒛瘸却埆崅悫雀硞确&amp;#34;, &amp;#34;Q阕塙搉皵阙鹊愨榷墧慤毃確趞燩闋礐闕鵲礭夋囷峮逡宭帬裙羣群裠郄&amp;#34;, &amp;#34;R吺兊兌熯卪坈繚髳挐鈉柟蟯臑抐內涊蹨孃菍莥獳檽蹃亽罖囕呥肰衻袇蚦袡蚺然髥嘫髯燃繎冄冉姌苒染珃媣蒅穣瀼獽禳瓤穰躟鬤壌嚷壤攘爙让懹譲讓荛饶桡橈襓饒犪扰娆隢擾绕遶繞惹热熱&amp;#34;, &amp;#34;R人仁壬忈朲忎秂芢鈓魜銋鵀忍荏栠栣荵秹稔綛躵刃刄认仞仭讱任屻扨纫妊杒牣纴肕轫韧饪姙紉衽紝訒軔梕袵絍腍靭靱韌飪認餁扔仍辸礽芿陾日驲囸釰鈤馹戎肜栄狨绒茙茸荣容峵毧烿媶嵘&amp;#34;, &amp;#34;R絨羢嫆搈搑摉榵溶蓉榕榮熔瑢穁蝾褣镕氄縙融螎駥髶嬫嶸爃鎔瀜曧蠑冗宂傇軵穃厹禸柔粈媃揉渘葇瑈腬糅蝚蹂輮鍒鞣瓇騥鰇鶔楺煣韖肉宍嶿邚如侞帤茹桇袽铷渪筎蒘銣蕠儒鴑嚅嬬孺濡薷&amp;#34;, &amp;#34;R鴽曘燸襦蠕颥醹顬鱬汝肗乳辱鄏入扖込杁洳嗕媷溽缛蓐鳰褥縟擩堧撋壖阮朊软耎偄軟媆愞瑌腝嫰碝緛蝡輭瓀礝桵甤緌蕤蕊蕋橤繠蘂蘃芮枘蚋锐瑞睿叡壡闰润閏閠潤橍叒若偌弱鄀婼渃焫楉&amp;#34;, &amp;#34;R嵶蒻箬篛爇鰙鰯鶸&amp;#34;, &amp;#34;S鉍灬杓攃偲纔參叄叅喰傪穇懆鄵拺笧粣鎈褨剎摻攙摌顫塲場綝乗娍匙飭埫醻敊猭漺輴縒棇楤漎憁缞縗鎝単單擔伔僤宲鍉遞遰挕阇闍陏蘴棴丨鞨咶鏸韢閄靃濈櫼帴菨嫅潏麗攦療蕯瀧氀稤蠰&amp;#34;, &amp;#34;S娞淰掱忯圱圲凵廧薔鐰韒鞩嫀殸棯葚挼仨桬撒洒訯靸潵卅飒脎萨摋隡馺颯薩櫒栍毢愢揌塞毸腮嘥噻鳃顋嗮赛僿賽簺虄三弎叁毵毶厁毿犙鬖壭伞傘散糁糂馓橵糝糣糤繖鏒饊俕閐桒桑槡嗓搡&amp;#34;, &amp;#34;S磉褬颡鎟顙丧喪掻慅搔溞骚缫臊鳋颾騒鰠鱢扫掃嫂埽瘙氉矂髞色栜涩啬渋铯歮琗嗇瑟歰銫澁懎擌濇濏瘷穑澀璱瀒穡繬穯轖鏼譅飋裇聓森槮襂僧鬙閪縇杀沙纱乷砂唦挱猀粆紗莎铩痧硰蔱裟&amp;#34;, &amp;#34;S樧魦鲨閷鎩鯊鯋繺傻儍繌倽唼啥帹萐喢歃煞翜翣閯霎筛篩簁簛晒曬山彡邖圸删刪杉杣芟姗衫钐埏狦珊舢痁脠軕笘閊跚剼搧嘇幓煽蔪潸澘曑檆膻鯅羴羶闪陕炶陝閃晱煔睒熌覢讪汕疝苫扇訕&amp;#34;, &amp;#34;S赸傓善椫銏骟僐鄯墠墡缮嬗擅敾樿膳磰謆赡繕蟮譱贍鐥饍騸鳝灗鱔伤殇商觞傷墒慯滳蔏殤熵螪觴謪鬺裳垧扄晌赏賞鑜丄上仩尙尚恦绱緔弰捎梢烧焼稍旓筲艄蛸輎蕱燒髾鮹勺芍柖玿韶少劭&amp;#34;, &amp;#34;S卲邵绍哨娋袑紹綤潲奢猞赊畲輋賒賖檨舌佘蛇蛥舍捨厍设社舎厙射涉涻渉設赦弽慑摄滠慴摵蔎蠂韘騇懾灄麝欇申屾扟伸身侁呻妽籶绅罙诜柛氠珅穼籸娠峷甡眒砷堔深紳兟椮葠裑訷罧蓡詵&amp;#34;, &amp;#34;S甧蔘燊薓駪鲹鯓鵢鯵鰺神榊鉮鰰邥弞抌沈审矤哂矧宷谂谉婶渖訠審諗頣魫曋瞫嬸瀋覾讅肾侺昚甚胂涁眘渗祳脤腎愼慎椹瘆蜃滲鋠瘮升生阩呏声斘昇枡泩苼殅牲珄竔胜陞曻陹笙湦焺甥鉎聲&amp;#34;, &amp;#34;S鍟鼪鵿绳憴澠譝省眚偗渻圣晟晠剰盛剩勝貹嵊聖墭榺蕂橳賸尸失师呞虱诗邿鸤屍施浉狮師絁湤湿葹溮溼獅蒒蓍詩瑡酾鳲蝨鳾褷鲺鍦鯴鰤鶳襹籭釃十饣什石辻佦时竍识实実旹飠峕拾炻祏蚀&amp;#34;, &amp;#34;S食埘時莳寔湜遈塒嵵溡蒔榯蝕鉽篒鲥鮖鼫鼭鰣史矢乨豕使始驶兘屎笶榁鉂駛士氏礻世丗仕市示卋式叓事侍势呩柹视试饰冟室恀恃拭是枾柿眂贳适栻烒眎眡舐轼逝铈視釈崼弑揓谥貰释勢嗜&amp;#34;, &amp;#34;S弒煶睗筮觢試軾鈰飾舓誓奭噬嬕澨諟諡遾餝螫簭籂襫鰘兙瓧収收手守垨首艏寿受狩兽售授绶痩膄壽瘦綬夀獣獸鏉书殳抒纾叔杸枢陎姝柕倏倐書殊紓掓梳淑焂菽軗鄃疎疏舒摅毹毺綀输跾踈&amp;#34;, &amp;#34;S樞蔬輸橾鮛攄瀭鵨尗秫婌孰赎塾熟璹贖暏暑黍署鼠鼡蜀潻薯曙癙襡糬襩籔蠴鱪鱰朮术戍束沭述侸怷树竖荗恕庶庻絉蒁術裋数竪腧墅漱潄數澍豎樹濖錰鏣鶐虪刷唰耍誜衰摔甩帅帥蟀卛闩拴&amp;#34;, &amp;#34;S閂栓涮腨双滝霜雙孀骦孇騻欆礵鷞鹴艭驦鸘爽塽慡樉縔鏯灀谁脽誰氵水氺閖帨涗涚祱税裞睡吮楯顺舜順蕣橓瞚瞤瞬鬊说妁烁朔铄欶硕矟嗍搠蒴嗽槊碩鎙厶丝司糹私咝泀俬思恖鸶媤斯絲缌&amp;#34;, &amp;#34;S蛳楒禗鉰飔凘厮榹禠罳銯锶嘶噝廝撕澌緦蕬螄鍶蟖蟴颸騦鐁鷥鼶死巳亖四罒寺汜伺似佀兕姒泤祀価孠泗饲驷俟娰柶牭梩洍涘肂飤笥耜釲竢覗嗣肆貄鈻飼禩駟蕼儩騃瀃螦乺忪松枀枩娀柗倯&amp;#34;, &amp;#34;S凇梥崧庺淞菘嵩硹蜙憽檧濍鬆怂悚捒耸竦傱愯嵷慫聳駷讼宋诵送颂訟頌誦餸鎹凁捜鄋嗖廀廋搜溲獀蒐蓃馊飕摗锼艘螋醙鎪餿颼騪叟傁嗾瞍擞薮擻藪櫢瘶苏甦酥稣窣穌鯂蘇蘓櫯囌俗玊夙诉&amp;#34;, &amp;#34;S泝肃洬涑珟素速殐粛骕傃粟訴谡嗉塐塑嫊愫溯溸肅遡鹔僳愬榡膆蔌觫趚遬憟樎樕潥鋉餗縤璛簌藗謖蹜驌鱐鷫狻痠酸匴祘笇筭蒜算夊芕虽倠哸浽荽荾眭葰滖睢熣濉鞖雖绥隋随遀綏隨瓍膸瀡&amp;#34;, &amp;#34;S髄髓亗岁砕祟粋谇埣嵗脺遂歲歳煫碎隧嬘澻穂誶賥檖燧璲禭穗穟繀襚邃旞繐繸鐆譢鐩孙狲荪飧搎猻蓀飱槂蕵薞畃损笋隼損榫箰鎨巺潠唆娑莏傞挲桫梭睃嗦羧蓑摍缩趖簑簔縮髿鮻所唢索琐&amp;#34;, &amp;#34;S琑惢锁嗩暛溑瑣鎍鎖鎻鏁逤溹蜶厦忄莘疋栅属&amp;#34;, &amp;#34;T諳啚裧儃禪蟬繵閶瞋鐺珵侱漦爞綢籌俶埱蓴鶉鈶撘迏迖沓荅逹溚達鎉韃呔蚮軚貸癉撣嘾彈餤黨攩欓逿蕩簜蘯闣朷焘燾僜奃髢詆弚苐媂諦顚顛鈿调蓧啑惵趃奵忊墥峝湩詷钭鋀褍蜳橔囤庉憞&amp;#34;, &amp;#34;T燉軃鋨鞈騩咍漢宊她冂燑轁墤謉饋噋擴斄伖鍩奤嵜鉆汭蟺鱓愓漡苕萔姼忕徥褆扌涭瑹儵稅磃鋖枱他它牠祂咜趿铊塌榙溻褟蹹侤塔墖獭鮙鳎獺鰨挞狧闼崉涾搨遝遢阘榻毾禢撻澾誻踏嚃錔嚺&amp;#34;, &amp;#34;T濌蹋鞜闒鞳闥譶躢襨囼孡骀胎台邰坮抬苔炱炲跆鲐箈臺颱儓鮐嬯擡薹檯籉太冭夳忲汰态肽钛泰粏舦酞鈦溙態燤坍贪怹啴痑舑貪摊滩嘽潬瘫擹攤灘癱坛昙倓谈郯婒惔弾覃榃痰锬谭墰墵憛潭&amp;#34;, &amp;#34;T談醈壇曇檀顃罈藫壜譚貚醰譠罎鷤忐坦袒钽菼毯鉭嗿憳憻暺醓璮叹炭埮探傝湠僋嘆碳舕歎賧汤铴嘡劏羰蝪薚镗蹚鏜鐋鞺鼞饧坣唐堂傏啺棠鄌塘嵣搪溏蓎隚榶漟煻瑭禟膅樘磄糃膛橖篖糖螗&amp;#34;, &amp;#34;T踼糛螳赯醣鎕餹闛饄鶶帑倘偒淌傥耥躺镋鎲儻戃曭爣矘钂烫摥趟燙仐夲弢涛绦掏絛詜嫍幍慆搯滔槄瑫韬飸縚縧濤謟鞱韜饕迯咷洮逃桃陶啕梼淘绹萄祹裪綯蜪鞀醄鞉鋾錭駣檮騊鼗讨套討畓&amp;#34;, &amp;#34;T忑忒特貣脦铽慝鋱蟘膯鼟疼痋幐腾誊漛滕邆縢螣駦謄儯藤騰籐鰧籘虅驣霯唞朰剔梯锑踢銻鷈鷉厗绨偍珶啼崹惿提渧稊缇罤遆鹈嗁瑅綈碮徲漽緹蕛蝭题趧蹄醍謕蹏鍗鳀題鮷鵜騠鯷鶗鶙体挮&amp;#34;, &amp;#34;T躰骵軆體戻屉剃洟倜悌涕逖悐惕掦逷惖揥替楴裼褅殢髰嚏鬀瓋鬄籊天兲婖添酟靔黇靝田屇沺恬畋畑胋畠甛甜菾湉填搷阗碵緂磌窴鴫璳闐鷆鷏忝殄倎唺悿捵淟晪琠腆觍痶睓舔餂覥賟錪靦掭&amp;#34;, &amp;#34;T瑱睼舚旫佻庣挑祧聎芀条岧岹迢祒條笤蓚龆樤蜩鋚鞗髫鲦螩鯈鎥齠鰷宨晀朓脁窕誂窱嬥眺粜絩覜趒跳頫糶贴萜貼铁蛈僣鴩鐡鐵驖呫帖飻餮厅庁汀艼听耓厛烃烴綎鞓聴聼廰聽廳邒廷亭庭莛&amp;#34;, &amp;#34;T停婷嵉渟筳葶蜓楟榳閮霆聤蝏諪鼮圢侹娗挺涏梃烶珽脡艇颋誔鋌頲濎乭囲炵通痌嗵蓪樋熥仝同佟彤峂庝哃狪茼晍桐浵烔砼蚒眮秱铜童粡絧衕酮鉖僮勭銅餇鲖潼曈朣橦氃犝膧瞳鮦统捅桶筒&amp;#34;, &amp;#34;T統綂恸痛慟憅偷偸鍮头投骰頭妵紏敨斢黈蘣透凸禿秃怢突唋涋捸堗湥痜葖嶀鋵鵚鼵図图凃峹庩徒捈涂荼途屠梌揬稌塗嵞瘏筡腯蒤鈯圖圗廜跿酴馟鍎駼鵌鶟鷋鷵土圡吐汢钍釷兎迌兔莵堍菟&amp;#34;, &amp;#34;T鵵湍猯煓貒团団抟團慱槫檲鏄糰鷒鷻圕疃彖湪褖推蓷藬颓隤頹頺頽魋穨蘈蹪俀脮腿僓蹆骽退娧煺蜕褪駾吞呑朜焞暾黗屯芚饨豘豚軘鲀魨霕臀臋氽畽坉乇讬托汑饦侂咃拕拖沰侻莌袥託涶脫&amp;#34;, &amp;#34;T脱飥魠驮佗陀坨岮沱驼柁砣砤袉鸵紽堶跎酡碢馱槖駄踻駝駞橐鮀鴕鼧騨鼍驒鼉妥毤庹媠椭楕嫷橢鵎拓柝唾跅毻箨籜&amp;#34;, &amp;#34;U辪癷袰蝊曢聣烪燞躼蒊蓞耂稥洜毜毝茒桛毮朑焽虲鶑鎼鐢艈霻闧焑屗歚徚鍂藔贘皼斏聁祍&amp;#34;, &amp;#34;W趡惡噁唲陚龏萖関闗關貫窐姽恑瞶咼堝濄幠膴鋘譁瀤綄朚撝蒦嚄擭雘艧扝噲抂巋磈薶槾鄤澫堥夘呅韎雺霿沕忞鴖譕帓歾靺瞴蟱墲娒孯掔瓗渞蜹捼琞亠撱鰖屲劸哇娃徍挖洼娲畖窊媧嗗蛙搲&amp;#34;, &amp;#34;W溛漥窪鼃攨瓦佤邷咓瓲砙袜嗢腽膃襪韈韤歪喎竵崴外弯剜婠帵塆湾睕蜿潫豌彎壪灣丸刓汍纨芄完岏忨抏玩笂紈捖顽烷琓貦頑邜宛倇唍挽晚盌埦婉惋晩梚绾脘菀晼椀琬皖畹碗綩綰輓踠鋔鍐&amp;#34;, &amp;#34;W万卍卐杤捥腕萬翫鋄薍錽贃鎫贎尩尪尫汪亡亾兦王仼彺莣蚟网忹往徃枉罔惘菵暀棢焹蛧辋網蝄誷輞瀇魍妄忘迋旺盳望朢危威烓偎逶隇隈喴媁媙愄揋揻渨煀葨葳微椳楲溦煨詴縅蝛覣嶶薇鳂&amp;#34;, &amp;#34;W癐巍鰃鰄囗为韦围帏沩违闱峗峞洈為韋桅涠唯帷惟维喡圍嵬幃湋溈爲違潍蓶鄬潙潿濰鍏闈鮠癓覹犩霺伟伪尾纬芛苇委炜玮洧娓捤浘荱诿偉偽崣梶硊萎隗骩嵔廆徫愇猥葦蒍骪骫暐椲煒瑋痿&amp;#34;, &amp;#34;W腲艉韪僞碨蜲蜼鲔寪緯蔿諉踓韑頠儰濻鍡鮪壝韙颹瀢亹斖卫未位味苿畏胃軎尉硙菋谓喂媦渭猬煟墛蔚慰熭犚磑緭蝟衛懀濊璏罻衞謂餧鮇螱褽餵魏藯轊鏏霨鳚蘶饖讆躗讏躛昷塭温殟溫瑥榲&amp;#34;, &amp;#34;W瘟豱鳁鎾饂鰛鰮文彣纹芠炆砇闻紋蚉蚊珳阌鈫雯瘒聞馼魰鳼鴍螡閺閿蟁闅鼤闦刎吻呚忟抆呡肳紊桽脗稳穏穩问妏汶莬問渂脕揾搵絻顐璺翁嗡鹟螉鎓鶲奣塕嵡滃蓊暡瞈聬瓮蕹甕罋齆挝倭涡&amp;#34;, &amp;#34;W莴唩涹渦猧萵喔窝窩蜗蝸踒我婐婑捰仴沃肟卧臥偓媉幄握渥焥硪楃腛斡瞃濣瓁龌齷乌圬弙污邬呜杇巫屋洿诬钨趶剭窏釫鄔嗚誈誣箼螐鴮鎢鰞无毋吴吾呉芜梧洖浯茣莁珸祦鹀無禑蜈蕪璑鵐&amp;#34;, &amp;#34;W鯃鼯鷡乄五午仵伍坞妩庑忤怃迕旿武玝侮俉倵捂啎娬牾珷塢摀熓碔鹉瑦舞嫵廡憮潕錻儛橆甒鵡躌兀勿务戊阢伆屼扤岉杌芴忢物矹敄误務悞悟悮粅逜晤焐婺嵍痦隖靰骛奦嵨溩雾寤熃誤鹜鋈&amp;#34;, &amp;#34;W窹霚鼿霧齀蘁騖鶩&amp;#34;, &amp;#34;X欸庍壆扱烲愖糦臰欪滀嘼錯廗諜摡給蚼規嶲鮭巂鬹咁譀迒茠滈欱郃螛嗃熇燺揈閧闀闂鬨銗謼滸芐觟懁郇狟澴還镮鐶儶譮孈葷轋掝擊彐蔇縘繫夾埉浹傢裌叚徦鰔梘筧礆見閒瞯鵁轇驕絞較湝&amp;#34;, &amp;#34;X頡觧吤繲坙巠坓顈眗鼰鼳鋗絹獧決泬勪噱姰濬愾埳堿闞晇欵歀潰搚懢壏嘮釐溓蘝蘞稴漻衖莔禰瓕賯撓譊鉨鉩煖謳嘔盤嚊恓棲諿氣欦臤慳荨羬蕁槏伣俔嗛骹燆睄綅瓊蓲鱃魼胊卻舃碏儴勷蘘&amp;#34;, &amp;#34;X纕繻灑钑鈒鰓騷雭殺榝姍釤縿莦颵姺濕宩昰笹齛咰鉥獡箾蜤燍叜宿碿潚橚孫鶽橝撢餳饀屜歒盷蓨赨緰圩韡捾夕兮忚汐西覀吸希卥昔析矽穸肸肹俙徆怸郗饻唏奚娭屖息悕晞氥浠牺狶莃唽悉&amp;#34;, &amp;#34;X惜桸欷淅渓烯焁焈琋硒菥赥釸傒惁晰晳焟犀睎稀粞翕翖舾鄎厀嵠徯溪煕皙蒠锡僖榽熄熙緆蜥豨餏嘻噏嬆嬉瘜膝餙凞樨橀歙熹熺熻窸羲螅螇錫燨犠瞦礂蟋谿豀豯貕繥雟鯑鵗觹譆醯鏭隵巇曦&amp;#34;, &amp;#34;X爔犧酅觽鼷蠵鸂觿鑴习郋席習袭觋媳椺蒵蓆嶍漝覡趘槢蝷薂隰檄謵鎴霫鳛飁騱騽襲鰼驨枲洗玺徙铣喜葈葸鈢屣漇蓰銑憘憙暿橲禧諰壐縰謑蟢蹝璽鱚矖纚躧匸卌戏屃系饩呬忥怬细係恄盻郤&amp;#34;, &amp;#34;X欯绤細釳阋塈椞舄趇隙慀滊禊綌赩隟熂犔稧戯潟澙蕮覤戱黖戲磶虩餼鬩嚱闟霼衋虾谺傄閕敮煆颬瞎蝦鰕匣侠狎俠峡柙炠狭陜峽烚狹珨祫硖笚翈舺陿溊硤遐搳暇瑕筪碬舝辖縀蕸縖赮魻轄鍜&amp;#34;, &amp;#34;X霞鎋黠騢鶷閜丅下吓圷疜夏梺廈睱諕嚇懗罅夓鏬仙仚屳先奾纤佡忺氙杴祆秈苮籼珗莶掀铦跹酰锨僊僲嘕銛鲜暹韯憸鍁繊褼韱鮮馦蹮孅廯攕譣纎鶱襳躚纖鱻伭咞闲妶弦贤咸挦涎胘娴娹婱絃&amp;#34;, &amp;#34;X舷蚿衔啣痫蛝閑鹇嫌甉銜嫺嫻憪撏澖誸賢諴輱醎癇癎藖鹹礥贒鑦鷳鷴鷼冼狝显险毨烍猃蚬険赻筅尟尠搟禒蜆跣箲獫獮藓鍌燹顕幰攇櫶蘚玁韅顯灦县岘苋现线臽限姭宪県陥哯垷娊娨峴晛涀&amp;#34;, &amp;#34;X莧陷現馅睍絤缐羡献粯腺僩僴綫誢撊線鋧憲橌縣錎餡豏瀗臔獻糮鏾霰鼸乡芗相香郷厢啌鄉鄊廂湘缃葙鄕楿薌箱緗膷襄忀骧麘欀瓖镶鱜鑲驤瓨佭详庠栙祥絴翔跭享亯响蚃饷晑飨想銄餉鲞嚮&amp;#34;, &amp;#34;X蠁鯗響饗饟鱶向姠巷项珦象缿萫項像勨嶑曏橡襐蟓鐌鱌灱灲呺枭侾削哓枵骁宯宵庨恷消绡虓逍鸮啋婋梟焇猇萧痚痟硝硣窙翛萷销揱綃嘐歊潇箫踃嘵憢撨獢銷霄彇膮蕭魈鴞穘簘藃蟂蟏謞鴵&amp;#34;, &amp;#34;X嚣瀟簫蟰髇嚻囂櫹髐鷍蠨驍毊虈洨郩崤淆訤誵小晓暁筱筿皛曉篠謏皢孝肖効咲恔俲哮效校涍笑啸傚敩滧詨嘋嘨誟嘯歗熽斅斆些楔歇蝎蠍劦协旪邪協胁垥奊恊拹挾脅脇脋衺偕斜谐猲絜翓嗋&amp;#34;, &amp;#34;X愶携瑎綊熁膎勰撷擕緳缬蝢鞋諧燲擷鞵襭攜纈讗龤写冩寫藛伳灺泄泻祄绁缷卸炧炨卨娎屑屓偰徢械焎禼亵媟屟揳渫絬谢僁塮榍榭褉噧屧暬韰嶰廨懈澥獬糏薢薤邂燮褻謝夑瀉瀣爕蟹蠏齘齥&amp;#34;, &amp;#34;X齂躠屭躞心邤妡忻芯辛昕杺欣盺俽惞鈊锌新歆廞噷噺嬜薪馨鑫馫枔鬵鐔伈潃阠伩囟孞炘信軐脪衅訫焮馸舋顖釁兴狌星垶骍惺猩煋瑆腥蛵觪箵篂興謃曐觲騂皨刑邢形陉侀郉哘型洐钘陘娙硎&amp;#34;, &amp;#34;X裄铏鈃鉶銒鋞睲醒擤杏姓幸性荇倖莕婞悻涬塂緈嬹臖凶兄兇匈芎讻忷汹哅恟洶胷胸訩詾雄熊诇詗夐敻休俢修咻庥烋烌羞脙鸺臹貅馐樇銝髤髹鎀鮴鵂饈鏅飍苬朽綇滫糔秀岫珛绣袖琇锈溴綉&amp;#34;, &amp;#34;X璓裦螑繍繡鏥鏽齅戌旴疞盱欨胥须訏顼虗虚谞媭幁揟欻虛須楈窢頊嘘稰需魆噓墟嬃歔縃蕦蝑歘諝譃魖驉鑐鬚俆徐蒣许呴姁诩冔栩珝偦許湑暊詡鄦糈醑盨旭伵序汿侐卹沀叙恤昫洫垿欰殈烅&amp;#34;, &amp;#34;X珬勖勗敍敘烼绪续酗喣壻婿朂溆絮訹嗅慉煦続蓄賉槒漵潊盢瞁緒聟銊稸緖瞲藚續蓿吅轩昍咺宣晅軒梋谖喧塇媗愃愋揎萱萲暄煊瑄蓒睻儇禤箮翧蝖嬛蕿諠諼鍹駽矎翾藼蘐蠉譞鰚讂玄玹痃悬&amp;#34;, &amp;#34;X旋琁蜁嫙漩暶璇檈璿懸选烜暅選癣癬怰泫昡炫绚眩袨铉琄眴衒渲絢楦鉉碹蔙镟鞙颴縼繏鏇贙疶蒆靴薛鞾穴斈乴坹学岤峃茓泶袕鸴踅學嶨澩燢觷雤鷽雪樰膤艝轌鳕鱈血吷怴泧狘疦桖烕谑趐&amp;#34;, &amp;#34;X謔瀥坃勋埙焄勛塤熏窨蔒勲勳薫駨嚑壎獯薰曛燻臐矄蘍壦爋纁醺寻巡旬驯杊询峋恂洵浔紃荀栒桪毥珣偱尋循揗詢馴鄩鲟噚攳樳燂燅燖璕襑蟳鱏鱘灥卂训讯伨汛迅侚徇狥迿逊殉訊訓訙奞巽&amp;#34;, &amp;#34;X殾遜愻賐噀蕈顨鑂吁&amp;#34;, &amp;#34;Y叆賹礙譺靉菴媕葊痷闇鵪鶕晻洝媼澚墺驁頨瑒耛拸呾訑婸潒扚昳屵姶堊搤閼煾妋鳱輵夃焸蠱溎裷緷蟈淊嚛欥瓛輐喛揘韹熀袆煇褘蚘噦矆拁玪豜豣將侥烄僥伒莖俓泂揂圧僪貗飬妜焆鐍炏顑&amp;#34;, &amp;#34;Y丂髺樂貍櫟躒輅擽嫚玅桙獶輗掜孴儗肀喦噛槷嚙钀汼齵堷踦锜錡裿綺鉛膁羗撽赺欽汓翑蝺輑橪蕘嬈嵤銳鋭挻烻剡虵縄繩鱦釶鉇箷戺謚釋哾說説爍鑠梀筍鉈珆旲錟湯匋鴺趯恌銕桯筩婾媮殕&amp;#34;, &amp;#34;Y悇蛻涒扡挩捝狏迱詑彵啘乛涴妧尣燰琟維厃痏薳叞榅辒輼轀勜臒汙汚烏歍吳郚娪焬熈誒歖潝疨磍嬐薟唌湺衘崄險嶮硍羨麲詳峫鐷洩紲絏緤訢脩褎褏銹獝藇鱮楥辥廵潯丫压呀庘押鸦桠鸭孲&amp;#34;, &amp;#34;Y铔椏鴉錏鴨壓鵶鐚牙伢岈芽厓枒琊笌蚜堐崕崖涯猚瑘睚衙漄齖厊庌哑唖啞痖雅瘂蕥劜圠亚穵襾讶亜犽迓亞玡垭娅挜砑俹氩埡婭掗訝揠氬猰聐圔稏窫齾咽恹剦烟珚胭偣崦淹焉菸阉湮腌傿煙&amp;#34;, &amp;#34;Y鄢嫣漹嶖樮醃閹嬮篶懕臙黫讠円延闫严妍芫言訁岩昖沿炎郔姸娫狿研莚娮盐琂硏訮閆阎嵒嵓筵綖蜒塩揅楌詽碞蔅颜虤閻厳檐顏顔嚴壛巌簷櫩麙壧孍巖巗巚欕礹鹽麣夵抁沇乵兖奄俨兗匽弇&amp;#34;, &amp;#34;Y衍偃厣掩眼萒郾酓嵃愝扊揜棪渰渷琰遃隒椼硽罨裺演褗戭蝘魇噞躽縯檿黡厴甗鰋鶠黤齞龑儼黬黭顩鼴巘曮魘鼹齴黶厌妟觃牪姲彥彦砚唁宴晏艳覎验偐掞焔谚隁喭堰敥焰焱猒硯葕雁椻滟鳫&amp;#34;, &amp;#34;Y厭墕暥熖酽嬊谳餍鴈燄燕諺赝鬳曕鴳酀騐験嚥嬿艶贋軅爓醶騴鷃灔贗觾讌醼饜驗鷰艷灎釅驠灧讞豓豔灩央咉姎抰泱殃胦眏秧鸯鉠雵鞅鍈鴦扬羊阦阳旸杨炀佯劷氜疡钖飏垟徉昜洋羏烊珜眻&amp;#34;, &amp;#34;Y陽崵崸揚蛘敭暘楊煬禓瘍諹輰鍚鴹颺鐊鰑霷鸉卬仰佒坱奍岟养炴氧痒紻傟楧軮慃氱羪養駚懩攁瀁癢礢怏柍恙样羕詇様漾樣幺夭吆妖枖祅訞喓葽楆腰鴁邀爻尧尭肴垚姚峣轺倄烑珧窑傜堯揺&amp;#34;, &amp;#34;Y殽谣軺嗂媱徭愮搖摇猺遙遥摿暚榣瑤瑶銚飖餆嶢嶤徺磘窯窰餚繇謠謡鳐颻蘨顤鰩仸宎岆抭杳殀狕苭咬柼眑窅窈舀偠婹崾溔榚鴢闄騕齩鷕穾药要袎窔筄葯詏熎覞靿獟鹞薬鼼曜燿艞藥矅曣耀&amp;#34;, &amp;#34;Y纅鷂讑鑰倻椰暍噎潱蠮爷耶捓揶铘爺釾鋣鎁擨也吔亪冶埜野嘢漜壄业叶曳页邺夜抴亱枼洂頁晔枽烨掖液谒堨殗腋葉鄓墷楪業馌僷曄曅歋燁擛皣瞱鄴靥嶪嶫澲謁餣嚈擫曗瞸鍱擪爗礏鎑饁鵺&amp;#34;, &amp;#34;Y靨驜鸈膶岃一弌辷衤伊衣医吚壱依祎咿洢猗畩郼铱壹揖欹蛜禕嫛漪稦銥嬄噫夁瑿鹥繄檹毉醫黟譩鷖黳乁仪匜圯夷冝宐沂诒侇宜怡沶狋衪迤饴咦姨峓弬恞柂瓵荑贻迻宧巸扅栘桋眙胰袘酏痍&amp;#34;, &amp;#34;Y移萓媐椬羠蛦詒貽遗暆椸誃跠頉颐飴疑儀熪遺嶬彛彜螔頤頥寲嶷簃顊鮧彝彞謻鏔籎觺讉鸃乙已以迆钇佁攺矣苡苢庡舣蚁釔倚扆笖逘偯崺旑椅鈘鉯鳦旖輢敼螘檥礒艤蟻顗轙齮乂义亿弋刈忆&amp;#34;, &amp;#34;Y艺仡匇肊议阣亦伇屹异忔芅伿佚劮呓坄役抑曵杙耴苅译邑佾呭呹峄怈怿易枍泆炈绎诣驿俋奕帟帠弈枻浂玴疫羿衵轶唈垼悒挹栧欭浥浳益袣谊貤陭勚埶埸悘悥殹異羛翊翌萟訲訳豙豛逸釴隿&amp;#34;, &amp;#34;Y幆敡晹棭殔湙焲蛡詍跇鈠骮亄兿意溢獈痬竩缢義肄裔裛詣勩嫕廙榏潩瘗膉蓺蜴靾駅億撎槸毅熠熤熼瘞誼镒鹝鹢黓劓圛墿嬑嬟嶧憶懌曀殪澺燚瘱瞖穓縊艗薏螠褹寱斁曎檍歝燡燱翳翼臆貖鮨&amp;#34;, &amp;#34;Y癔藙藝贀鎰镱繶繹豷霬鯣鶂鶃鶍瀷蘙譯議醳醷饐囈鐿鷁鷊懿襼驛鷧虉鷾讛齸乚囙因阥阴侌垔姻洇茵荫音骃栶殷氤陰凐秵裀铟陻隂喑堙婣愔筃絪歅溵禋蒑蔭慇瘖銦磤緸鞇諲霒駰噾濦闉霠韾&amp;#34;, &amp;#34;Y冘吟犾苂垠泿圁峾烎狺珢粌荶訔唫婬寅崟崯淫訡银鈝龂滛碒鄞夤蔩訚誾銀龈噖殥璌嚚檭蟫霪齗齦鷣尹引吲饮蚓隐淾釿鈏飲隠靷飮朄趛檃瘾隱嶾濥螾蘟櫽癮讔印茚洕胤垽湚猌廕酳慭癊憖憗&amp;#34;, &amp;#34;Y鮣懚檼应応英偀桜珱莺啨婴媖愥渶绬朠煐瑛嫈碤锳嘤撄滎甇緓缨罂蝧賏樱璎噟罃褮霙鴬鹦嬰應膺韺甖鎣鹰鶧嚶孆孾攖瀴罌蘡櫻瓔礯譻鶯鑍纓蠳鷪軈鷹鸎鸚盁迎茔盈荥荧莹萤营萦蛍営溁溋&amp;#34;, &amp;#34;Y萾僌塋楹滢蓥潆熒蝇瑩蝿嬴營縈螢濙濚濴藀覮謍赢巆攍攚瀛瀠瀯蠅櫿灐籝灜贏籯矨郢梬颍颕颖摬影潁瘿穎頴巊廮鐛癭映暎硬媵膡鞕瀅譍哟唷喲佣拥痈邕庸傭嗈鄘雍墉嫞慵滽槦牅噰壅擁澭&amp;#34;, &amp;#34;Y郺镛臃癕雝鏞鳙廱灉饔鱅鷛癰喁颙顒鰫永甬咏怺泳俑勇勈栐埇悀柡涌恿傛惥愑湧硧詠塎嵱彮愹蛹慂踊禜鲬踴鯒用苚砽醟优忧攸呦怮泑幽悠麀滺憂優鄾嚘懮瀀櫌纋耰尢尤由沋犹邮怞油肬怣&amp;#34;, &amp;#34;Y斿柚疣峳浟秞莜莤莸逌郵铀偤蚰訧逰游猶遊鱿楢猷鲉輏駀蕕蝣魷輶鮋櫾邎友有丣卣苃酉羑庮羐莠梄聈脜铕湵蒏禉蜏銪槱牖牗黝又右幼佑侑孧狖糿哊囿姷宥峟牰祐诱迶唀梎蚴亴貁釉酭誘鼬&amp;#34;, &amp;#34;Y扜纡迂迃穻陓紆虶唹淤盓渝瘀箊于亐予邘伃余妤扵杅欤玗玙於盂臾衧鱼俞兪禺竽舁茰荢娛娯娱狳谀酑馀渔萸釪隃隅雩魚堣堬崳嵎嵛愉揄楰湡畬畭硢腴逾骬愚楡榆歈牏瑜艅虞觎漁睮窬舆褕&amp;#34;, &amp;#34;Y歶羭蕍蝓諛雓餘魣嬩懙澞覦踰歟璵螸輿鍝礖謣髃鮽旟籅騟鯲鰅鷠鸆与伛宇屿羽雨俁俣挧禹语圄峿祤偊匬圉庾敔鄅萭萮铻傴寙斞楀瑀瘐與語窳鋙龉噳嶼貐斔麌蘌齬玉驭聿芋芌妪忬饫育郁彧&amp;#34;, &amp;#34;Y昱狱秗茟俼峪栯浴砡钰预喐域堉悆惐欲淢淯袬谕逳阈喅喩喻媀寓庽御棛棜棫焴琙矞裕遇飫馭鹆愈滪煜稢罭蒮蓣誉鈺預嫗嶎戫毓獄瘉緎蜟蜮輍銉隩噊慾稶蓹薁豫遹鋊鳿澦燏燠蕷諭錥閾鴥鴧&amp;#34;, &amp;#34;Y鴪儥礇禦魊鹬癒礜穥篽繘醧鵒櫲饇蘛譽轝鐭霱欎驈鬻籞鱊鷸鸒欝軉鬰鬱灪籲爩囦鸢剈冤弲悁眢鸳寃渁渆渊渕惌淵葾棩蒬蜎鹓箢鳶蜵駌鋺鴛嬽鵷灁鼘鼝元贠邧员园沅杬垣爰貟原員圆笎蚖袁&amp;#34;, &amp;#34;Y厡酛圎援湲猨缘鈨鼋園圓塬媴嫄源溒猿獂蒝榞榬辕緣縁蝝蝯魭橼羱薗螈謜轅黿鎱櫞邍騵鶢鶰厵远盶逺遠夗肙妴苑怨院垸衏傆媛掾瑗禐愿裫褑褤噮願曰曱约約箹矱彟彠月戉刖岄抈礿岳枂玥&amp;#34;, &amp;#34;Y恱钥悅悦蚎蚏軏钺阅捳跀跃粤越鈅粵鉞閱閲嬳樾篗嶽龠籆瀹蘥黦爚禴躍籥鸑籰龥鸙蒀煴蒕熅奫蝹赟頵馧贇云勻匀伝呍囩妘抣沄纭芸昀畇眃秐郧涢紜耘耺鄖雲愪氲溳筼蒷氳熉澐蕓鋆橒篔縜&amp;#34;, &amp;#34;Y繧允阭夽抎狁玧陨荺殒喗鈗隕殞褞馻磒霣齫齳孕运枟郓恽晕鄆酝傊惲愠缊運慍暈腪韫韵熨緼蕰蕴縕薀賱醖醞餫藴韗韞蘊韻這&amp;#34;, &amp;#34;Z敱捗囃謲匨蔵冊側厠廁嶒扠挿揷蹅茝僝欃倀长仧長镸鼌鼂謿謓迧陳鈂趂朾脀憕徎胵絺泜歭遟遲迣徸漴褈緟蝩蟲紬搊椆詶薵偢芻鉏蕏傳鶨倕埀箠鎚純湻辶腏趠齱骴薋泚跐從蓯樅熜緫潀潈潨&amp;#34;, &amp;#34;Z酢噈欑穳篹嶉槯伜倅紣綷顇墫拵踆睉蔖剳蹛黱酖亶翢篴拞牴觝啇摕蝃踶點鳭調藋喋臷鰈眰鼑枓剢耑磓隊腞夛仛喥柮樲胕阝贛戇滜睪牫贑嫢啈楖嚌璾鯽穧椾碊鳽餰栫袸濺瀳鏩繳擳竧鳩砠蓻&amp;#34;, &amp;#34;Z齟怚跙脧雋捔逫嵁沴酈譧驡狵沵摨聶囁釽亝祇蚔齊磩鈆謙綪繰菬埥軽鯖伹岨恮跧甽繅洓篸箑摂攝鉐實識亊鉃適銴檡薥藷鸀尌虒睟簨駘菭襢犆媞薙嚔鐟塡怗聑跕鉄鉵獞穜潳剬剸塼摶漙篿尵&amp;#34;, &amp;#34;Z旽啍忳飩杔馲驝陁萚蘀聉顡醀錗撾扸杫咥枮鮝鞢鋅鮏鯹鎐蓔捙偞擖杝妷秇栺軼乑斦浧銿鈾圫汋帀匝沞咂拶沯桚紥紮鉔魳臜臢杂砸韴雑磼襍雜囐雥災灾甾哉栽烖菑渽溨睵賳宰载崽載再在扗&amp;#34;, &amp;#34;Z洅傤酨儎縡兂糌簪簮鐕咱偺喒昝寁撍儧攒儹攢趱趲暂暫賛赞錾鄼濽蹔酂瓉贊鏨瓒酇囋灒讃瓚禶襸讚饡牂羘赃賍臧賘贓髒贜驵駔奘弉脏塟葬銺臓臟傮遭糟蹧醩凿鑿早枣栆蚤棗璅澡璪薻藻灶&amp;#34;, &amp;#34;Z皁皂唕唣造梍喿慥煰艁噪簉燥竃譟趮躁竈啫伬则択沢择泎泽责迮則唶啧帻笮舴責溭矠嘖嫧幘箦蔶樍歵諎赜擇澤皟瞔簀耫礋襗謮賾蠌齚齰鸅仄夨庂汄昃昗捑崱稄贼賊鲗蠈鰂鱡怎谮譖譛囎曽&amp;#34;, &amp;#34;Z増鄫增憎缯橧熷璔矰磳罾繒譄鱛锃鋥甑赠贈吒迊咋抯挓柤哳偧喳揸渣溠楂劄皶箚樝觰皻譇齄齇扎札甴轧軋闸蚻铡煠牐閘霅鍘譗厏苲眨砟搩鲊鲝踷鮓鮺乍灹诈咤奓柵炸宱痄蚱詐搾摣榨醡夈&amp;#34;, &amp;#34;Z粂捚斋斎摘榸齋宅翟窄鉙债砦債寨瘵沾毡旃栴粘蛅飦惉詀趈詹閚谵噡嶦薝邅霑氈氊瞻鹯旜譫饘鳣驙魙鱣鸇讝拃斩飐展盏崭斬琖搌盞嶃嶄榐辗颭嫸醆橏蹍輾皽黵占佔战栈桟站偡绽菚棧湛戦&amp;#34;, &amp;#34;Z綻嶘輚戰虥虦覱轏蘸驏张弡張章傽鄣嫜彰慞漳獐粻蔁遧暲樟璋餦蟑鏱騿鱆麞仉涨涱掌漲幥礃鞝鐣丈仗扙帐杖胀账粀帳脹痮障墇嶂幛賬瘬瘴瞕佋钊妱巶招昭炤盄釗啁鉊駋窼鍣爫找沼瑵召兆&amp;#34;, &amp;#34;Z诏枛垗狣赵笊肁旐棹罀詔照罩箌肇肈趙曌燳鮡櫂瞾羄蜇嫬遮厇折歽矺砓籷虴哲埑粍袩啠悊晢晣辄喆棏蛰詟谪摺輒樀磔輙銸辙蟄嚞謫謺鮿轍讁襵讋者锗赭褶鍺这柘浙淛嗻蔗樜鹧蟅鷓贞针侦&amp;#34;, &amp;#34;Z浈珍珎貞帪栕桢眞真砧祯針偵敒桭酙寊湞葴遉搸斟楨獉甄禎蒖蓁鉁靕榛槇殝瑧碪禛潧箴樼澵臻薽錱轃鍖鍼籈鱵屒诊抮枕姫弫昣胗轸畛疹眕袗紾聄萙裖覙診軫嫃缜稹駗縝縥辴鬒黰圳阵纼侲&amp;#34;, &amp;#34;Z挋陣鸩振朕栚紖眹赈塦揕絼蜄敶誫賑鋴镇震鴆鎭鎮黮凧争佂姃征怔爭峥挣炡狰烝眐钲埩崝崢掙猙睁聇铮媜揁筝徰睜蒸鉦徴箏徵踭篜錚鬇癥氶抍糽拯掟塣晸愸撜整正证诤郑帧政症幀証鄭諍&amp;#34;, &amp;#34;Z鴊證之支卮汁芝吱巵汥枝知织肢徔栀祗秓秖胑胝衹衼倁疷祬秪脂隻梔戠椥臸搘禔綕榰蜘馶鳷謢鴲織蘵鼅禵执侄坧直姪値值聀釞埴執职植殖禃絷跖瓡墌摭馽嬂慹漐踯樴膱縶職蟙蹠蹢軄躑止&amp;#34;, &amp;#34;Z只凪劧旨阯址坁帋扺汦沚纸芷抧祉茋咫恉指枳洔砋轵淽疻紙訨趾軹黹酯藢襧阤至芖志忮扻豸制厔垁帙帜治炙质郅俧峙庢庤挃柣栉洷祑陟娡徏挚晊桎狾秩致袟贽轾乿偫徝掷梽猘畤痔秲秷窒&amp;#34;, &amp;#34;Z紩翐袠觗貭铚鸷傂崻彘智滞痣蛭骘寘廌搱滍稙稚筫置跱輊锧雉墆槜滯潌疐瘈製覟誌銍幟憄摯潪熫稺膣觯質踬鋕旘瀄緻隲駤鴙儨劕懥擲擿櫛穉螲懫贄櫍瓆觶騭鯯礩豑騺驇躓鷙鑕豒中伀汷刣&amp;#34;, &amp;#34;Z妐彸迚忠泈炂终柊盅衳钟舯衷終鈡幒蔠锺螤鴤螽鍾鼨蹱鐘籦肿种冢喠尰塚歱煄腫瘇種踵仲众妕狆祌茽衶重蚛偅眾堹媑筗衆諥州舟诌侜周洀洲炿诪烐珘辀郮婤徟淍矪週鸼喌粥赒輈銂賙輖霌&amp;#34;, &amp;#34;Z駲嚋盩謅鵃騆譸妯轴軸碡肘帚疛菷晭睭箒鯞纣伷呪咒宙绉冑咮昼紂胄荮晝皱酎粙葤詋甃僽皺駎噣縐骤籀籕籒驟朱劯侏诛邾洙茱株珠诸猪硃袾铢絑蛛誅跦槠潴蝫銖橥諸豬駯鮢鴸瀦藸櫧櫫鼄&amp;#34;, &amp;#34;Z鯺蠩竹泏竺炢笁茿烛窋逐笜舳瘃蓫燭蠋躅鱁劚孎灟斸曯欘爥蠾钃主宔拄砫罜陼渚煑煮詝嘱濐麈瞩屬囑矚伫佇住助纻芧苎坾杼注苧贮迬驻壴柱柷殶炷祝疰眝祩竚莇秼紵紸羜著蛀嵀筑註貯跓&amp;#34;, &amp;#34;Z軴铸筯鉒飳馵墸箸翥樦鋳駐築篫霔麆鑄抓檛膼簻髽爪拽跩专叀専砖專鄟嫥瑼甎膞颛磚諯蟤顓鱄转孨転竱轉灷啭堟蒃瑑僎赚撰篆馔縳襈賺譔饌囀籑妆庄妝庒荘娤桩莊湷粧装裝樁糚丬壮壯状&amp;#34;, &amp;#34;Z狀壵梉焋幢撞戅隹追骓椎锥錐騅鵻沝坠笍娷缀惴甀缒畷硾膇墜綴赘縋諈醊錣餟礈贅轛鑆宒迍肫窀谆諄衠准埻凖準綧訰稕卓拙炪倬捉桌棁涿棳琸窧槕穛穱蠿圴彴犳灼叕妰茁斫浊丵浞烵诼酌&amp;#34;, &amp;#34;Z啄啅娺梲着斮晫椓琢斱硺窡罬撯擆斲禚劅諁諑鋜濁篧擢斀斵濯櫡謶镯鐯鵫灂蠗鐲籗鷟籱仔孖孜茊兹咨姕姿茲栥玆紎赀资崰淄秶缁谘赼嗞孳嵫椔湽滋葘辎鄑孶禌觜貲資趑锱稵緇鈭镃龇輜鼒&amp;#34;, &amp;#34;Z澬諮趦輺錙髭鲻鍿鎡頾頿鯔鶅齍鰦齜籽子吇姉姊杍矷秄胏呰秭耔虸笫梓釨啙紫滓訾訿榟橴字自芓茡倳剚恣牸渍眥眦胔胾漬唨宗倧综骔堫嵏嵕惾棕猣腙葼朡椶嵸稯綜緃熧緵翪艐蝬踨踪磫豵&amp;#34;, &amp;#34;Z蹤騌鬃騣鬉鬷鯮鯼鑁总偬捴惣愡揔搃傯蓗摠総縂燪總鍯鏓纵昮疭倊猔碂粽糉瘲縦錝縱邹驺诹郰陬掫菆棷棸鄒箃緅諏鄹鲰鯫黀騶齺赱走鯐奏揍媰租菹葅蒩卆足卒哫崒崪族傶稡箤踤踿镞鏃诅&amp;#34;, &amp;#34;Z阻组俎爼珇祖組詛靻鎺謯劗躜鑚躦鑽繤缵纂纉籫纘钻揝攥厜朘嗺樶蟕纗嶊嘴噿濢璻枠栬絊酔晬最祽罪辠酻蕞醉嶵檇鋷錊檌穝欈尊嶟遵樽繜罇鶎鐏鳟鱒鷷僔噂撙譐捘銌昨秨莋捽椊葃稓筰鈼&amp;#34;, &amp;#34;Z左佐繓作坐阼岝岞怍侳柞祚胙唑座袏做葄蓙飵糳咗&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;需要注意的是C#和VB.Net在处理Unicode编码时有些区别，VB.Net使用&lt;/p&gt;</description></item><item><title>Windows 下使用Git管理Github项目</title><link>https://fwhyy.com/2012/02/use-git-manage-github-project-on-windows/</link><pubDate>Mon, 06 Feb 2012 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2012/02/use-git-manage-github-project-on-windows/</guid><description>&lt;h2 id="git"&gt;Git&lt;/h2&gt;
&lt;p&gt;Git是一个开源的分布式版本控制系统，用以有效、高速的处理从很小到非常大的项目版本管理。最初由Linus Torvalds编写，用作Linux内核代码的管理。在推出后，Git在其它项目中也取得了很大成功，尤其是在Ruby社区中。&lt;/p&gt;
&lt;h2 id="github"&gt;Github&lt;/h2&gt;
&lt;p&gt;Github是一个面向开源及私有软件项目的托管平台，因为只支持Git作为唯一的版本库格式进行托管，故名GitHub。GitHub可以托管各种git库，并提供一个web界面，但与其它像 &lt;a href="http://www.oschina.net/p/sourceforge"&gt;SourceForge&lt;/a&gt;或&lt;a href="http://www.oschina.net/p/googlecode"&gt;Google Code&lt;/a&gt;这样的服务不同，GitHub的独特卖点在于从另外一个项目进行分支的简易性。为一个项目贡献代码非常简单：首先点击项目站点的“fork”的按 钮，然后将代码检出并将修改加入到刚才分出的代码库中，最后通过内建的“pull request”机制向项目负责人申请代码合并。&lt;/p&gt;
&lt;p&gt;上面的介绍摘自oschina.net ,下面就开始介绍在windows下怎样用Git管理Github的项目&lt;/p&gt;
&lt;p&gt;1 在&lt;a href="https://github.com/"&gt;Github&lt;/a&gt;上创建账号，这个很简单就不再赘述。&lt;/p&gt;
&lt;p&gt;2 下载安装Git&lt;/p&gt;
&lt;p&gt;下载地址：&lt;a href="http://code.google.com/p/msysgit/downloads/list"&gt;http://code.google.com/p/msysgit/downloads/list&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;安装很简单，一路Next就可以了。&lt;/p&gt;
&lt;p&gt;3 登陆GitHbu后创建一个新的仓库（New repository），命名为HelloWorld，创建成功后如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290716529.webp" alt="2012-02-06_220858" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;4 上面只是创建了一个空的代码仓库，下面就在本地创建一个HelloWorld的项目，并将其推送到Github中。创建D:\GitProject\HelloWorld的目录结构。&lt;/p&gt;
&lt;p&gt;5 打开Git的命令行Git base，输入如下命令来提供身份标示，主要是用户名和邮箱：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290716745.webp" alt="2012-02-06_221545" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;6 同过cd命令进入到刚才创建的HelloWorld目录中，然后使用git init来初始化当前目录，该目录中会生成一个.git的隐藏目录:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290717696.webp" alt="2012-02-06_222338" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;7 在D:\GitProject\HelloWorld目录中添加一个readme.txt文件，文件中写入“my first hello world project!”，然后用git add 命令以及git commit命令将其添加到库中。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290717852.webp" alt="2012-02-06_223250" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;8 下面就是最关键的步骤了，将本地的代码库提交到Github中，首先要使用命令来创建密匙，该密匙会在Github的设置中用到。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290717747.webp" alt="2012-02-06_223734" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;9 我系统是windows server 2008R2 ，生成的密匙在C:\Users\Administrator.ssh目录下，打开id_rsa.pub文件，复制里面所有内容。&lt;/p&gt;
&lt;p&gt;10 在Github中点击“Account Settings”进入到设置界面，选择“SSH Public Keys”,然后点击”add another public key“&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290717142.webp" alt="2012-02-06_224654" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201290717518.webp" alt="2012-02-06_224737" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;11 将刚才复制的密匙内容粘贴到对应的框中。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290718778.webp" alt="2012-02-06_225104" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;12 用命令来检验下是否设置成功&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290718000.webp" alt="2012-02-06_230129" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;13 现在一切就绪，在Git base 中使用命令就可以将本地代码推送到Github&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290718820.webp" alt="2012-02-06_230614" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;14 现在刷新下在Github中的项目页面，如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290718295.webp" alt="2012-02-06_230744" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="学习资料"&gt;学习资料&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.worldhello.net/gotgithub/index.html"&gt;http://www.worldhello.net/gotgithub/index.html&lt;/a&gt;
&lt;a href="http://www.cnblogs.com/wojilu/"&gt;http://www.cnblogs.com/wojilu/&lt;/a&gt;
&lt;a href="http://download.csdn.net/detail/oec2003/4048166"&gt;Pro Git中文版下载&lt;/a&gt;
&lt;a href="http://www.slideshare.net/josephj/git-the-social-coding-system"&gt;一个还不错的Git ppt介绍&lt;/a&gt;&lt;/p&gt;</description></item><item><title>MongoDB(4)–MongoDB服务的启动</title><link>https://fwhyy.com/2011/11/mongo-service-startup/</link><pubDate>Thu, 03 Nov 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/11/mongo-service-startup/</guid><description>&lt;h2 id="原始方式"&gt;原始方式&lt;/h2&gt;
&lt;p&gt;只有启动了MongoDB的服务，才能使用MongoDB的功能，通常情况下会开一个命令窗口，输入下面的命令来启动服务：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300726402.webp" alt="2011-10-14_222912" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="配置文件方式"&gt;配置文件方式&lt;/h2&gt;
&lt;p&gt;如果不想每次启动的时候都在命令行中输入很多繁琐的参数，可以把参数信息保存在配置文件中。创建一个名为mongodb.cnf的配置文件，和那些小工具放在同一个目录中，文件的内容如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;dbpath=&amp;#34;d:\database\mongodb\data&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;然后在命令窗口输入下面命令就可以启动服务&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300726049.webp" alt="2011-10-14_225624" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;看似和上面的方法差不多，还是需要指定配置文件，但如果参数不止-dbpath的时候，就可以将参数都写在配置文件中，在命令行调用的时候就会显得方便很多。&lt;/p&gt;
&lt;h2 id="daemon方式"&gt;Daemon方式&lt;/h2&gt;
&lt;p&gt;上面介绍的两种方式启动服务都需要打开一个命令行窗口，窗口关闭了服务也就停止了。我们使用–fork参数可以将mongodb的服务放在后台运行，这样相对比较安全。–fork参数是和–logpath参数一起使用的&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300726756.webp" alt="2011-10-14_235943" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://fwhyy.com/2011/09/some-concepts-about-nosql-and-mongodb/"&gt;MongoDB(3)–有关NoSQL及MongoDB的一些概念&lt;/a&gt;
&lt;a href="http://fwhyy.com/2011/09/mongvue-introduction/"&gt;MongoDB(2)–MongVUE介绍&lt;/a&gt;
&lt;a href="http://fwhyy.com/2011/09/mongo-introduction-and-installation/"&gt;MongoDB(1)&amp;ndash;MongoDB介绍及安装&lt;/a&gt;&lt;/p&gt;</description></item><item><title>解决Windows Server2008 R2中IE开网页时弹出阻止框</title><link>https://fwhyy.com/2011/10/solution-for-ie-to-open-the-web-pop-up-windows-server2008-r2-block-box/</link><pubDate>Sat, 15 Oct 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/10/solution-for-ie-to-open-the-web-pop-up-windows-server2008-r2-block-box/</guid><description>&lt;p&gt;相信使用Windows Server2008的朋友都遇到过这种情况，用IE打开网站时会弹出“Internet Explorer增强安全配置正在阻止来自下列网站的此应用程序中的内容”的对话框。如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301946631.webp" alt="2011-10-14_205047-300x243" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;禁止弹出此类对话框的步骤：&lt;/p&gt;
&lt;p&gt;1 打开服务器管理器，在”安全信息“栏的右侧点击”配置IE ESC“&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301946326.webp" alt="2011-10-14_204750-300x150" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 在弹出的对话框中将”管理员“和”用户“都选择为“禁用”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301947894.webp" alt="2011-10-14_204830-300x289" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 确定后，再浏览网页那烦人的弹出框就不会再出现了。&lt;/p&gt;</description></item><item><title>MongoDB(3)–有关NoSQL及MongoDB的一些概念</title><link>https://fwhyy.com/2011/09/some-concepts-about-nosql-and-mongodb/</link><pubDate>Thu, 29 Sep 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/09/some-concepts-about-nosql-and-mongodb/</guid><description>&lt;p&gt;学习任何东西在没有理解的前提下去背熟一些概念是没有用的，就像只背会了几个概念而没有理解的开发人员去面试是经不住面试官的追问的。前面的两篇对MongoDB做了简单的介绍，能够很快上手，对MongoDB有一个感性的认识。本篇大部分内容来自MongoDB权威指南和MongoDB实战。希望在学习完整个MongoDB后能对本篇的内容有一个全新的认识。&lt;/p&gt;
&lt;h2 id="nosql简介"&gt;NoSQL简介&lt;/h2&gt;
&lt;p&gt;NoSQL，全称是”Not Only Sql”,指的是非关系型的数据库。这类数据库主要有这些特点：非关系型的、分布式的、开源的、水平可扩展的。原始的目的是为了大规模 web 应用，这场全新的数据库革命运动早期就有人提出，发展至2009 年趋势越发高涨。NoSQL 的拥护者们提 倡运用非关系型的数据存储，通常的应用如：模式自由、支持简易复制、简单的API、最终&lt;/p&gt;
&lt;p&gt;的一致性 （非ACID ）、大容量数据等。NoSQL 被我们用得最多的当数 key-value 存储，当然还 有其他的文档型的、列存储、图型数据库、xml 数据库等。相对于目前铺天盖地的关系型数 据库运用，这一概念无疑是一种全新思维的注入。&lt;/p&gt;
&lt;h2 id="nosql的优势"&gt;NoSQL的优势&lt;/h2&gt;
&lt;p&gt;同关系型数据库相比，NoSQL有下面的一些优势：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;适合对数据库高并发读写的需求。&lt;/li&gt;
&lt;li&gt;适合对海量数据的高效率存储和访问的需求。&lt;/li&gt;
&lt;li&gt;适合对数据库的高可扩展性和高可用性的需求。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;由于NoSQL的这些优势，使得NoSQL比较适合以下的一些场景的使用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对数据库事务一致性要求不高的时候，因为NoSQL不支持事务（MongoDB是不支持事务的，其他的没做研究）。&lt;/li&gt;
&lt;li&gt;对数据库的写实时性和读实时性要求不高的时候。&lt;/li&gt;
&lt;li&gt;对复杂的SQL 查询，特别是多表关联查询不多的时候。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="nosql的特点"&gt;NoSQL的特点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;它可以处理超大量的数据&lt;/li&gt;
&lt;li&gt;它运行在便宜的它运行在便宜的 PC 服务器集群上服务器集群上，意思是在数据库不够用的时候进行PC的集群扩展很方便并且成本很低。&lt;/li&gt;
&lt;li&gt;它击碎了性能瓶颈，因为使用NoSQL省去了传统的程序模型到SQL之间转换的时间，执行效率更高。&lt;/li&gt;
&lt;li&gt;它没有过多的操作，意思是去掉了很多在关系数据库中拥有而在实际又不怎么使用的功能。&lt;/li&gt;
&lt;li&gt;它的支持支持者源于社区者源于社区，所有的NoSQL产品都是开源的。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mongodb简介"&gt;MongoDB简介&lt;/h2&gt;
&lt;p&gt;MongoDB 是一个介于关系数据库和非关系数据库之间的产品，是非关系数据库当中功能最丰富，最像关系数据库的。他支持的数据结构非常松散，是类似json 的bjson 格式，简称BSON，因此可 以存储比较复杂的数据类型。MongoDB 最大的特点是他支持的查询语言非常强大，其语法有点类似于面向对象的查询语言，几乎可以实现类似关系数据库单表查询的绝大部分功能， 而且还支持对数据建立索引。它是一个面向集合的,模式自由的文档型数据库。&lt;/p&gt;
&lt;h2 id="mongodb特点"&gt;MongoDB特点&lt;/h2&gt;
&lt;h3 id="1-丰富的数据模型"&gt;1 丰富的数据模型&lt;/h3&gt;
&lt;p&gt;MongoDB是一种面向文档的数据库。在MongoDB中文档就相当于关系型数据库中的行。文档中可以包含很复杂的数据结构，这样一条记录就可以表示很复杂的层级关系。比如说文章表有一个字段是评论，在关系型数据库中我们通常会建一个评论表和文章表做关联，在MongoDB中就可以直接将评论存在一条文章记录的文档中。更符合我们的思维。&lt;/p&gt;
&lt;p&gt;MongoDB没有模式，也就是说没有表结构，文档的字段可以随时添加，不会对原来数据有任何影响，使开发变得很容易。&lt;/p&gt;
&lt;h3 id="2-容易扩展"&gt;2 容易扩展&lt;/h3&gt;
&lt;p&gt;在一些大型的网站中，数据的增长是非常惊人的。在面临数据增长机器不够用的时候通常有两种做法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;购买更高配置的机器，会花费很大，而且达到物理极限后花钱也买不到更高配置的了。&lt;/li&gt;
&lt;li&gt;进行扩展，将数据分散到多个机器上，这种在操作上会显得复杂点。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MongoDB的设计就考虑到了扩展的问题，它所采用的面向文档的数据模型使得可以自动在多台服务器中切割数据。还可以平衡群集的数据和负载，自动进行文档重排。&lt;/p&gt;
&lt;h3 id="3-丰富的功能"&gt;3 丰富的功能&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;索引：MongoDB支持通用辅助索引，可以进行多种快速查询。&lt;/li&gt;
&lt;li&gt;存储Javascript：不必再使用存储过程了，可以直接在服务器端存取Javascript的函数和值。&lt;/li&gt;
&lt;li&gt;聚合：MongoDB支持MapReduce和其他聚合工具。&lt;/li&gt;
&lt;li&gt;固定集合：集合的大小是有上限的，这对于日志一类的数据很有用。&lt;/li&gt;
&lt;li&gt;存储文件：MongoDB支持用一种容易使用的协议（GridFS）来存储大型文件。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="4-更快的速度"&gt;4 更快的速度&lt;/h3&gt;
&lt;p&gt;高性能是MongoDB的目标，为了提高性能，就必须进行很多精简的设计，相比关系型数据库少了很多功能，但仍然保持着关系型数据库的众多的特性。一些精简设计表现在：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用MongoDB传输协议作为与服务器交互的主要方式，将比较HTTP、Reset等可以节省不少开销。&lt;/li&gt;
&lt;li&gt;对文档进行动态填充，预分配数据文件，用空间换取时间，而且空间对于现在来说已不是问题。&lt;/li&gt;
&lt;li&gt;默认的存储引擎使用内存映射文件，将内存管理工作交给OS去处理。&lt;/li&gt;
&lt;li&gt;动态查询优化器会记住执行查询最高效的方式。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="5-简单的管理"&gt;5 简单的管理&lt;/h3&gt;
&lt;p&gt;MongoDB尽量让服务器自治来简化数据库的管理。除了启动数据库服务器之外，几乎没有什么管理操作了。如果主服务器挂掉了，MongoDB会自动切换到备份服务器上，并将备份服务器提升为活跃服务器。在分布式的环境下，群集只需要知道有新的节点就会自动集成和配置新的节点。&lt;/p&gt;
&lt;h2 id="mongodb适用场景"&gt;MongoDB适用场景&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;网站数据：MongoDB非常适合实时的插入，更新与查询，并具备网站实时数据存储所 需的复制及高度伸缩性 。&lt;/li&gt;
&lt;li&gt;缓存：由于性能很高，MongoDB 也适合作为信息基础设施的缓存层。在系统重启之后， 由MongoDB 搭建的持久化缓存层可以避免下层的数据源过载 。&lt;/li&gt;
&lt;li&gt;大尺寸，低价值的数据：使用传统的关系型数据库存储一些数据时可能会比较昂贵，在此之前，很多时候程序员往往会选择传统的文件进行存储 。&lt;/li&gt;
&lt;li&gt;高伸缩性的场景：MongoDB 非常适合由数十或数百台服务器组成的数据库。MongoDB的路线图中已经包含对MapReduce 引擎的内置支持 。&lt;/li&gt;
&lt;li&gt;用于对象及JSON 数据的存储：MongoDB 的BSON 数据格式非常适合文档化格式的存储及查询 。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>MongoDB(2)–MongVUE介绍</title><link>https://fwhyy.com/2011/09/mongvue-introduction/</link><pubDate>Tue, 20 Sep 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/09/mongvue-introduction/</guid><description>&lt;p&gt;对于数据库来说有一款功能强大的管理工具将会大大的提高我们的工作效率。对于MongoDB来说MongoVUE就是这样一款工具，MongoVUE在1.0版以后就开始收费了，所以我现在用的还是0.9.7.2版。对于初学来时已经够用了。&lt;/p&gt;
&lt;p&gt;安装运行后的界面如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300728711.webp" alt="2011-09-12_150826-300x199" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击Connect来连接MongoDB数据库&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300728115.webp" alt="2011-09-12_150941-300x225" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;填写好Name 和Server后点击Save，Name随便给取个名字就型，Server为服务器的地址，本机即127.0.0.1，Port默认为27017，可以根据实际情况进行设置。保存后在Connect界面就多了一个MyMongoDB的数据库连接，点击Connect即可连接到数据库。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300728285.webp" alt="2011-09-12_200130" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;除了系统默认的admin和local数据库外，在上一篇中创建的Blogs数据库也在列表中。并且在Blogs库中已经存在一个Collection，就是在上篇中insert的一条数据。双击Posts，在右边的窗口中会展示数据，分为三个Tab页来进行展示，分别是树状结构、表结构（类似关系型数据库的展示方式）和文本结构（BSON）。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300728453.webp" alt="2011-09-12_200949-300x203" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;本篇就介绍到这里，更多的功能和用法还是让读者自己下载试用吧。&lt;/p&gt;
&lt;p&gt;MongoDB0.9.7.2 版下载：&lt;a href="http://download.csdn.net/detail/oec2003/3595146"&gt;http://download.csdn.net/detail/oec2003/3595146&lt;/a&gt;&lt;/p&gt;</description></item><item><title>MongoDB(1)--MongoDB介绍及安装</title><link>https://fwhyy.com/2011/09/mongo-introduction-and-installation/</link><pubDate>Tue, 13 Sep 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/09/mongo-introduction-and-installation/</guid><description>&lt;p&gt;NoSql已经流行好一阵子了，我似乎接触的有点晚了。NoSql的产品有很多，MongoDB只是其中一种，之所以选在学习MongoDB是因为最早知道的就是她，也比较具有代表性。&lt;/p&gt;
&lt;p&gt;MongoDB相比传统的关系型数据库有一些优势，比如在海量数据下的性能表现、很好的扩展性等。初识MongoDB感觉和关系型数据库最大的区别就是没有关系型数据库中的那种关系模型，更准确的说她是一个面向文档的数据库。通俗的讲在MongoDB中集合对应关系型数据库的表，文档对应着行。在MongoDB中一条记录的表现形式是BSON的格式，和JavaScript中的JSON类似。&lt;/p&gt;
&lt;h2 id="mongdb的下载安装"&gt;MongDB的下载安装&lt;/h2&gt;
&lt;p&gt;下载地址：&lt;a href="http://www.mongodb.org/downloads"&gt;http://www.mongodb.org/downloads&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;下载下来的是一个mongodb-win32-i386-1.8.2.zip文件，将该文件解压，会发现里面的bin目录下有很多的exe文件，这些是MongoDB的一些工具，比如要启动MongoDB服务就要用到里面的Mongod.exe。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300726967.webp" alt="2011-09-12_114648" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;bsondump: 将 bson 格式的文件转储为json 格式的数据&lt;/li&gt;
&lt;li&gt;mongo: 客户端命令行工具，其实也是一个javascript解释器，支持javascript语法&lt;/li&gt;
&lt;li&gt;mongod: 数据库服务端，每个实例启动一个进程，可以fork 为后台运行&lt;/li&gt;
&lt;li&gt;mongodump/ mongorestore: 数据库备份和恢复工具&lt;/li&gt;
&lt;li&gt;mongoexport/ mongoimport: 数据导出和导入工具&lt;/li&gt;
&lt;li&gt;mongofiles: GridFS 管理工具，可实现二制文件的存取&lt;/li&gt;
&lt;li&gt;mongos: 分片路由，如果使用了sharding功能，则应用程序连接的是 mongo而不是 mongod&lt;/li&gt;
&lt;li&gt;mongosniff: 这一工具的作用类似于tcpdump，不同的是他只监控MongoDB 相关的包请求，并且是以指定的可读性的形式输出&lt;/li&gt;
&lt;li&gt;mongostat: 实时性能监控工具&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;要正常的使用MongoDB首先要做的就是启动MongoDB服务，打开CMD进入到MongoDB的bin目录，执行Mongod.exe，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300726870.webp" alt="2011-09-12_132542-300x66" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;可以看到在mongod.exe 后面有一个-dbpath来制定数据库的存放路径。这个目录我们必须事先创建好。如果没有制定-dbpath，会使用默认路径：C：\data\db\。&lt;/p&gt;
&lt;p&gt;下面就可以在MongoDB中来创建数据库了，本文中使用MongoDB自带的Shell来进行操作，在下一篇中将介绍MongoDB的一款IDE工具MongoVUE，使用bin先的mongo.exe可以打开Shell窗口。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300727903.webp" alt="2011-09-12_133937-300x58" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;执行show dbs命令可以查看所有数据库的列表，关于更多的Shell命令可以通过执行help命令查看。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300727232.webp" alt="2011-09-12_142453" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;admin和local数据库是MongoDB自带的数据库，这两个数据库在系统中有特殊的作用。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;admin：最高权限的一个数据库，该数据库中的用户会拥有所有数据库的权限。一些特殊的服务器端的命令也只能从这个数据库中运行。&lt;/li&gt;
&lt;li&gt;local：该数据库不会被复制，可以用来存储限与本地单台服务器的任意集合。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在MongoDB的Shell命令中并没有创建数据库的命令，假设现在要创建一个名为Blogs的数据库，并在这个数据库中添加集合和文档，我们可以想下面这样做：&lt;/p&gt;
&lt;p&gt;1 执行use Blogs命令将数据库切换到Blogs，当然此时Blogs还并没有被创建。&lt;/p&gt;
&lt;p&gt;2 创建一条数据记录保存在一个变量post中，执行db.Blogs.insert(post)。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300727969.webp" alt="2011-09-12_201351-300x91" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;这时可以看在在上面设定的路径中已经生产了数据库的文件：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300727295.webp" alt="2011-09-12_201414-300x103" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;有关更多的Shell命令使用在后面的文章中再介绍。&lt;/p&gt;
&lt;h2 id="mongodb-drivers"&gt;MongoDB Drivers&lt;/h2&gt;
&lt;p&gt;要在程序中使用MongoDB，需要要到MongoDB针对某一语言的驱动，在MongoDB的官网中已经提供了Ruby 、Python、C#、PHP等多种语言的驱动。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;驱动列表页：&lt;a href="http://www.mongodb.org/display/DOCS/Drivers"&gt;http://www.mongodb.org/display/DOCS/Drivers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;C#驱动下载：&lt;a href="https://github.com/samus/mongodb-csharp"&gt;https://github.com/samus/mongodb-csharp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对MongoDB的简单介绍就到此，后面的文章会用C#来写一个完整的示例。&lt;/p&gt;</description></item><item><title>在VS中查看文件是谁签出的</title><link>https://fwhyy.com/2011/08/in-vs-view-who-file-is-checked-out/</link><pubDate>Sat, 20 Aug 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/08/in-vs-view-who-file-is-checked-out/</guid><description>&lt;p&gt;最近的项目使用的源码管理器是VSS，有时候你想修改的文件被别人签出了，所以我们需要知道该文件是被谁签出了，好及时和他沟通。我原来的做法都是直接进入VSS管理器中进行查看，但这样很麻烦，每次都要打开VSS管理器。其实可以在VS中进行简单的设置就可以了，步骤如下：&lt;/p&gt;
&lt;p&gt;1 在VS中的菜单上单击鼠标右键，然后选择显示“源代码管理”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300706197.webp" alt="2011-08-13_160609" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 选中要查看的文件后，在源代码管理中单击“属性”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300706261.webp" alt="2011-08-13_160643" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 打开第2个标签页“Check Out Status”，可以看到签出人等信息。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300706850.webp" alt="2011-08-13_160833" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>在SQL查询中使用LIKE来代替IN</title><link>https://fwhyy.com/2011/08/in-the-sql-query-using-the-like-instead-of-the-in/</link><pubDate>Sat, 13 Aug 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/08/in-the-sql-query-using-the-like-instead-of-the-in/</guid><description>&lt;p&gt;在SQL查询中根据已知ID的集合来查询结果我们通常会用到IN，直接在IN后面给出ID的集合或是在IN后面跟一个子查询。如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT * FROM Orders
WHERE OrderGUID IN(&amp;#39;BC71D821-9E25-47DA-BF5E-009822A3FC1D&amp;#39;,&amp;#39;F2212304-51D4-42C9-AD35-5586A822258E&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;可以看出直接在IN后面跟ID的集合需要将每一个ID都用单引号引起来。在实际应用中会遇到这么一种情况，在界面中收集的是一串GUID的拼接字符串，中间以逗号隔开，如果作为参数传到一个存储过程中执行，最终生成的语句会是下面这样：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT * FROM Orders
WHERE OrderGUID IN(&amp;#39;BC71D821-9E25-47DA-BF5E-009822A3FC1D,F2212304-51D4-42C9-AD35-5586A822258E&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这样就不能查询到正确的结果。&lt;/p&gt;
&lt;p&gt;一般情况下我们解决此问题的思路是将传入的字符串用一个split函数来处理，最终处理的结果是一张表，然后将这个表做自查询即可，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;DECLARE @IDs VARCHAR(4000)
SET @IDs=&amp;#39;BC71D821-9E25-47DA-BF5E-009822A3FC1D,F2212304-51D4-42C9-AD35-5586A822258E&amp;#39;
DECLARE @temp TABLE(str VARCHAR(50))
INSERT INTO @temp
SELECT * FROM dbo.Split(@IDs,&amp;#39;,&amp;#39;)
SELECT * FROM Orders WHERE OrderGUID IN (SELECT str FROM @temp)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;当然split函数系统比不提供，需要我们自己写：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;CREATE FUNCTION Split
(
 @SourceSql varchar(8000),
 @StrSeprate varchar(10)
)
RETURNS @temp TABLE(F1 VARCHAR(100))
AS
BEGIN
 DECLARE @i INT
 SET @SourceSql=rtrim(ltrim(@SourceSql))
 SET @i=charindex(@StrSeprate,@SourceSql)
 WHILE @i&amp;gt;=1
 BEGIN
 INSERT @temp VALUES(left(@SourceSql,@i-1))
 SET @SourceSql=substring(@SourceSql,@i+1,len(@SourceSql)-@i)
 SET @i=charindex(@StrSeprate,@SourceSql)
 END
 IF @SourceSql&amp;lt;&amp;gt;&amp;#39;&amp;#39;
 INSERT @temp VALUES(@SourceSql)
 RETURN
END
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;像这样做非常麻烦，而且还需要借助函数来实现，下面介绍一种简单的方法，因为GUID是唯一的，所以在上面的例子中可以使用LIKE来代替IN也可以达到同样的查询效果：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT * FROM Orders
WHERE &amp;#39;BC71D821-9E25-47DA-BF5E-009822A3FC1D,F2212304-51D4-42C9-AD35-5586A822258E&amp;#39;
LIKE &amp;#39;%&amp;#39;+convert(VARCHAR(40),OrderGUID)+&amp;#39;%&amp;#39;
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>SqlServer表死锁的解决方法</title><link>https://fwhyy.com/2011/08/essentially-a-table-of-deadlock-solution/</link><pubDate>Sat, 06 Aug 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/08/essentially-a-table-of-deadlock-solution/</guid><description>&lt;p&gt;前些天写一个存储过程，存储过程中使用了事务，后来我把一些代码注释掉来进行调试找错，突然发现一张表被锁住了，原来是创建事务的代码忘记注释掉。本文表锁住了的解决方法。&lt;/p&gt;
&lt;p&gt;其实不光是上面描述的情况会锁住表，还有很多种场景会使表放生死锁，解锁其实很简单，下面用一个示例来讲解：&lt;/p&gt;
&lt;p&gt;1 首先创建一个测试用的表：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;CREATE TABLE Test
(
 TID INT IDENTITY(1,1)
)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 执行下面的SQL语句将此表锁住：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT * FROM Test WITH (TABLOCKX)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;3 通过下面的语句可以查看当前库中有哪些表是发生死锁的：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT request_session_id spid,OBJECT_NAME(resource_associated_entity_id)tableName
FROM sys.dm_tran_locks
WHERE resource_type=&amp;#39;OBJECT &amp;#39; 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;4 上面语句执行结果如下：&lt;/p&gt;
&lt;p&gt;spid ：被锁进程ID。
tableName：发生死锁的表名。
5 只需要使用kill关键字来杀掉被锁的进程ID就可以对表进行解锁：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;KILL 52
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>使用sp_xml_preparedocument处理XML文档</title><link>https://fwhyy.com/2011/07/use-sp-xml-preparedocument-processing-xml-documents/</link><pubDate>Sat, 23 Jul 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/07/use-sp-xml-preparedocument-processing-xml-documents/</guid><description>&lt;p&gt;有时会在存储过程中处理一些XML格式的数据，所以会用到sp_xml_preparedocument，他可以将XML数据进行读取，然后使用 MSXML 分析器 (Msxmlsql.dll) 对其进行分析。我们就可以很容易的在存储过程中得到XML中我们想要的数据。下面的代码就是使用sp_xml_preparedocument读取XML：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;DECLARE @hdoc int
DECLARE @doc varchar(1000)
SET @doc =&amp;#39;
&amp;lt;ROOT&amp;gt;
&amp;lt;Customer CustomerID=&amp;#34;VINET&amp;#34; ContactName=&amp;#34;Paul Henriot&amp;#34;&amp;gt;
 &amp;lt;Order CustomerID=&amp;#34;VINET&amp;#34; EmployeeID=&amp;#34;5&amp;#34; OrderDate=&amp;#34;1996-07-04T00:00:00&amp;#34;&amp;gt;
 &amp;lt;OrderDetail OrderID=&amp;#34;10248&amp;#34; ProductID=&amp;#34;11&amp;#34; Quantity=&amp;#34;12&amp;#34;/&amp;gt;
 &amp;lt;OrderDetail OrderID=&amp;#34;10248&amp;#34; ProductID=&amp;#34;42&amp;#34; Quantity=&amp;#34;10&amp;#34;/&amp;gt;
 &amp;lt;/Order&amp;gt;
&amp;lt;/Customer&amp;gt;
&amp;lt;Customer CustomerID=&amp;#34;LILAS&amp;#34; ContactName=&amp;#34;Carlos Gonzlez&amp;#34;&amp;gt;
 &amp;lt;Order CustomerID=&amp;#34;LILAS&amp;#34; EmployeeID=&amp;#34;3&amp;#34; OrderDate=&amp;#34;1996-08-16T00:00:00&amp;#34;&amp;gt;
 &amp;lt;OrderDetail OrderID=&amp;#34;10283&amp;#34; ProductID=&amp;#34;72&amp;#34; Quantity=&amp;#34;3&amp;#34;/&amp;gt;
 &amp;lt;/Order&amp;gt;
&amp;lt;/Customer&amp;gt;
&amp;lt;/ROOT&amp;gt;&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;EXEC sp_xml_preparedocument @hdoc OUTPUT, @doc
上面只是读取了XML，要想获取XML数据还需要使用OPENXML，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT *
FROM openxml(@hdoc,&amp;#39;/ROOT/Customer&amp;#39;,1)
WITH (CustomerID VARCHAR(40),ContactName VARCHAR(40)) 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OPENXML有三个参数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一个是sp_xml_preparedocument读取是的OUTPUT参数，在本示例中就是@hdoc；&lt;/li&gt;
&lt;li&gt;第二个是一个XPath表达式，用来获取指定位置的数据；&lt;/li&gt;
&lt;li&gt;第三个是一个可选项，用来表示获取的方式，有0,1,2,8四种取值，详细解释&lt;a href="http://msdn.microsoft.com/zh-cn/library/ms186918.aspx"&gt;请看&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;FROM后面的WITH也是可选的，用来指定获取哪些数据字段，上面代码中只取了CustomerID和ContactName。上面的查询结果如下：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;CustomerID&lt;/th&gt;
					&lt;th&gt;ContactName&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;LILAS&lt;/td&gt;
					&lt;td&gt;Carlos Gonzlez&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;如果不指定WITH子句，查询出来的是一个默认的表结构，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2011/2011-07-23_114701.webp" alt="2011-07-23_114701" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;表格列的解释说明：&lt;/p&gt;
&lt;p&gt;在WITH子句中,我们还可以通过设置来获取父级元素的属性值:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;DECLARE @hdoc int
DECLARE @doc varchar(1000)
SET @doc =&amp;#39;
&amp;lt;ROOT&amp;gt;
&amp;lt;Customer CustomerID=&amp;#34;VINET&amp;#34; ContactName=&amp;#34;Paul Henriot&amp;#34;&amp;gt;
 &amp;lt;Order OrderID=&amp;#34;10248&amp;#34; CustomerID=&amp;#34;VINET&amp;#34; EmployeeID=&amp;#34;5&amp;#34;
 OrderDate=&amp;#34;1996-07-04T00:00:00&amp;#34;&amp;gt;
 &amp;lt;OrderDetail ProductID=&amp;#34;11&amp;#34; Quantity=&amp;#34;12&amp;#34;/&amp;gt;
 &amp;lt;OrderDetail ProductID=&amp;#34;42&amp;#34; Quantity=&amp;#34;10&amp;#34;/&amp;gt;
 &amp;lt;/Order&amp;gt;
&amp;lt;/Customer&amp;gt;
&amp;lt;Customer CustomerID=&amp;#34;LILAS&amp;#34; ContactName=&amp;#34;Carlos Gonzlez&amp;#34;&amp;gt;
 &amp;lt;Order OrderID=&amp;#34;10283&amp;#34; CustomerID=&amp;#34;LILAS&amp;#34; EmployeeID=&amp;#34;3&amp;#34;
 OrderDate=&amp;#34;1996-08-16T00:00:00&amp;#34;&amp;gt;
 &amp;lt;OrderDetail ProductID=&amp;#34;72&amp;#34; Quantity=&amp;#34;3&amp;#34;/&amp;gt;
 &amp;lt;/Order&amp;gt;
&amp;lt;/Customer&amp;gt;
&amp;lt;/ROOT&amp;gt;&amp;#39;

EXEC sp_xml_preparedocument @hdoc OUTPUT, @doc
SELECT *
FROM OPENXML (@hdoc, &amp;#39;/ROOT/Customer/Order/OrderDetail&amp;#39;,2)
 WITH (OrderID int &amp;#39;../@OrderID&amp;#39;,
 CustomerID varchar(10) &amp;#39;../@CustomerID&amp;#39;,
 OrderDate datetime &amp;#39;../@OrderDate&amp;#39;,
 ProdID int &amp;#39;@ProductID&amp;#39;,
 Qty int &amp;#39;@Quantity&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查询的结果为:&lt;/p&gt;</description></item><item><title>使用MicroSoft CLR Debug来调试较大项目</title><link>https://fwhyy.com/2011/07/use-microsoft-clr-debug-to-debug-larger-projects/</link><pubDate>Wed, 20 Jul 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/07/use-microsoft-clr-debug-to-debug-larger-projects/</guid><description>&lt;p&gt;在以前的开发中，调试时很自然的会直接按F5进行调试，有时项目部署在IIS中也只是将项目的服务器指向IIS，仍然是将整个项目运行设置断点进行调试。最近遇到了一个问题，项目很大，直接F5运行会导致VS卡死，这种时候使用MicroSoft CLR Debug来进行调试是最合适不过了。&lt;/p&gt;
&lt;p&gt;首先打开MicroSoft CLR Debug&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290710632.webp" alt="2011-07-18_164829" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;打开后界面如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290710108.webp" alt="2011-07-18_164908" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;从项目中选择一个需要调试的文件，并在需要调试的地方设置断点&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290710393.webp" alt="2011-07-18_165017" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;选择“调试”-“附加到进程”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290710454.webp" alt="2011-07-18_165041" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;附加进程前确保你的项目已经运行，如果是Win2003系统，会有一个w3wp.exe的进程存在,如果是xp系统，该进程名是aspnet_wp.exe。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290710503.webp" alt="2011-07-18_165126" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;此时运行程序就会命中断点，个人认为此方法比较适用于将项目部署到IIS中进行调试，此方法的几个优点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不会占用很多资源，只需要将需要调试的文件添加进来设置断点即可。&lt;/li&gt;
&lt;li&gt;如果是管理系统之类的项目，只需要登陆一次即可，不需要每次调试时都重新登陆。&lt;/li&gt;
&lt;li&gt;退出调试不会对运行的程序有什么影响，如果是F5进行调试，退出调试页面就关闭了。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>给Javascript代码“预留退路”</title><link>https://fwhyy.com/2011/06/retreat-to-the-javascript-code-reserved/</link><pubDate>Thu, 16 Jun 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/06/retreat-to-the-javascript-code-reserved/</guid><description>&lt;p&gt;所谓给Javascript代码“预留退路”意思就是当用户将浏览器的Javascript功能禁用的时候，页面中使用了Javascript的地方要能够以变通的方式得以运行，而不能让用户看到出错或是点击某按钮而毫无反应，这也是用户体验很重要的一部分。&lt;/p&gt;
&lt;p&gt;举个简单的例子来说，点击页面中的一个链接可以弹出一个新的页面，我们通常会使用window.open，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;a href=&amp;#34;#&amp;#34; onclick=&amp;#34;openWin(&amp;#39;http://baidu.com&amp;#39;);&amp;#34;&amp;gt;百度&amp;lt;/a&amp;gt;
&amp;lt;script type=&amp;#34;text/javascript&amp;#34;&amp;gt;
 function openWin(url) {
 window.open(url, &amp;#34;openwin&amp;#34;, &amp;#34;width=600,height=400&amp;#34;);
 }
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;或&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;a href=&amp;#34;javascript:openWin1(&amp;#39;http://baidu.com&amp;#39;);&amp;#34; &amp;gt;百度&amp;lt;/a&amp;gt;
&amp;lt;script type=&amp;#34;text/javascript&amp;#34;&amp;gt;
 function openWin(url) {
 window.open(url, &amp;#34;openwin&amp;#34;, &amp;#34;width=600,height=400&amp;#34;);
 }
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的两种方法第一种将href的值设置为#，第二种使用伪协议javascript: ，这两种做法都不是很好，没有“预留退路”，当用户将浏览器的Javascript禁用后，点击链接都不是我们想要的结果，正确的做法如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;a href=&amp;#34;http://baidu.com/&amp;#34;
 onclick=&amp;#34;openWin(this.getAttribute(&amp;#39;href&amp;#39;));return false;&amp;#34; &amp;gt;百ù度è&amp;lt;/a&amp;gt;
 &amp;lt;script type=&amp;#34;text/javascript&amp;#34;&amp;gt;
 function openWin1(url) {
 window.open(url, &amp;#34;openwin&amp;#34;, &amp;#34;width=600,height=400&amp;#34;);
 }
 &amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;改进后的方法在禁用Javascript后，也会打开href中的链接地址，只是打开方式有所不同，相比上面两种已经好多了。&lt;/p&gt;</description></item><item><title>未在本地计算机上注册“Microsoft.Jet.OleDb.4.0”提供程序 错误解决</title><link>https://fwhyy.com/2011/06/not-registered-on-the-local-computer-microsoft-jet-oledb-4/</link><pubDate>Wed, 15 Jun 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/06/not-registered-on-the-local-computer-microsoft-jet-oledb-4/</guid><description>&lt;p&gt;最近在做一个导入Excel数据到数据库的程序出现了如下错误：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301558041.webp" alt="2011-06-15_1552061" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="运行环境"&gt;运行环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;数据库：SqlServer2008 R2&lt;/li&gt;
&lt;li&gt;OS：Windows Server 2008 R2&lt;/li&gt;
&lt;li&gt;IIS：IIS7&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="解决方法"&gt;解决方法&lt;/h2&gt;
&lt;p&gt;在应用程序对用的应用程序池的高级设置中设置“启用32位应用程序”为“True”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301558286.webp" alt="2011-06-15_155851" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>Windows服务在Win7中不能安装的解决方法</title><link>https://fwhyy.com/2011/05/windows-service-in-windows-7-cant-install-solution/</link><pubDate>Tue, 24 May 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/05/windows-service-in-windows-7-cant-install-solution/</guid><description>&lt;p&gt;用C#写的Windows服务在Win7中安装时出现如下错误：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290648137.webp" alt="2011-05-24_102447" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;解决方法：&lt;/p&gt;
&lt;p&gt;1 安装服务的脚本写在bat文件中，一定要注意路径，如下&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;D:\Project\JXW\Code\WorkFlow\FlowServer\installutil.exe D:\Project\JXW\Code\WorkFlow\FlowServer\FlowServer.exe

pause


net start ShineFlow.FlowServer
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 在bat文件上点击右键-》以管理员身份运行。&lt;/p&gt;
&lt;p&gt;3 成功安装服务，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290649864.webp" alt="2011-05-24_102806" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>附加数据库失败 操作系统错误5</title><link>https://fwhyy.com/2011/05/additional-database-failure-5120-error/</link><pubDate>Sun, 22 May 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/05/additional-database-failure-5120-error/</guid><description>&lt;h2 id="环境"&gt;环境&lt;/h2&gt;
&lt;p&gt;数据库版本：SqlServer2008 R2 32位&lt;/p&gt;
&lt;p&gt;附加文件的版本：SqlServer2008 R2 64位&lt;/p&gt;</description></item><item><title>在VS2010中将AspNet网站编译成一个DLL</title><link>https://fwhyy.com/2011/04/aspnet-website-compiled-into-a-dll-in-vs2010/</link><pubDate>Wed, 06 Apr 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/04/aspnet-website-compiled-into-a-dll-in-vs2010/</guid><description>&lt;p&gt;在VS2010中创建一个网站，部署时网站的dll是动态生成的，每次编译产生的dll的名称都不一样，这样会导致在部署时必须将aspx页面和dll一起部署，尽管有时你可能只修改了后台代码。这样就变得很不方便，在VS2010中可以借助一个插件是网站生成一个固定名称的dll。&lt;/p&gt;
&lt;p&gt;1 从下面的链接地址中下载 Visual Studio® 2010 Web Deployment Projects&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.microsoft.com/downloads/en/confirmation.aspx?FamilyID=711a2eef-b107-4784-9063-c978edc498cd&amp;amp;displaylang=en"&gt;http://www.microsoft.com/downloads/en/confirmation.aspx?FamilyID=711a2eef-b107-4784-9063-c978edc498cd&amp;amp;displaylang=en&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2 安装Visual Studio® 2010 Web Deployment Projects插件，然后再网站项目上点击右键，可以看到多了一项Add Web Deployment Project&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290807175.webp" alt="2011-04-06_113023" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 点击Add Web Deployment Project，弹出如下对话框&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290807160.webp" alt="2011-04-06_113422" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;4 名称和路径可以修改，一般默认就好，点击OK，在解决方案中会生成一个部署项目&lt;/p&gt;
&lt;p&gt;5 在部署项目点击右键，点击“生成”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290807093.webp" alt="2011-04-06_113814" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;6 生成成功后，在部署项目的目录中会产生一个Release目录，Release目录中就是项目发布的所有文件，在bin目录中可以看到并没有之前那样有很多不规则命名的dll，生成的dll的名称和前面添加部署项目时所填写的名称相同，为EduAppWeb_deploy&lt;/p&gt;</description></item><item><title>Asp.Net站点整合Discuz论坛实现同步注册和单点登录</title><link>https://fwhyy.com/2011/04/aspnet-site-integration-discuz-bbs-sync-reg-and-sso/</link><pubDate>Fri, 01 Apr 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/04/aspnet-site-integration-discuz-bbs-sync-reg-and-sso/</guid><description>&lt;p&gt;最近在一个小站中整合了Discuz论坛，查阅了些资料后实现了同步注册和单点登录。&lt;/p&gt;
&lt;p&gt;Discuz是以虚拟目录的方式加载网站中，整合Discuz到网站中进行安装要注意一下几个问题：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201292105539.webp" alt="2011-04-01_163915" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Discuz所在的目录需要添加NETWORK SERVICE 和IIS_User这两个账户的权限。&lt;/li&gt;
&lt;li&gt;Discuz根目录下的DNT.config文件需要修改，将&lt;Forumpath&gt;/&lt;/Forumpath&gt;修改为&lt;Forumpath&gt;/BBS/&lt;/Forumpath&gt;，BBS为虚拟目录的名称。&lt;/li&gt;
&lt;li&gt;由于我网站用了第三方的控件，在webconfig文件中进行了相关设置，然后在访问论坛时提示缺少程序集的引用，后来把第三方控件的dll加到Discuz下的bin目录中得以解决。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下面说说怎样实现同步注册和单点登录&lt;/p&gt;
&lt;p&gt;其实在研究后发现很简单，当然我现在做的只是同域的情况下，跨域的情况还没研究，估计也不会很难，应该只是多了一个设置cookieDomain的过程。Discuz给我们提供了一个DiscuzToolkit的工具包，提供了很多API供调用，下面就一步步来吧。&lt;/p&gt;
&lt;p&gt;1 安装好Discuz论坛后，进入后台管理，选择扩展-》通行证设置-》添加整合程序设置&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;应用程序名称：可以随便输入&lt;/li&gt;
&lt;li&gt;应用程序Url地址：我填写的是我站点的地址&lt;/li&gt;
&lt;li&gt;登录完成后返回地址：同上&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2 记下生成的APIKey和密匙，在后面的代码编写中会用到&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2011/2011-04-01_164204.webp" alt="2011-04-01_164204" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 我将APIKey，密匙都配置在了webconfig文件中&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201292106145.webp" alt="2011-04-01_164509" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;APIKey：value值为后台生成的APIKey&lt;/li&gt;
&lt;li&gt;Secret：value值为后台生成的密匙&lt;/li&gt;
&lt;li&gt;Url：value值为BBS的路径&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;4 写一个公共的BBSHelper类，将添加用户，登录，改密码等方法封装在里面。注意要引用命名空间Discuz.Toolkit&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 同步Discuz论坛帮助类
/// &amp;lt;/summary&amp;gt;
public class DiscuzBBSHelper
{
 private string _apiKey = string.Empty;
 private string _secret = string.Empty;
 private string _url = string.Empty;
 DiscuzSession _ds;

 public DiscuzBBSHelper()
 {
 _apiKey = ConfigHelper.APIKey();
 _secret = ConfigHelper.Secret();
 _url = ConfigHelper.Url();
 _ds = new DiscuzSession(_apiKey, _secret, _url);
 }

 /// &amp;lt;summary&amp;gt;
 /// 登录
 /// &amp;lt;/summary&amp;gt;
 public void Login(string userName,string pwd)
 {
 int uid = _ds.GetUserID(userName);
 _ds.Login(uid, pwd, false, 100, &amp;#34;&amp;#34;);
 }

 /// &amp;lt;summary&amp;gt;
 /// 登出
 /// &amp;lt;/summary&amp;gt;
 public void Logout()
 {
 _ds.Logout(&amp;#34;&amp;#34;);
 _ds.session_info = null;
 HttpContext.Current.Session[&amp;#34;AuthToken&amp;#34;] = null;
 }

 /// &amp;lt;summary&amp;gt;
 /// 创建用户
 /// &amp;lt;/summary&amp;gt;
 public void AddUser(string userName,string pwd)
 {
 _ds.Register(userName, pwd, &amp;#34;&amp;#34;, false);
 }

 /// &amp;lt;summary&amp;gt;
 /// 修改密码
 /// &amp;lt;/summary&amp;gt;
 public void ChangePWD(string userName,string oldPWD,string newPWD)
 {
 int uid = _ds.GetUserID(userName);
 _ds.ChangeUserPassword(uid, oldPWD, newPWD, newPWD, &amp;#34;&amp;#34;);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5 在网站需要的地方调用该类中的方法即可，如下：&lt;/p&gt;</description></item><item><title>在SqlServer 2008中将数据导成脚本</title><link>https://fwhyy.com/2011/03/data-into-the-sql-script-in-sqlserver-2008/</link><pubDate>Thu, 31 Mar 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/03/data-into-the-sql-script-in-sqlserver-2008/</guid><description>&lt;p&gt;当我们想将数据库搬到另一个环境中运行时，如果数据库的版本一样我们可以直接选择附加的方式，而如果实验环境中的数据库版本比当前数据库低，就无法附加了。这时要向将数据全部导过去就需要使用脚本的方式，像Sqldbx就可以将数据库中的数据导出成脚本。本文将说下怎样直接在SqlServer 2008中将数据导出成脚本。&lt;/p&gt;
&lt;p&gt;具体步骤：&lt;/p&gt;
&lt;p&gt;1 打开SqlServer 2008 ，选择需要将数据导出到脚本的数据库。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290623081.webp" alt="2011-03-31_102716" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 在选中数据库上右击，选择任务-》生成脚本…&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290623858.webp" alt="2011-03-31_102951" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 点击“生成脚本”后，弹出一个生成脚本的向导。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290623337.webp" alt="2011-03-31_103235" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;4 点击下一步至“设置脚本编写选项”，点击高级进入到高级设置对话框，可以看到“要编写脚本数据的类型”默认是“仅限架构”。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290623298.webp" alt="2011-03-31_103700" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;5 将“要编写脚本的数据的类型”修改为“架构和数据”。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290623038.webp" alt="2011-03-31_103808" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;6 执行完后，可以看到脚本中多了很多的Insert语句。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290624044.webp" alt="2011-03-31_104032" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>SQL2008修改并保存表结构时报错的解决(阻止保存要求重新创建表的更改)</title><link>https://fwhyy.com/2011/03/sql2008-modify-and-save-the-table-structure-error/</link><pubDate>Wed, 09 Mar 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/03/sql2008-modify-and-save-the-table-structure-error/</guid><description>&lt;p&gt;今天在SqlServer2008中修改表结构时，弹出下面对话框阻止我保存&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301954622.webp" alt="20100304002" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;解决此问题方法为：&lt;/p&gt;
&lt;p&gt;1 打开SqlServer2008工具—&amp;gt;选项&lt;/p&gt;
&lt;p&gt;2 在弹出的对话框中去掉“阻止保存要求重新创建表的更改”，如下图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301954844.webp" alt="2011-03-09_161021" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>Excel导入数据库出现“外部表不是预期的格式”错误的解决方法</title><link>https://fwhyy.com/2011/03/excel-import-database-external-table-is-not-desired-format-mistakes-of-the-solution/</link><pubDate>Tue, 08 Mar 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/03/excel-import-database-external-table-is-not-desired-format-mistakes-of-the-solution/</guid><description>&lt;p&gt;下图为出错的界面&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300645078.webp" alt="20110308001" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;出错的原因是因为Excel的格式不是标准的Excel格式，像我出现这个错误的原因就是使用的Excel是用程序导出的Excel。&lt;/p&gt;
&lt;p&gt;解决此问题方法很简单：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;将格式不标准的Excel另存为一个标准格式。&lt;/li&gt;
&lt;li&gt;如果Excel是用程序导出的，可以修改导出程序，将其导出为标准格式。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>VirtualPC2007的文件复制到其他电脑不能打开的问题解决</title><link>https://fwhyy.com/2011/03/virtualpc2007-file-is-copied-to-the-other-computer-cant-open-the-problem-solving/</link><pubDate>Fri, 04 Mar 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/03/virtualpc2007-file-is-copied-to-the-other-computer-cant-open-the-problem-solving/</guid><description>&lt;p&gt;在使用VirtualPC的时候，我一般都习惯保存当前状态的方式关机，这样在下次使用的时候可以保证继续我上次的工作状态。最近我将保存状态的VirtualPC2007的文件拷贝到另一台电脑中，然后用VirtualPC2007去添加，我选择的是已经存在的虚机，这时会报一个错误，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290625609.webp" alt="201103040011" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;经过查询得知，解决此问题的方法为启动VirtualPC后，按照添加新的虚机的方法去做，直到提示要选择硬盘的时候，选择已经存在的虚机硬盘，然后选择要添加虚机的vhd文件。这样就可以顺利的添加成功了。&lt;/p&gt;
&lt;p&gt;这时复制过来的虚机文件中的vmc文件还是以前的保存了状态的那个文件，新的vmc文件在目录C:\Users\Administrator\Documents\My Virtual Machines\虚机的名字 目录下，可以将此文件替换原来的vmc文件。&lt;/p&gt;
&lt;p&gt;吃一堑长一智，以后如果要将虚机拷贝到别的电脑上用，一定要先将虚机关机。&lt;/p&gt;</description></item><item><title>解决“此版本的 SQL Server 不支持用户实例登录标志。该连接将关闭”问题</title><link>https://fwhyy.com/2011/02/sql-server-does-not-support-the-user-instance-login-flag/</link><pubDate>Tue, 22 Feb 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/02/sql-server-does-not-support-the-user-instance-login-flag/</guid><description>&lt;p&gt;错误提示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301954824.webp" alt="20110222-001" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;出现此错误的原因为在webconfig连接字符串中的;User Instance设置为True了，将;User Instance值修改为false即可解决此问题。&lt;/p&gt;</description></item><item><title>解决AspNet中DataGrid GridView等列表控件导出Excel长数字显示成科学计数法的问题</title><link>https://fwhyy.com/2011/01/solve-gridview-long-export-excel-such-as-digital-display/</link><pubDate>Sun, 23 Jan 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/01/solve-gridview-long-export-excel-such-as-digital-display/</guid><description>&lt;p&gt;大家都知道，在Excel中，当一个单元格中的值为一长串数字，而且该单元格又不是文本格式的时候，这一长串数字会以科学计数法的方式显示，这给我们的阅读带来了障碍。如果是直接在Excel中编辑数据，手动将格式改为“文本”即可，但要是用程序导出的Excel，手动去改就显得很麻烦了。简单的方法就是在程序中导出Excel的时候就设置列为“文本”格式。&lt;/p&gt;
&lt;p&gt;AspNet中将DataGrid，GridView等列表控件导出Excel的代码通常如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;DataSet ds = GetData();
this.GridView1.DataSource = ds;
GridView1.DataBind();

//导出Excel的方法
Export(GridView1, &amp;#34;mayfile.xls&amp;#34;, &amp;#34;application/ms-excel&amp;#34;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;现在只需在调用导出Excel方法前对GridView中的列进行设置即可，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;DataSet ds = GetData();
this.GridView1.DataSource = ds;
GridView1.DataBind();

for (int i = 0; i &amp;lt; GridView1.Rows.Count; i++)
{
 for (int j = 0; j &amp;lt; GridView1.Columns.Count; j++)
 {
 GridView1.Rows[i].Cells[j].Attributes.Add(&amp;#34;style&amp;#34;, &amp;#34;vnd.ms-excel.numberformat:@&amp;#34;);
 }
}

//导出Excel的方法
Export(GridView1, &amp;#34;mayfile.xls&amp;#34;, &amp;#34;application/ms-excel&amp;#34;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码是将GridView中所有的列都设置成了文本格式，你也可以根据需要对指定的几列进行设置。&lt;/p&gt;</description></item><item><title>微软最新的 Web 开发工具WebMatrix的简单介绍及安装</title><link>https://fwhyy.com/2011/01/the-latest-microsoft-web-development-tools-webmatrix-simple-introduction-and-installation/</link><pubDate>Fri, 14 Jan 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/01/the-latest-microsoft-web-development-tools-webmatrix-simple-introduction-and-installation/</guid><description>&lt;p&gt;今天很给力，微软Asp.Net团队同时发布了WebMatrix,Razor,MVC3以及Orchard四个产品，其中&lt;a href="http://www.microsoft.com/web/webmatrix/"&gt;WebMatrix&lt;/a&gt; 是微软最新的 Web 开发工具，它包含了构建网站所需要的一切元素。您可以从开源 Web 项目或者内置的 Web 模板开始，也可以直接从无到有编写代码。简单并且完全是免费的。开发网站从来没有如此简单。&lt;/p&gt;
&lt;p&gt;什么介绍也没有官方的详细，我就将官网的介绍文字引用过来吧，当然你也可以访问&lt;a href="http://www.microsoft.com/web/webmatrix/"&gt;http://www.microsoft.com/web/webmatrix/&lt;/a&gt;进行了解。&lt;/p&gt;
&lt;h2 id="建立您的网站"&gt;建立您的网站&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;为了开始建立网站，您只需要使用 Microsoft Web 平台安装器下载并安装 WebMatrix。这只会占用您短短的5分钟时间。当 WebMatrix 成功安装后，您可以非常方便地获得并下载最新版本的免费 Web 应用，如 WordPress, Joomla!, DotNetNuke 和 Orchard.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="自定义您的网站"&gt;自定义您的网站&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;您会发现 WebMatrix 在一个统一界面中提供了您需要的一切工具的特性，不需要再花费精力于在多种应用工具切换来完成一般性的 Web 开发任务。通过 WebMatrix，您只需要一步点击，即可编辑文件，管理数据库和更改服务器设置等。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="发布您的网站"&gt;发布您的网站&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;当您完成网站开发后，WebMatrix 提供了最快速的方法来发布。通过访问托管服务库，您可以找到提供托管服务的合作伙伴，并且您可以直接通过 WebMatrix 来发布您的网站。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="安装"&gt;安装&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.microsoft.com/web/webmatrix/"&gt;WebMatrix&lt;/a&gt;的安装需要连接到网络，进入到官方网站，下载下exe的安装文件，双击进入安装。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302105019.webp" alt="2011-01-14_125505" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201302105421.webp" alt="2011-01-14_125530" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201302105543.webp" alt="2011-01-14_125600" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“安装”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302105185.webp" alt="2011-01-14_125634" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“我接受”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302105768.webp" alt="2011-01-14_125655" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;等待下载完成，自动进行安装&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302105713.webp" alt="2011-01-14_130224" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;再稍等几分钟&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302105235.webp" alt="2011-01-14_131824" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“完成”，就安装完成了，Web平台安装程序3.0 的界面如下，我们可以自行添加需要的项目进行安装&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302105836.webp" alt="2011-01-14_133049" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;刚刚接触&lt;a href="http://www.microsoft.com/web/webmatrix/"&gt;WebMatrix&lt;/a&gt;，会尽快抽时间好好体验一下，然后写成博文与大家分享。&lt;/p&gt;</description></item><item><title>在SharePoint2007中创建站点一：相关服务的启动</title><link>https://fwhyy.com/2011/01/sharepoint2007-related-service-startup/</link><pubDate>Thu, 13 Jan 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/01/sharepoint2007-related-service-startup/</guid><description>&lt;p&gt;在程序中打开“SharePoint3.0管理中心”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301941047.webp" alt="2011-01-11_225545" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“SharePoint3.0管理中心”会弹出要求输入用户名和密码的对话框&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301941326.webp" alt="2011-01-11_232210" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;输入用户名和密码（注意用户名需要是域名加上用户名），点击“确定”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301941628.webp" alt="2011-01-11_232432" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在上图中可以看出，服务器场配置未完成，所以先来配置服务器场。在“服务器场拓扑结构”下的“服务器”下点击服务器名称，上图中为“FENGWEI ”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301941460.webp" alt="2011-01-11_233056" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;单击“Office SharePoint Server搜索”后面的“启动”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301941413.webp" alt="2011-01-11_233919" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2011/2011-01-11_234255.webp" alt="2011-01-11_234255" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;勾选“使用此服务器索引内容”和“使用此服务器提供搜索查询服务”&lt;/p&gt;
&lt;p&gt;输入一个电子邮件地址&lt;/p&gt;
&lt;p&gt;输入管理员的账户信息，需要注意的是用户名必须以“域\用户名”的格式，如上图&lt;/p&gt;
&lt;p&gt;填写完毕后点击“开始”按钮来启动搜索服务&lt;/p&gt;
&lt;p&gt;使用同样的方法启动“Windows SharePoint Services 搜索 ”服务&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301941209.webp" alt="2011-01-11_234904" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“Windows SharePoint Services 搜索”右边的“启动”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301941256.webp" alt="2011-01-11_235051" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;填写“服务账户”和“内容访问账户”，两个账户填写一致就可以，注意用户名为“域\用户名”的格式，只填写这个两个账户信息即可，其他的保持默认，填写完毕点击“开始”按钮来启动服务&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301942453.webp" alt="2011-01-11_235346" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;数秒后服务便启动成功&lt;/p&gt;
&lt;p&gt;现在点击“Excel Calculation Services ”右边的“启动”来启动“Excel Calculation Services ”服务，启动该服务只需点击“启动”按钮即可，不需要做任何设置&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301942826.webp" alt="2011-01-11_235759" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;到此服务已经启动完成，切换到“主页”选项卡，服务器场拓扑结构如下图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301942490.webp" alt="2011-01-12_000124" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>SharePoint2007配置</title><link>https://fwhyy.com/2011/01/sharepoint2007-configuration/</link><pubDate>Wed, 12 Jan 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/01/sharepoint2007-configuration/</guid><description>&lt;p&gt;在前面的文章中已经介绍了SharePoint2007的安装，本篇将详细介绍下SharePoint2007的配置。首先从程序中打开SharePoint2007的配置向导。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301943608.webp" alt="2011-01-11_204240" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;向导启动后的界面如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301943157.webp" alt="2011-01-11_204406" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301944914.webp" alt="2011-01-11_204420" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;上图中提示需要启动或重启几个相关服务，点击“是”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301944425.webp" alt="2011-01-11_211055" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;因为我们是在安装第一台SharePoint服务器，所以选择第二项“否，我希望创建新的服务器场”，点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301945489.webp" alt="2011-01-11_221442" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;“数据库服务器”填写安装的SqlServer2005的服务器名称&lt;/p&gt;
&lt;p&gt;“数据库名称”默认为“SharePoint_Config ”，不用做修改&lt;/p&gt;
&lt;p&gt;“用户名为”AD域加上账户名称，如：fwhyy\administrator&lt;/p&gt;
&lt;p&gt;“密码”为Win2003Server的密码&lt;/p&gt;
&lt;p&gt;填写好后点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301945568.webp" alt="2011-01-11_221850" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;默认情况下系统会自动给分配一个端口号，在这里，我们指定一个特定的端口，勾选“指定端口号”，在后面的文本框中输入10000，“Web应用程序的验证提供程序”选择NTLM，点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301945543.webp" alt="2011-01-11_222312" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;所有的设置已经完成，点击“下一步”开始配置，请耐心等待&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301945504.webp" alt="2011-01-11_222430" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;稍等几分钟后便可配置成功&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301945270.webp" alt="201101130943278918" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“完成”后SharePoint的配置就结束了。创建SharePoint站点等会在后面的文章中详细介绍。&lt;/p&gt;</description></item><item><title>SharePoint2007安装图文详解三：安装SqlServer2005</title><link>https://fwhyy.com/2011/01/install-sqlserver2005/</link><pubDate>Tue, 11 Jan 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/01/install-sqlserver2005/</guid><description>&lt;p&gt;SharePoint2007 中的很多功能会用到数据库，如分析服务，报表服务等。本文介绍SqlServer2005的安装，数据库的安装很简单，基本上安装默认选项点击下一步即可，需要注意的地方在下面会提到。&lt;/p&gt;
&lt;p&gt;现在就开始安装SqlServer2005 ，运行Setup.exe&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300707160.webp" alt="2011-01-10_100800" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;选中“我接受许可条款和条件”，点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300707706.webp" alt="2011-01-10_113025" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“安装”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300707388.webp" alt="2011-01-10_113725" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300707407.webp" alt="2011-01-10_113911" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300707915.webp" alt="2011-01-10_113957" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300707990.webp" alt="2011-01-10_114354" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300707920.webp" alt="2011-01-10_114427" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“高级”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300708207.webp" alt="2011-01-10_120035" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;根据需要选择需要安装的服务，此处我将所有的都选择了，点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300708185.webp" alt="2011-01-10_120318" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;选择“默认实例”，点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300708141.webp" alt="2011-01-10_144340" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;选择“使用域用户账户”，输入用户名和密码，域填写在安装AD时配置的域名称。填写完后点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300708895.webp" alt="201101111515433034" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;选择“Windows身份验证模式”，点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300708213.webp" alt="2011-01-10_145622" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;按照默认，点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300708228.webp" alt="2011-01-10_145752" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;选择“安装默认配置”，点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300708174.webp" alt="2011-01-10_145938" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300709983.webp" alt="2011-01-10_150028" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“安装”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300709405.webp" alt="2011-01-10_150143" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;现在等他自己安装就行了，我们可以去做做别的事情。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300709198.webp" alt="2011-01-10_153124" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;到现在SqlServer2005已经安装成功了。&lt;/p&gt;
&lt;h2 id="相关文章"&gt;相关文章&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2011/01/iis-install/"&gt;SharePoint2007安装图文详解一：安装IIS及相关组件&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2011/01/installation-of-ad-and-dns/"&gt;SharePoint2007安装图文详解二：安装AD（活动目录）及DNS&lt;/a&gt;
SharePoint2007安装图文详解三：安装SqlServer2005
&lt;a href="http://blog.fwhyy.com/2011/01/installation-of-the-net-framework-3-0-and-sharepoint-2007/"&gt;SharePoint2007安装图文详解四：安装.NET Framework 3.0和SharePoint 2007&lt;/a&gt;&lt;/p&gt;</description></item><item><title>SharePoint2007安装图文详解四：安装.NET Framework 3.0和SharePoint 2007</title><link>https://fwhyy.com/2011/01/installation-of-the-net-framework-3-0-and-sharepoint-2007/</link><pubDate>Tue, 11 Jan 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/01/installation-of-the-net-framework-3-0-and-sharepoint-2007/</guid><description>&lt;p&gt;终于到了SharePoint2007安装的最后一步了，.NET Framework 3.0在官网可以下载，不过需要连接到网络才可以安装，SharePoint2007我下载的是官网的半年试用版，但安装的时候居然要求输入序列号，随便搜了一个顺利通过，嘿嘿！下面是下载链接地址和序列号&lt;/p&gt;
&lt;p&gt;.NETFramework3.0：&lt;a href="http://www.microsoft.com/downloads/zh-cn/confirmation.aspx?familyId=10cc340b-f857-4a14-83f5-25634c3bf043&amp;amp;displayLang=zh-cn"&gt;http://www.microsoft.com/downloads/zh-cn/confirmation.aspx?familyId=10cc340b-f857-4a14-83f5-25634c3bf043&amp;amp;displayLang=zh-cn&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SharePoint2007：&lt;a href="http://www.microsoft.com/downloads/zh-cn/confirmation.aspx?familyId=10cc340b-f857-4a14-83f5-25634c3bf043&amp;amp;displayLang=zh-cn"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyID=2e6e5a9c-ebf6-4f7f-8467-f4de6bd6b831&amp;amp;displayLang=zh-cn&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SharePoint 2007 序列号：F6YVR-4XY7K-RCVY4-37FBK-G44PY&lt;/p&gt;
&lt;p&gt;安装.NET Framework 3.0&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300714138.webp" alt="2011-01-08_215420" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;加载完后进入安装界面&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300715807.webp" alt="2011-01-08_215504" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;可以看到文件大小有39MB，需要连接网络下载，点击“安装”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300715905.webp" alt="2011-01-08_215730" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;等待下载完成&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300715941.webp" alt="2011-01-08_220523" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201300715126.webp" alt="2011-01-08_220931" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;.NET Framework 3.0 已安装成功&lt;/p&gt;
&lt;h2 id="安装sharepoint-2007"&gt;安装SharePoint 2007&lt;/h2&gt;
&lt;p&gt;双击下载下来的exe文件
&lt;img src="https://img.fwhyy.com/2022/202201300715143.webp" alt="2011-01-09_001745" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201300715762.webp" alt="2011-01-09_002829" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201300715130.webp" alt="2011-01-09_002843" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;输入上面给出的序列号，点击“继续”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300716923.webp" alt="201101120951336913" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;选中“我接受此协议的条款”，点击继续&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300716524.webp" alt="2011-01-09_002948" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“高级”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300716659.webp" alt="2011-01-09_003240" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;“服务器类型”选项卡中选中“完整…”，然后切换到“文件位置”选项卡&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300716328.webp" alt="2011-01-09_003313" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;文件位置可以选择你想放的目录，此处是使用默认位置，然后切换到“反馈”选项卡&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300716580.webp" alt="2011-01-09_003327" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;该处我选择的是“不参加”，点击“立即安装”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300716355.webp" alt="2011-01-09_003350" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;稍等片刻就安装完毕了&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300717282.webp" alt="2011-01-10_171910" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“关闭”会提示重启，重启电脑后SharePoint 2007 就成功安装了。&lt;/p&gt;
&lt;p&gt;安装仅仅只是一个开始，配置乃至跟多的内容请关注我的后面的文章吧&lt;/p&gt;
&lt;h2 id="相关文章"&gt;相关文章&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2011/01/iis-install/"&gt;SharePoint2007安装图文详解一：安装IIS及相关组件&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2011/01/installation-of-ad-and-dns/"&gt;SharePoint2007安装图文详解二：安装AD（活动目录）及DNS&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2011/01/install-sqlserver2005/"&gt;SharePoint2007安装图文详解三：安装SqlServer2005&lt;/a&gt;
SharePoint2007安装图文详解四：安装.NET Framework 3.0和SharePoint 2007&lt;/p&gt;</description></item><item><title>SharePoint2007安装图文详解一：IIS安装</title><link>https://fwhyy.com/2011/01/iis-install/</link><pubDate>Mon, 10 Jan 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/01/iis-install/</guid><description>&lt;p&gt;由于工作需要最近准备研究下SharePoint，SharePoint的最新版本为2010，但由于硬件环境所致我打算从2007开始学。首先准备详细介绍下SharePoint2007的安装过程。&lt;/p&gt;
&lt;p&gt;本次安装是在Windows2003 sp2的虚拟机上进行，安装SharePoint2007 先后分为以下几个步骤&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;安装IIS等一些组件&lt;/li&gt;
&lt;li&gt;安装AD（活动目录）及DNS&lt;/li&gt;
&lt;li&gt;安装SqlServer2005&lt;/li&gt;
&lt;li&gt;安装.NET Framework 3.0&lt;/li&gt;
&lt;li&gt;安装SharePoint 2007&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;由于安装介绍大部分为图片，为了博文的访问速度我将上面的几个步骤分为4篇来介绍，本文只介绍安装IIS及一些相关组件。下面就正式开始安装了。&lt;/p&gt;
&lt;p&gt;现在假设我们已经在Virtual PC中安装好了Win2003 SP2，从控制面板中打开“添加或删除程序”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300703827.webp" alt="2011-01-09_014134" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在弹出窗口左侧选择“添加/删除Windows组件”来启动组件向导&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300703310.webp" alt="2011-01-09_014211" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在“Windows组件向导”窗口中选中“应用程序服务器”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300703687.webp" alt="2011-01-09_014929" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“详细信息”，在弹出窗口中选择如下图的选项&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300703615.webp" alt="2011-01-09_015116" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在上图中选中“Internet信息服务（IIS）”点击详细信息，选中下图中的红色框标识的选项&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300704962.webp" alt="2011-01-09_015414" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;将所选配置确定保存，然后点击下一步进行安装&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300704693.webp" alt="2011-01-09_015621" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;稍等几分钟，即可安装成功。如果在安装过程中弹出提示框提示插入光盘，将Win2003的系统盘插入光驱即可，如果不是用光盘安装的系统，那么在Virtual PC中CD菜单中选择安装的ISO文件即可。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300704410.webp" alt="2011-01-09_015951" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;至此IIS及一些相关组件已经安装好了。下面链接中的博文继续介绍后继的安装。&lt;/p&gt;
&lt;h2 id="相关文章"&gt;相关文章&lt;/h2&gt;
&lt;p&gt;SharePoint2007安装图文详解一：安装IIS及相关组件
&lt;a href="http://blog.fwhyy.com/2011/01/installation-of-ad-and-dns/"&gt;SharePoint2007安装图文详解二：安装AD（活动目录）及DNS&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2011/01/install-sqlserver2005/"&gt;SharePoint2007安装图文详解三：安装SqlServer2005&lt;/a&gt;
[SharePoint2007安装图文详解四：安装.NET Framework 3.0和SharePoint 2007](SharePoint2007安装图文详解四：安装.NET Framework 3.0和SharePoint 2007)&lt;/p&gt;</description></item><item><title>SharePoint2007安装图文详解二：安装AD（活动目录）及DNS</title><link>https://fwhyy.com/2011/01/installation-of-ad-and-dns/</link><pubDate>Mon, 10 Jan 2011 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2011/01/installation-of-ad-and-dns/</guid><description>&lt;p&gt;在上一篇&lt;a href="http://blog.fwhyy.com/2011/01/iis-install/"&gt;SharePoint2007安装图文详解一&lt;/a&gt;：安装IIS及相关组件中已经介绍了IIS及相关组件的安装，本篇将详细介绍AD（活动目录）的安装。&lt;/p&gt;
&lt;p&gt;打开“管理您的服务器”，点击“添加或删除角色”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300710078.webp" alt="2011-01-09_114808" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“添加或删除角色”后弹出“配置你的服务器向导”对话框&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300710969.webp" alt="2011-01-09_214602" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击下一步进入如下对话框&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300710727.webp" alt="2011-01-09_215159" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;数秒后，进入到下面视图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300710662.webp" alt="2011-01-09_220636" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;选择“域控制器”后点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300711867.webp" alt="2011-01-09_221344" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300711508.webp" alt="2011-01-09_222512" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;随之便出现下面的对话框&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300711990.webp" alt="2011-01-09_222554" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300711554.webp" alt="201101110942371851" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;继续“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300711403.webp" alt="2011-01-09_222702" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;选择“新域的域控制器”，点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300711674.webp" alt="2011-01-09_222835" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;选择“在新林中的域”，点击下一步&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300712352.webp" alt="2011-01-09_222921" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;输入“新域的DNS全名”，如上图中我输入的fwhyy.com ， 点击下一步&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300712108.webp" alt="2011-01-09_223113" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;上图中的“域NetBIOS名”默认就好，一般不做修改，点击下一步&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300712290.webp" alt="2011-01-09_223228" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;AD数据库的保存路径保持默认就好，如果需要您可以修改为你想要存放的路径，然后点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300712760.webp" alt="2011-01-09_223350" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;SYSVOL文件夹的位置也不做修改，点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300713949.webp" alt="2011-01-09_223509" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;出现上图的窗口说明在安装AD前没有安装DNS，当然我们可以在之前先装好DNS再安装AD，此次安装中我选择的是选择上图对话框中的第二项，在安装AD的同时安装DNS。选择第二项后，点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300713948.webp" alt="2011-01-09_223815" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;选择“只与Windows 2000 或 Windows Server 2003 操作系统兼容的权限”，点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300713483.webp" alt="2011-01-09_225001" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;输入密码，点击“下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300713240.webp" alt="2011-01-09_225034" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;继续“下一步”，就会开始安装了&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300713152.webp" alt="2011-01-09_225123" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;稍等几分钟，就会出现安装成功的窗口，如下图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300713343.webp" alt="2011-01-09_225700" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击完成会弹出重启电脑的确认框&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300713258.webp" alt="2011-01-09_225755" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;重启动脑后会弹出下面对话框，提示此服务器已是域控制器&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300714657.webp" alt="2011-01-09_230726" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击“完成”就完成了AD和DNS的安装。&lt;/p&gt;
&lt;h2 id="相关文章"&gt;相关文章&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2011/01/iis-install/"&gt;SharePoint2007安装图文详解一：安装IIS及相关组件&lt;/a&gt;
SharePoint2007安装图文详解二：安装AD（活动目录）及DNS
&lt;a href="http://blog.fwhyy.com/2011/01/install-sqlserver2005/"&gt;SharePoint2007安装图文详解三：安装SqlServer2005&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2011/01/installation-of-the-net-framework-3-0-and-sharepoint-2007/"&gt;SharePoint2007安装图文详解四：安装.NET Framework 3.0和SharePoint 2007&lt;/a&gt;&lt;/p&gt;</description></item><item><title>jQuery boxy插件弹出框的四个边角图片在IE中不显示问题的解决</title><link>https://fwhyy.com/2010/12/jquery-boxy-plug-in-pop-up-the-four-edges-of-images-in-ie-dont-show/</link><pubDate>Thu, 09 Dec 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/12/jquery-boxy-plug-in-pop-up-the-four-edges-of-images-in-ie-dont-show/</guid><description>&lt;p&gt;jQuery boxy插件很好用，但也会出现一些问题，比如弹出框的边角在IE中不能显示。本博文将来解决这个问题。将boxy插件引用到项目中后会有一个boxy.css文件和jquery.boxy.js文件。在boxy.css文件中有给弹出框设置四个角图片的样式，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300719946.webp" alt="2010-12-08_232652" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;不做任何修改在Chrome浏览器下没有问题，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300719056.webp" alt="2010-12-08_234216" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在网上查了一些资料，说将css文件中的图片路径给位全路径可以解决问题，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300719018.webp" alt="2010-12-08_234934" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;发现这样修改后并没有作用，运行后效果仍然如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300720107.webp" alt="2010-12-08_235049" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;有效的解决方法&lt;/p&gt;
&lt;p&gt;将上面css截图的下半部分注释掉，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2010/2010-12-08_235357.webp" alt="2010-12-08_235357" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;然后在jquery.boxy.js文件中的Boxy函数中添加一段脚本，下面贴出修改后的Boxy函数代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;function Boxy(element, options) {

 this.boxy = jQuery(Boxy.WRAPPER);
 jQuery.data(this.boxy[0], &amp;#39;boxy&amp;#39;, this);

 this.visible = false;
 this.options = jQuery.extend({}, Boxy.DEFAULTS, options || {});

 if (this.options.modal) {
 this.options = jQuery.extend(this.options, {center: true, draggable: false});
 }

 // options.actuator == DOM element that opened this boxy
 // association will be automatically deleted when this boxy is remove()d
 if (this.options.actuator) {
 jQuery.data(this.options.actuator, &amp;#39;active.boxy&amp;#39;, this);
 }

 this.setContent(element || &amp;#34;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;#34;);
 this._setupTitleBar();

 this.boxy.css(&amp;#39;display&amp;#39;, &amp;#39;none&amp;#39;).appendTo(document.body);
 this.toTop();

 if (this.options.fixed) {
 if (jQuery.browser.msie &amp;amp;&amp;amp; jQuery.browser.version &amp;lt; 7) {
 this.options.fixed = false; // IE6 doesn&amp;#39;t support fixed positioning
 } else {
 this.boxy.addClass(&amp;#39;fixed&amp;#39;);
 }
 }

 if (this.options.center &amp;amp;&amp;amp; Boxy._u(this.options.x, this.options.y)) {
 this.center();
 } else {
 this.moveTo(
 Boxy._u(this.options.x) ? this.options.x : Boxy.DEFAULT_X,
 Boxy._u(this.options.y) ? this.options.y : Boxy.DEFAULT_Y
 );
 }

 //fengwei add 2010-11-28
 //用于解决弹出框的圆角在ie中的显示问题
 if ($.browser.msie) {
 var setFilter = function(cls) {
 var obj = $(cls), ret = obj.css(&amp;#34;background-image&amp;#34;).match(/url\(\&amp;#34;(.+)\&amp;#34;\)/);
 if (ret == null || ret.length &amp;lt; 1) return;
 obj.css({
 &amp;#34;background&amp;#34;: &amp;#34;none&amp;#34;, &amp;#34;filter&amp;#34;: &amp;#34;alpha(opacity=0)&amp;#34;,
 &amp;#34;filter&amp;#34;: &amp;#34;progid:DXImageTransform.Microsoft.
 AlphaImageLoader(src=&amp;#39;&amp;#34; + ret[1] + &amp;#34;&amp;#39;)&amp;#34;
 });
 };

 setFilter(&amp;#34;.top-left&amp;#34;);
 setFilter(&amp;#34;.top-right&amp;#34;);
 setFilter(&amp;#34;.bottom-left&amp;#34;);
 setFilter(&amp;#34;.bottom-right&amp;#34;);
 }
 if (this.options.show) this.show();
};
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;修改好css和js文件后，再次运行程序，在IE6,7,8中均能正常弹出带边角的框了。&lt;/p&gt;</description></item><item><title>jQuery boxy插件的确认框在AspNet中的应用</title><link>https://fwhyy.com/2010/11/use-jquery-boxy-plug-in-confirmation-box-in-the-aspnet/</link><pubDate>Sat, 20 Nov 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/11/use-jquery-boxy-plug-in-confirmation-box-in-the-aspnet/</guid><description>&lt;p&gt;jQuery有不少弹出框的插件，boxy应该算的上是功能和效果都还不错的一款了。先来看一张效果图吧。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290715574.webp" alt="2010-11-20_134247" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在Web开发中经常会使用到Alert和Confirm弹出框，在Asp.Net中的删除按钮上我们常常会加上删除的确认提示，以避免误删除数据，就像上面图片那样。我们一般会写出这样的代码。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;html xmlns=&amp;#34;http://www.w3.org/1999/xhtml&amp;#34; &amp;gt;
&amp;lt;head runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;
 &amp;lt;script type=&amp;#34;text/javascript&amp;#34;&amp;gt;
 function confirmDel() {
 return confirm(&amp;#34;您确认要删除吗？&amp;#34;);
 }
 &amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
 &amp;lt;form id=&amp;#34;form1&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;asp:Button ID=&amp;#34;btnDel&amp;#34; runat=&amp;#34;server&amp;#34; 
 OnClientClick=&amp;#34;return confirmDel();&amp;#34; Text=&amp;#34;删除&amp;#34; /&amp;gt;
 &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码很简单，confirm弹出框会有两个按钮，点击确定返回true，点击取消返回false。在boxy插件中也有confirm方法，调用代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$(document).ready(function() {
 $(&amp;#34;#btnDel&amp;#34;).click(function() {
 Boxy.confirm(&amp;#34;您确认要删除吗？&amp;#34;, function() { }, null);
 return false;
 });
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Boxy的confirm方法有三个参数分别是确认信息内容，弹出框点击确定的回调函数，一些设置项比如标题。上面的代码中如果不加上return false，那么弹出框会闪现，然后删除按钮的后天事件还是执行了。加上return false，那么不管是点击确定还是取消都不会执行后台事件，这显然达不到我们的要求，看来只能打点击确定后的回调函数的主意了。可以在一个公用的js文件中将Boxy的confirm封装一下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290716976.webp" alt="2010-11-20_140830" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;页面的调用代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$(document).ready(function() {
 $(&amp;#34;#Button1&amp;#34;).click(function() { return confirmO(this, &amp;#34;您确认删除吗？&amp;#34;) });

});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;经过这样修改后，但点击弹出框的确定按钮时就会执行服务器事件了。&lt;/p&gt;</description></item><item><title>给PDF文档添加书签</title><link>https://fwhyy.com/2010/11/add-a-bookmark-to-a-pdf-document/</link><pubDate>Sat, 20 Nov 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/11/add-a-bookmark-to-a-pdf-document/</guid><description>&lt;p&gt;我们在阅读纸质的书时，一般都会使用书签来标识看到什么地方以便下次看时可以方便的找到。如果是在电脑上阅读PDF文档，我们同样希望能够给PDF文档做些标记，不过默认情况下PDF是不支持标记的。下面就来介绍一种方法可以在PDF文档中添加书签。&lt;/p&gt;</description></item><item><title>C#:友元程序集</title><link>https://fwhyy.com/2010/11/csharp-a-friend-assembly/</link><pubDate>Mon, 15 Nov 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/11/csharp-a-friend-assembly/</guid><description>&lt;p&gt;C#中的访问修饰符Internal可以说是介于Public和Private之间，可以使类型在同程序集中可以被互相访问。但有时会有这样的需求，我们希望一个程序集中的类型可以被外部的某些程序集可以访问，这时当然不能设置成Public，否则可以被所有的外部程序集访问。要达到上述要求我们可以使用友元程序集。&lt;/p&gt;
&lt;p&gt;下面用一个简单的例子来介绍下友元程序集。&lt;/p&gt;
&lt;p&gt;1 在一个解决方案中创建两个类库项目TestA和TestB，分别在两个类库项目中创建类A和类B。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290807599.webp" alt="2010-11-14_175103" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 在项目TestA中添加对项目TestB的引用。&lt;/p&gt;
&lt;p&gt;3 将项目TestB中的类B访问级别设置为Internal。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;namespace TestB
{
 internal class B
 {

 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;4 现在在TestA项目的类A中是肯定不能访问到类B的，如果想让类A可以访问类B，必须将项目TestA的程序集添加为项目TestB程序集的友元程序集。添加友元程序集我们要使用InternalIsVisibleTo特性，使用该特性需要添加命名空间&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;using System.Runtime.CompilerServices。
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5 在B类中使用InternalIsVisibleTo特性将程序集TestA添加为友元程序集。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo(&amp;#34;TestA&amp;#34;)]
namespace TestB
{
 internal class B
 {

 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;6 InternalIsVisibleTo特性也可以添加到AssemblyInfo.cs中。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290808640.webp" alt="2010-11-14_181114" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;7 现在在项目TestA的类A中就可以访问TestB项目的类B了。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290808258.webp" alt="2010-11-14_181324" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>让 ASP.NET Menu 控件在 Google Chrome 浏览器上正常运行</title><link>https://fwhyy.com/2010/11/let-the-aspnet-menu-controls-on-the-google-chrome-browser-run-normally/</link><pubDate>Thu, 11 Nov 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/11/let-the-aspnet-menu-controls-on-the-google-chrome-browser-run-normally/</guid><description>&lt;p&gt;最近在帮朋友做一管理系统，里面用到了Asp.Net的Menu控件，由于我的Chrome浏览器为默认，运行后发现二级菜单不能正常出来，网上查到解决方法是在项目中创建一个Others.browser文件，文件代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;browsers&amp;gt;
 &amp;lt;browser id=&amp;#34;Safari3&amp;#34; parentID=&amp;#34;Safari1Plus&amp;#34;&amp;gt;
 &amp;lt;identification&amp;gt;
 &amp;lt;userAgent match=&amp;#34;Safari/\d+\.\d+&amp;#34; /&amp;gt;
 &amp;lt;/identification&amp;gt;
 &amp;lt;capture&amp;gt;
 &amp;lt;userAgent match=&amp;#34;Version/(?&amp;#39;version&amp;#39;\d+\.\d+)&amp;#34; /&amp;gt;
 &amp;lt;/capture&amp;gt;
 &amp;lt;capabilities&amp;gt;
 &amp;lt;capability name=&amp;#34;browser&amp;#34; value=&amp;#34;Safari3&amp;#34; /&amp;gt;
 &amp;lt;capability name=&amp;#34;version&amp;#34; value=&amp;#34;${version}&amp;#34; /&amp;gt;
 &amp;lt;/capabilities&amp;gt;
 &amp;lt;controlAdapters&amp;gt;
 &amp;lt;adapter controlType=&amp;#34;System.Web.UI.WebControls.Menu&amp;#34;
 adapterType=&amp;#34;&amp;#34; /&amp;gt;
 &amp;lt;/controlAdapters&amp;gt;
 &amp;lt;/browser&amp;gt;
 &amp;lt;browser id=&amp;#34;GoogleChrome&amp;#34; parentID=&amp;#34;Safari3&amp;#34;&amp;gt;
 &amp;lt;identification&amp;gt;
 &amp;lt;userAgent match=&amp;#34;Chrome/(?&amp;#39;version&amp;#39;\d+\.\d+)&amp;#34; /&amp;gt;
 &amp;lt;/identification&amp;gt;
 &amp;lt;capabilities&amp;gt;
 &amp;lt;capability name=&amp;#34;browser&amp;#34; value=&amp;#34;Googlebot&amp;#34; /&amp;gt;
 &amp;lt;/capabilities&amp;gt;
 &amp;lt;/browser&amp;gt;
&amp;lt;/browsers&amp;gt;
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>C#/Net代码精简优化技巧（3）</title><link>https://fwhyy.com/2010/11/csharp-net-code-concise-optimization-techniques-c/</link><pubDate>Wed, 10 Nov 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/11/csharp-net-code-concise-optimization-techniques-c/</guid><description>&lt;p&gt;前面两篇中已经介绍了10个小技巧，本篇是本次系列的最后一篇，将再介绍5个。这些小技巧看着并不起眼，有些您可能知道，但在平时的开发中可能由于惯性并没有去使用。所以建议大家掌握并去使用这些小技巧，他们将使我们的代码变得更简洁和易于维护。&lt;/p&gt;
&lt;h2 id="隐式类型"&gt;隐式类型&lt;/h2&gt;
&lt;p&gt;首先了解一下概念，隐式类型并不是动态类型，隐式类型是用关键字var来定义，var定义的类型仍然是强类型。&lt;/p&gt;
&lt;p&gt;很多人认为使用隐式类型是懒惰的表现，刚开始我也是这么认为的，但是想想我使用STL中迭代指针的开发经理，我就明白了。看下面代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;for (list&amp;lt;int&amp;gt;::const_iterator it = myList.begin(); it != myList.end(); ++it)
{
 // ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;很多时候我们会写出下面这样的代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;// pretty obvious
ActiveOrdersDataAccessObject obj = new ActiveOrdersDataAccessObject();

// still obvious but even more typing
Dictionary&amp;lt;string,List&amp;lt;Product&amp;gt;&amp;gt; productsByCategory =
 new Dictionary&amp;lt;string,List&amp;lt;Product&amp;gt;&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码的类型定义很明显，是什么类型就用什么类型来定义，下面尝试用var关键字来定义&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;// nicer!
var obj = new ActiveOrdersDataAccessObject();
// Ah, so much nicer!
var productsByCategory = new Dictionary&amp;lt;string,List&amp;lt;Product&amp;gt;&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;用var关键字后代码变得简洁多了，编译器会在编译时去推断是什么类型，var关键字只相当于是一个占位符。&lt;/p&gt;
&lt;p&gt;而且使用var关键字在我们使用泛型或是Linq表达式时会提供更好的可读性，比较下面两行代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;// 隐式类型
var results1 = from p in products where p.Value &amp;gt; 100 group p by p.Category;

// 显示类型
IEnumerable&amp;lt;IGrouping&amp;lt;string, Product&amp;gt;&amp;gt; results2 =
 from p in products where p.Value &amp;gt; 100 group p by p.Category;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="linq-扩展方法"&gt;Linq 扩展方法&lt;/h2&gt;
&lt;p&gt;在以前的编码中，很多时候我们需要去写一些自己的函数库，如排序、分组、查找或是其他的一些算法。并且我们要花很多的时间来为这些函数写单元测试，很多时候困扰我们的一些bug正是在这些方法中出现的。&lt;/p&gt;
&lt;p&gt;随着Linq扩展方法的推出，你可以使用现成的这些标准的算法，而不需要自己再去写一遍，提供了极大的方便。需要排序可以使用OrderBy()，当需要查询条件时可以使用Where()，当需要选择一些类的属性时可以使用Select()，当需要分组查询时可以使用GroupBy()，这些Linq中的扩展方法经过了全面的测试，不需要我们来为他写单元测试代码，也不会出现让人困扰的bug。&lt;/p&gt;
&lt;p&gt;看下面的例子，假设有一个集合List&lt;Product&gt;，集合里装载的是Product对象，Product有Value和Category两个属性，现在要按类别来查找Value值大于$100的数据，以前我们可能会像下面这样写&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;var results = new Dictionary&amp;lt;string, List&amp;lt;Product&amp;gt;&amp;gt;();

foreach (var p in products)
{
 if (p.Value &amp;gt; 100)
 {
 List&amp;lt;Product&amp;gt; productsByGroup;
 if (!results.TryGetValue(p.Category, out productsByGroup))
 {
 productsByGroup = new List&amp;lt;Product&amp;gt;();
 results.Add(p.Category, productsByGroup);
 }

 productsByGroup.Add(p);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;使用Linq扩展方法&lt;/p&gt;</description></item><item><title>C#/Net代码精简优化技巧（2）</title><link>https://fwhyy.com/2010/10/csharp-net-code-concise-optimization-techniques-2/</link><pubDate>Tue, 26 Oct 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/10/csharp-net-code-concise-optimization-techniques-2/</guid><description>&lt;p&gt;在&lt;a href="http://blog.fwhyy.com/2010/10/csharp-net-code-concise-optimization-techniques-1/"&gt;C#/Net代码精简优化技巧（1）&lt;/a&gt;中已经介绍了5个小技巧，本篇将再介绍5个。&lt;/p&gt;
&lt;h2 id="stringisnullorempty-and-stringisnullorwhitespace"&gt;string.IsNullOrEmpty() and string.IsNullOrWhiteSpace()&lt;/h2&gt;
&lt;p&gt;在Net2.0中String类型有一个静态方法IsNullOrEmpty，到了Net4.0中String类又增加了一个新的静态方法IsNullOrWhiteSpace。这两个方法看名称也可以知道IsNullOrEmpty是判断空引用和空字符串，而IsNullOrWhiteSpace是判断空引用和字符串中的每一个字符是否是空格。&lt;/p&gt;
&lt;p&gt;在有这两个方法之前，我们要进行这样的判断，需要些如下代码&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;GetFileName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;fullPathFileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullPathFileName&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;fullPathFileName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullPathFileName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;使用IsNullOrEmpty&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;GetFileName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;fullPathFileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullPathFileName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullPathFileName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;下面又了新的需求，需要将三个名字连接在一起，并且希望中间名字不为空字符串和不出现多余的空格，我们会写出下面的代码&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;GetFullName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;middleName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;middleName&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;middleName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{0} {1}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{0} {1} {2}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;middleName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上面的代码中使用了Trim来去掉空格然后判断其长度是否为0，代码也非常的清晰简洁，但是会产生额外的String对象以至于影响性能，这时就应该使用Net4.0中的IsNullOrWhiteSpace方法&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;GetFullName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;middleName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsNullOrWhiteSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;middleName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{0} {1}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{0} {1} {2}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;middleName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上面的代码非常简洁，而且也不用担心会产生额外的String对象没有及时的进行垃圾回收而影响性能。&lt;/p&gt;
&lt;h2 id="stringequals"&gt;string.Equals()&lt;/h2&gt;
&lt;p&gt;string.Equals方法有很多的重载供我们使用，但是其中有些常常会被我们忽视掉。通常我们比较字符串会使用下面的方法&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;CreateOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;orderType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;equity&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果orderType为null会抛出NullReferenceException异常，所以为了不抛出异常，在判断之前先要进行null的判断，如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orderType&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;orderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;equity&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;相当于每次都要做两次判断，很麻烦而且有时还有可能遗忘，如果使用string.Equals就可以解决这个问题，代码如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orderType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;equity&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上面的代码当orderType为null时不会抛出异常而是直接返回false。&lt;/p&gt;</description></item><item><title>C#/Net代码精简优化技巧（1）</title><link>https://fwhyy.com/2010/10/csharp-net-code-concise-optimization-techniques-1/</link><pubDate>Thu, 21 Oct 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/10/csharp-net-code-concise-optimization-techniques-1/</guid><description>&lt;p&gt;在我们写代码的时候可以使用一些小的技巧来使代码变得更加简洁，易于维护和高效。下面介绍几种在C#/Net中非常有用的一些编程技巧。&lt;/p&gt;
&lt;h2 id="空操作符"&gt;空操作符（??）&lt;/h2&gt;
&lt;p&gt;在程序中经常会遇到对字符串或是对象判断null的操作，如果为null则给空值或是一个指定的值。通常我们会这样来处理&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;string name = value;
if (name == null)
{
 name = string.Empty;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;可以使用三元操作符（?:）对上面对吗进行优化&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;string name = value == null ? string.Empty : value;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这样使代码简洁了不少，但这还不是最简洁的，我们还可以使用??操作符来进行进一步优化，??操作符意思是如果为null取操作符左边的值，否则取右边的值。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;string name = value ?? string.Empty;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;我们甚至可以写一个扩展方法来过滤掉null和空格，使返回的结果可以更好的使用??操作符&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public static class StringUtility
{
 public static string TrimToNull(string source)
 {
 return string.IsNullOrWhiteSpace(source) ? null : source.Trim();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;使用代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;string name = string.TrimToNull(value) ?? &amp;#34;None Specified&amp;#34;;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="使用as转换类型"&gt;使用As转换类型&lt;/h2&gt;
&lt;p&gt;在C#中进行类型转换有很多种方式比如可以进行强制类型转换，通常在转换前会使用Is进行类型的判断，所以您可能经常写过或见过类似下面的代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;if (employee is SalariedEmployee)
{
 var salEmp = (SalariedEmployee)employee;
 pay = salEmp.WeeklySalary;
 // ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码不会报异常，但在整个过程中做了两次转换操作，这样会降低性能。我们可以使用as操作符来进行类型的转换，同样也不会报异常，如果类型不兼容则返回null，而是用as进行转换整个过程只转换一次。代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;var salEmployee = employee as SalariedEmployee;
if (salEmployee != null)
{
 pay = salEmployee.WeeklySalary;
 // ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="自动属性"&gt;自动属性&lt;/h2&gt;
&lt;p&gt;自动属性是C#3.0以上版本中的新功能，可以使代码变得更简洁，在以前定义属性我们会写如下代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Point
{
 private int _x, _y;

 public int X
 {
 get { return _x; }
 set { _x = value; }
 }
 public int Y
 {
 get { return _y; }
 set { _y = value; }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;使用自动属性代码就会简洁了很多&lt;/p&gt;</description></item><item><title>Virtual PC附加程序安装</title><link>https://fwhyy.com/2010/09/additional-program-installed-virtual-pc/</link><pubDate>Thu, 23 Sep 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/09/additional-program-installed-virtual-pc/</guid><description>&lt;p&gt;在Virtual PC中安装好了虚机后，要想让虚拟机能够和物理机实现文件共享就必须安装附加程序。下面介绍附加程序的安装方法。&lt;/p&gt;</description></item><item><title>推荐两款富文本编辑器：NicEdit和Kindeditor</title><link>https://fwhyy.com/2010/09/nicedit-and-kindeditor/</link><pubDate>Sun, 05 Sep 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/09/nicedit-and-kindeditor/</guid><description>&lt;p&gt;做过Web开发的朋友相信都使用过富文本编辑器，比较出名的&lt;a href="http://cuteeditor.51aspx.com/"&gt;CuteEditor&lt;/a&gt;和&lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;很多人应该已经使用过，在功能强大的同时需要加载的东西也变得很多。下面要推荐的两款富文本编辑器都是使用JS编写，使用简单，非常轻量级。&lt;/p&gt;
&lt;h2 id="niceditor"&gt;NicEditor&lt;/h2&gt;
&lt;p&gt;NicEdit是一个轻量级，跨平台的Inline Content Editor。NicEdit能够让任何 element/div变成可编辑或者能够把标准的TextArea转换成富文本编辑器。&lt;/p&gt;
&lt;p&gt;主页:&lt;a href="http://nicedit.com/"&gt;http://nicedit.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;下载:&lt;a href="http://nicedit.com/download.php"&gt;http://nicedit.com/download.php&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;示例:&lt;a href="http://nicedit.com/demos.php"&gt;http://nicedit.com/demos.php&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;NicEdit是我见过最轻量级的富文本编辑器，总共就一个JS文件和一张图片&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301603918.webp" alt="2010-09-05_102850" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;使用也非常简单，只需在页面中添加简单的JS代码就可以将TextBox或是TextArea控件转换成富文本编辑器，代码如下&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;head runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;title&amp;gt;title&amp;gt;
head&amp;gt;
&amp;lt;body&amp;gt;
 &amp;lt;form id=&amp;#34;form1&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;script src=&amp;#34;../JS/Eidtor/nicEdit.js&amp;#34; type=&amp;#34;text/javascript&amp;#34;&amp;gt;script&amp;gt;
 &amp;lt;script type=&amp;#34;text/javascript&amp;#34;&amp;gt;
 bkLib.onDomLoaded(function() {
 new nicEditor({ fullPanel: true }).panelInstance(&amp;#39;txtContent&amp;#39;);
 });
 script&amp;gt;
 &amp;lt;asp:TextBox runat=&amp;#34;server&amp;#34; ID=&amp;#34;txtContent&amp;#34;
 TextMode=&amp;#34;MultiLine&amp;#34; Height=&amp;#34;200px&amp;#34; Width=&amp;#34;600px&amp;#34; &amp;gt;asp:TextBox&amp;gt;
 &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;运行效果如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301603551.webp" alt="2010-09-05_104825" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;官网中的版本为英文版，而且字体设置也只能设置英文字体，我对英文版本做了简单的汉化，并且增加了几种中文字体，如下图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301604995.webp" alt="2010-09-05_104528" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://files.cnblogs.com/oec2003/NICEidtor.rar"&gt;中文本下载&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="kindeditor"&gt;KindEditor&lt;/h2&gt;
&lt;p&gt;KindEditor是一套开源的HTML可视化编辑器，主要用于让用户在网站上获得所见即所得编辑效果，兼容IE、Firefox、Chrome、Safari、Opera等主流浏览器。 KindEditor使用JavaScript编写，可以无缝的与Java、.NET、PHP、ASP等程序接合。这个是官网上的介绍。&lt;/p&gt;
&lt;p&gt;主页：&lt;a href="http://www.kindsoft.net/index.php"&gt;http://www.kindsoft.net/index.php&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;下载：&lt;a href="http://www.kindsoft.net/down.php"&gt;http://www.kindsoft.net/down.php&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;示例：&lt;a href="http://www.kindsoft.net/demo.php"&gt;http://www.kindsoft.net/demo.php&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;KindEditor相比较NicEditor涉及的文件要多很多，不过大小也才几百K而已，下图为文件结构&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301604810.webp" alt="2010-09-05_102941" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;使用代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;html xmlns=&amp;#34;http://www.w3.org/1999/xhtml&amp;#34;&amp;gt;
&amp;lt;head runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;title&amp;gt;title&amp;gt;
head&amp;gt;
&amp;lt;body&amp;gt;
 &amp;lt;form id=&amp;#34;form1&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;script charset=&amp;#34;utf-8&amp;#34; src=&amp;#34;../JS/KindEditor/kindeditor-min.js&amp;#34; 
 type=&amp;#34;text/javascript&amp;#34;&amp;gt;script&amp;gt;
 &amp;lt;script type=&amp;#34;text/javascript&amp;#34; charset=&amp;#34;utf-8&amp;#34;&amp;gt;
 KE.show({
 id: &amp;#39;txtContent&amp;#39;,
 resizeMode: 1,
 allowPreviewEmoticons: false,
 allowUpload: false,
 });
 script&amp;gt;
 &amp;lt;textarea cols=&amp;#34;60&amp;#34; id=&amp;#34;txtContent&amp;#34; style=&amp;#34;width: 600px; height: 300px;&amp;#34; runat=&amp;#34;server&amp;#34;
 readonly=&amp;#34;readonly&amp;#34;&amp;gt;textarea&amp;gt;
 &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;运行效果如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301604578.webp" alt="2010-09-05_110505" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>WCF中绑定的简单介绍</title><link>https://fwhyy.com/2010/08/the-simple-introduction-of-the-wcf-binding/</link><pubDate>Sun, 29 Aug 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/08/the-simple-introduction-of-the-wcf-binding/</guid><description>&lt;h2 id="绑定基本概念"&gt;绑定基本概念&lt;/h2&gt;
&lt;p&gt;绑定就是一个从通用基础类型派生出来的运行时类型。绑定中描述了传输协议，消息编码格式和其他的一些用于通信的通信协议。&lt;/p&gt;
&lt;h2 id="绑定的种类介绍"&gt;绑定的种类介绍&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302117082.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="两种方式来配置端点以及相关联的绑定"&gt;两种方式来配置端点以及相关联的绑定&lt;/h2&gt;
&lt;p&gt;绑定的配置可以使用配置文件的形式或是代码的形式，如下面的代码：&lt;/p&gt;
&lt;p&gt;配置文件形式(服务端)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;endpoint address=&amp;#34;HelloWorld&amp;#34; binding=&amp;#34;basicHttpBinding&amp;#34;
 contract=&amp;#34;Service.IHelloWorldService&amp;#34;&amp;gt;&amp;lt;/endpoint&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;配置文件形式(客户端)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;endpoint address=&amp;#34;http://localhost:10000/HelloWorld&amp;#34; binding=&amp;#34;basicHttpBinding&amp;#34;
 bindingConfiguration=&amp;#34;BasicHttpBinding_oec2003&amp;#34; contract=&amp;#34;HelloWorld.oec2003&amp;#34;
 name=&amp;#34;BasicHttpBinding_oec2003&amp;#34; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;代码形式&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;WSHttpBinding wsHttpBinding = new WSHttpBinding();
wsHttpBinding.Security.Mode = SecurityMode.Transport;
wsHttpBinding.ReliableSession.Enabled = true;
wsHttpBinding.TransactionFlow = true;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="绑定的功能"&gt;绑定的功能&lt;/h2&gt;
&lt;p&gt;每个绑定都必要要提供至少一个传输协议，一个消息编码格式和一个相关的消息版本，除此之外还有一些其他的功能，如安全性、双向通信、事务等。&lt;/p&gt;
&lt;p&gt;传输协议：有Http、Https、Tcp、命名管线和MSMQ，这些都有专门的绑定类型与之对应。&lt;/p&gt;
&lt;p&gt;消息编码：描述了消息是如何格式化的，可以使用Binary、Text或Mtom。&lt;/p&gt;
&lt;p&gt;消息版本：不管消息的编码格式如何，消息总是表示为SOAP1.1或是SOAP1.2.&lt;/p&gt;
&lt;p&gt;传输安全性：指在线传输证书、签名和加密的能力。一般使用SSL。&lt;/p&gt;
&lt;p&gt;消息安全性：指独立于传输层的传输证书、签名和加密的能力。&lt;/p&gt;
&lt;p&gt;双向通信：TCP和命名管线可以直接支持，但Http不支持。&lt;/p&gt;
&lt;p&gt;这些绑定的功能都是通过配置绑定元素来进行激活看，下面就简单介绍下绑定元素。&lt;/p&gt;
&lt;p&gt;每一种绑定都会有一个绑定元素的集合，像前面提到的传输协议、编码格式等都是绑定元素的一种。绑定元素在Net对应的类型都是继承自BindingElement类。在WCF中的每一种绑定必须有一个传输协议和一个消息编码格式。传输协议的通用绑定元素为TransportBindingElement，有下面一些子类继承TransportBindingElement，分别代表不同类型的传输协议。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HttpTransportBindingElement&lt;/li&gt;
&lt;li&gt;HttpsTransportBindingElement&lt;/li&gt;
&lt;li&gt;MsmqTransportBindingElement&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;编码格式通用绑定元素为MessageEncodingBindingElement，一些子类如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;BinaryMessageEncodingBindingElement&lt;/li&gt;
&lt;li&gt;TextMessageEncodingBindingElement&lt;/li&gt;
&lt;li&gt;MtomMessageEncodingBindingElement&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;还有一些其他的不是必须但是在一些特定场合特别有用的绑定元素：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;安全相关：SecurityBindingElement&lt;/li&gt;
&lt;li&gt;混合双向通信：CompositeDuplexBindingElement OneWayBindingElement&lt;/li&gt;
&lt;li&gt;可靠通信：ReliableSessionBindingElement&lt;/li&gt;
&lt;li&gt;事务：TransactionFlowBindingElement&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用上面的绑定元素必须引用命名空间System.ServiceModel.Channels&lt;/p&gt;
&lt;p&gt;在WCF中使用绑定通常会在配置文件中来进行，尽管也可以用代码的方式实现，但在配置文件中更加灵活。可以在端点的bindingConfiguration来进行扩展。看下面代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;system.serviceModel&amp;gt;
 &amp;lt;services&amp;gt;
 &amp;lt;service name=&amp;#34;Service.HelloWorldService&amp;#34; behaviorConfiguration=&amp;#34;HelloWorldBebavior&amp;#34;&amp;gt;
 &amp;lt;endpoint address=&amp;#34;HelloWorld&amp;#34; binding=&amp;#34;basicHttpBinding&amp;#34;
 bindingConfiguration=&amp;#34;baseBinding_oec2003&amp;#34;
 contract=&amp;#34;Service.IHelloWorldService&amp;#34;&amp;gt;&amp;lt;/endpoint&amp;gt;
 &amp;lt;endpoint address=&amp;#34;mex&amp;#34; binding=&amp;#34;mexHttpBinding&amp;#34; contract=&amp;#34;IMetadataExchange&amp;#34; /&amp;gt;
 &amp;lt;host&amp;gt;
 &amp;lt;baseAddresses&amp;gt;
 &amp;lt;add baseAddress=&amp;#34;http://localhost:10000/&amp;#34;/&amp;gt;
 &amp;lt;/baseAddresses&amp;gt;
 &amp;lt;/host&amp;gt;
 &amp;lt;/service&amp;gt;
 &amp;lt;/services&amp;gt;
 &amp;lt;bindings&amp;gt;
 &amp;lt;basicHttpBinding&amp;gt;
 &amp;lt;binding name=&amp;#34;baseBinding_oec2003&amp;#34; maxReceivedMessageSize=&amp;#34;10000&amp;#34;
 transferMode=&amp;#34;Buffered&amp;#34;&amp;gt;
 &amp;lt;security mode=&amp;#34;Transport&amp;#34;&amp;gt;&amp;lt;/security&amp;gt;
 &amp;lt;/binding&amp;gt;
 &amp;lt;/basicHttpBinding&amp;gt;
 &amp;lt;/bindings&amp;gt;
 &amp;lt;behaviors&amp;gt;
 &amp;lt;serviceBehaviors&amp;gt;
 &amp;lt;behavior name=&amp;#34;HelloWorldBebavior&amp;#34;&amp;gt;
 &amp;lt;serviceMetadata httpGetEnabled=&amp;#34;true&amp;#34; /&amp;gt;
 &amp;lt;/behavior&amp;gt;
 &amp;lt;/serviceBehaviors&amp;gt;
 &amp;lt;/behaviors&amp;gt;
&amp;lt;/system.serviceModel&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;本文只是简单介绍了下绑定的概念以及绑定的种类，以及使用了一些代码来说明绑定的运用，关于每种绑定的详细介绍及用法在后面的博文中介绍。&lt;/p&gt;</description></item><item><title>关于LoadRunner的一点资料</title><link>https://fwhyy.com/2010/08/a-little-information-about-loadrunner/</link><pubDate>Tue, 24 Aug 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/08/a-little-information-about-loadrunner/</guid><description>&lt;p&gt;LoadRunner是一款很强大的测试工具，前不久有过一段时间的使用经历，并且写了篇文章加以介绍&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/oec2003/archive/2010/05/21/1740625.html"&gt;使用LoadRunner测试WMS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在使用LoadRunner期间也积累的一些资料，下面给出下载地址与大家分享:&lt;/p&gt;</description></item><item><title>WebService生成客户端代理的工具WSDL参数介绍</title><link>https://fwhyy.com/2010/08/webservice-to-generate-the-client-proxy-tool-wsdl-parameters-is-introduced/</link><pubDate>Tue, 10 Aug 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/08/webservice-to-generate-the-client-proxy-tool-wsdl-parameters-is-introduced/</guid><description>&lt;h2 id="wsdlexe"&gt;wsdl.exe&lt;/h2&gt;
&lt;p&gt;使用 ASP.NET，根据 WSDL 协定文件、XSD 架构和 .disc 发现文档，为 Xml Web Services 客户端和 Xml Web Ser 代码的实用工具。此工具可以与 disco.exe 一起使用。&lt;/p&gt;
&lt;p&gt;wsdl.exe &amp;lt;选项&amp;gt; &amp;lt;URL 或路径&amp;gt; &amp;lt;URL 或路径&amp;gt;&lt;/p&gt;
&lt;h2 id="选项"&gt;选项&lt;/h2&gt;
&lt;p&gt;&amp;lt;URL 或路径&amp;gt; –
指向 WSDL 协定、XSD 架构或 .discomap 文档的 URL 或 /nologo 取消显示版权标志。&lt;/p&gt;
&lt;p&gt;/language:&lt;language&gt;
用于生成的代理类的语言。请从“CS”、“VB”、“JS”、“CPP”中选择，或者为实现System.CodeDom.Compiler. 的类提供一个完全限定的名称。默认语言为“CS”(CShar )缩写形式为“/l:”。&lt;/p&gt;
&lt;p&gt;/sharetypes
打开类型共享功能。此功能针对不同服务之间共享 的相同类型(命名空间、名称和网络签名必须相同) 创建一个具有单一类型定义的代码文件。 请使用 http:// URLs 作为命令行参数来引用 服务，或为本地文件创建一个 discomap 文档。&lt;/p&gt;
&lt;p&gt;/verbose
指定 /sharetypes 开关时显示额外信息。 缩写形式为“/v”。&lt;/p&gt;
&lt;p&gt;/fields
生成字段而非属性。缩写形式为“/f”。&lt;/p&gt;
&lt;p&gt;/order
为粒子成员生成显式顺序标识符。&lt;/p&gt;
&lt;p&gt;/enableDataBinding
在所有生成的类型上实现 INotifyPropertyChanged 接口 以启用数据绑定。缩写形式为“/edb”。&lt;/p&gt;
&lt;p&gt;/namespace:&lt;namespace&gt;
生成的代理或模板的命名空间。默认命名空间 为全局命名空间。缩写形式为“/n:”。&lt;/p&gt;
&lt;p&gt;/out:&amp;lt;fileName|directoryPath&amp;gt;
生成的代理代码的文件名或目录路径。默认文件名是从 服务名派生的。缩写形式为“/o:”。&lt;/p&gt;
&lt;p&gt;/protocol:&lt;protocol&gt;
重写要实现的默认协议。请从“SOAP”、“SOAP12”、 “HttpGet”、“HttpPost”中选择。&lt;/p&gt;
&lt;p&gt;/username:&lt;username&gt;
/password:&lt;password&gt;
/domain:&lt;domain&gt;
连接到要求身份验证的服务器时使用的凭据。 缩写形式为“/u:”、“/p:”和“/d:”。&lt;/p&gt;
&lt;p&gt;/proxy:&lt;url&gt;
用来处理 HTTP 请求的代理服务器的 URL。 默认为使用系统代理服务器设置。&lt;/p&gt;
&lt;p&gt;/proxyusername:&lt;username&gt;
/proxypassword:&lt;password&gt;
/proxydomain:&lt;domain&gt;
连接到要求身份验证的代理服务器时使用的凭据。 缩写形式为“/pu:”、“/pp:”和“/pd:”。&lt;/p&gt;
&lt;p&gt;/appsettingurlkey:&lt;key&gt;
在代码生成中用来读取 URL 属性的 默认值的配置项。默认为不从配置 文件中读取。缩写形式为“/urlkey:”。&lt;/p&gt;
&lt;p&gt;/appsettingbaseurl:&lt;baseurl&gt;
计算 URL 段时使用的基 URL。 还必须指定 appsettingurlkey 选项。URL 段是 从 appsettingbaseurl 计算 WSDL 文档中的 URL 的相对 URL 的结果。&lt;/p&gt;</description></item><item><title>Net4.0—数据绑定控件（GridView ListView…）中的ClientIDRowSuffix属性</title><link>https://fwhyy.com/2010/07/net-4-data-bound-controls-the-clientidrowsuffix-properties/</link><pubDate>Fri, 30 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/net-4-data-bound-controls-the-clientidrowsuffix-properties/</guid><description>&lt;p&gt;在AspNet4中的数据绑定控件（GridView ListView…）中新增了一个ClientIDRowSuffix属性，ClientIDRowSuffix属性可以影响数据绑定控件内部控件的ID，ClientIDRowSuffix控件的值可以设置为数据绑定控件的数据源的任何一列。值得注意的是ClientIDRowSuffix属性是和ClientIDMode属性配合使用的。ClientIDMode有四种属性值，这个在&lt;a href="http://blog.fwhyy.com/?p=18"&gt;Net4.0—对HTML净化的处理&lt;/a&gt;一文中有提到，下面介绍如何在数据绑定控件中使用ClientIDRowSuffix：&lt;/p&gt;
&lt;p&gt;1 在页面中放一个GridView控件，在控件添加一个模板列，模板列中添加一个Lable控件，ID设置为lblId，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;asp:GridView ID=&amp;#34;GridView1&amp;#34; runat=&amp;#34;server&amp;#34;
 ClientIDRowSuffix=&amp;#34;UserId&amp;#34; ClientIDMode=&amp;#34;Predictable&amp;#34; &amp;gt;
 &amp;lt;Columns&amp;gt;
 &amp;lt;asp:TemplateField&amp;gt;
 &amp;lt;ItemTemplate&amp;gt;
 &amp;lt;asp:Label ID=&amp;#34;lblId&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;&amp;lt;/asp:Label&amp;gt;
 &amp;lt;/ItemTemplate&amp;gt;
 &amp;lt;/asp:TemplateField&amp;gt;
 &amp;lt;/Columns&amp;gt;
&amp;lt;/asp:GridView&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 进入后台代码视图，添加一个User类做数据源用，在PageLoad事件中绑定GridView，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public partial class WebForm1 : System.Web.UI.Page
{
 protected void Page_Load(object sender, EventArgs e)
 {
 List&amp;lt;User&amp;gt; list = new List&amp;lt;User&amp;gt;
 {
 new User{UserId=10,UserName=&amp;#34;oec2003&amp;#34;},
 new User{UserId=20,UserName=&amp;#34;oec2004&amp;#34;}
 };
 if (!Page.IsPostBack)
 {
 this.GridView1.DataSource = list;
 this.GridView1.DataBind();
 }
 }
}
public class User
{
 public int UserId { get; set; }
 public string UserName { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;3 设置GridView的属性ClientIDMode为不同值，运行程序查看源码，观察Lable控件的ID，如下图：&lt;/p&gt;
&lt;p&gt;AutoID&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300731399.webp" alt="2010-07-30_112500" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Inherit&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300731940.webp" alt="2010-07-30_112644" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Predictable&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300731460.webp" alt="2010-07-30_112747_thumb" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Static&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300732906.webp" alt="2010-07-30_112954" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;1 根据上图看以看出当ClientIDMode值为Predictable和Inherit时，ClientIDRowSuffix的设置才起了作用，将ClientIDRowSuffix设置的UserId字段的值拼接到了Lable控件的ID属性后。&lt;/li&gt;
&lt;li&gt;2 在网上的一些资料表明ClientIDRowSuffix属性要和ClientIDMode属性一起使用，并且ClientIDMode属性的值要设置成Predictable，但我将GridView中的ClientIDMode属性去掉后运行，看到的源码和设置ClientIDMode为Predictable得到的源码一致。也就是说只设置GrieView的ClientIDRowSuffix就可以得到想要的结果。&lt;/li&gt;
&lt;li&gt;3 ClientIDRowSuffix属性还可以设置对应多个字段，如ClientIDRowSuffix=”UserId,UserName”，这样得到的控件的ID是多个字段值的拼接。&lt;/li&gt;
&lt;li&gt;4 在AspNet4的数据绑定控件中，只有GridView和ListView有ClientIDRowSuffix属性。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Net4.0—AspNet中的控件HyperLink的改进（支持路由跳转）</title><link>https://fwhyy.com/2010/07/net-4-aspnet-controls-the-hyperlink-in-the-improvement/</link><pubDate>Wed, 28 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/net-4-aspnet-controls-the-hyperlink-in-the-improvement/</guid><description>&lt;p&gt;作过Web开发的人对HyperLink控件一定非常熟悉，在客户端生成的代码就是一个a标签。AspNet4中的Hyperlink控件相比以前的版本做了些改进，可以更好地支持URl重写，下面结合在&lt;a href="http://blog.fwhyy.com/?p=20"&gt;Net4.0—AspNet中URL重写的改进&lt;/a&gt;一文中的例子来讲解下Hyperlink这个新的功能。&lt;/p&gt;
&lt;p&gt;1 在项目中的Default.aspx页面中加入一个Hyperlink控件，在设计视图中右击该控件，选择属性，在属性窗口中选择Expresstions，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300729640.webp" alt="2010-07-27_172142" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 点击右边的三个小点点，在弹出的对话框中进行如下设置：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300729586.webp" alt="2010-07-27_172422" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;设置RouteName为productdetail，就是让该链接导向test.aspx页面，因为在Global.asax中设置名为productdetail的路由对应的物理文件时test.aspx。RouteValus就是配置参数项，此处的category和name也是在Global.asax中配置的。&lt;/p&gt;
&lt;p&gt;3 设置好后点击OK，切换到代码视图，可以看到代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;asp:HyperLink ID=&amp;#34;HyperLink1&amp;#34; runat=&amp;#34;server&amp;#34;
 NavigateUrl=&amp;#34;&amp;lt;%$ RouteUrl:RouteName=productdetail,category=computer,name=thinkpad %&amp;gt;&amp;#34;&amp;gt;
 Test Page&amp;lt;/asp:HyperLink&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;4 设置Default.aspx为起始页，按F5运行，点击链接Test Page链接，会跳转到test.aspx页面，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300729625.webp" alt="2010-07-27_173712" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>Net4.0—对HTML净化的处理</title><link>https://fwhyy.com/2010/07/net-4-purification-processing-of-html/</link><pubDate>Wed, 28 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/net-4-purification-processing-of-html/</guid><description>&lt;p&gt;在使用Asp.Net进行Web开发时我一直都很注重最终生成的HTML是否干净，所以我会使用Repeater取代GridView等控件，可控性好而且生成的HTML代码也非常干净。干净的HTML有很多好处，如代码相应较少加载速度快，便于控制页面元素等。在AspNet4中对HTML的净化做了很大的改进，下面的文字中会做一个简单的介绍。&lt;/p&gt;
&lt;h2 id="设置controlrenderingcompatibilityversion"&gt;设置controlRenderingCompatibilityVersion&lt;/h2&gt;
&lt;p&gt;controlRenderingCompatibilityVersion需要在Webconfig文件中设置，配置在Pages节点中，可以设置使用3.5还是4.0的引擎来渲染HTML，默认是使用4.0。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300730129.webp" alt="2010-07-28_143021" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在VS2010中创建一个AspNet项目，在项目中的site.master中会有一个Menu控件来显示导航，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;asp:Menu ID=&amp;#34;NavigationMenu&amp;#34; runat=&amp;#34;server&amp;#34; CssClass=&amp;#34;menu&amp;#34;
EnableViewState=&amp;#34;false&amp;#34; IncludeStyleBlock=&amp;#34;false&amp;#34; Orientation=&amp;#34;Horizontal&amp;#34;&amp;gt;
 &amp;lt;Items&amp;gt;
 &amp;lt;asp:MenuItem NavigateUrl=&amp;#34;~/Default.aspx&amp;#34; Text=&amp;#34;Home&amp;#34;/&amp;gt;
 &amp;lt;asp:MenuItem NavigateUrl=&amp;#34;~/About.aspx&amp;#34; Text=&amp;#34;About&amp;#34;/&amp;gt;
 &amp;lt;/Items&amp;gt;
&amp;lt;/asp:Menu&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;分别设置 controlRenderingCompatibilityVersion属性值为3.5和4.0，运行项目，看到页面源码的区别如下：&lt;/p&gt;
&lt;p&gt;4.0&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2010/2010-07-28_150119.webp" alt="2010-07-28_150119" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3.5&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300730347.webp" alt="2010-07-28_150528" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;可以看出使用4.0的引擎是将Menu控件生成的Ul 标签，而3.5中是生成的table，代码的复杂度明显大了很多。当然并不只是对Menu控件进行了优化，还有其他一些方面如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一些控件的内置样式被去掉，而是在页面中生成样式代码；&lt;/li&gt;
&lt;li&gt;模板控件中移除了外表表格渲染；&lt;/li&gt;
&lt;li&gt;向导类控件使用站位符控制层。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="使用clientidmode"&gt;使用ClientIDMode&lt;/h2&gt;
&lt;p&gt;在继承了masterpage页的页面中添加其他的服务器控件，最终呈现的HTML的的ID都会改变，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300731072.webp" alt="2010-07-28_152923" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;AspNet4中可以使用ClientIDMode来改变这一局面，ClientIDMode在页面的Page指令中设置，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;%@ Page Title=&amp;#34;&amp;#34; Language=&amp;#34;C#&amp;#34; MasterPageFile=&amp;#34;~/Site.Master&amp;#34; AutoEventWireup=&amp;#34;true&amp;#34;
CodeBehind=&amp;#34;test.aspx.cs&amp;#34; Inherits=&amp;#34;UrlRewriterDemo.test&amp;#34; ClientIDMode=&amp;#34;Static&amp;#34; %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;将ClientIDMode设置为Static后，刷新页面查看源代码，控件的ID变成本来面目了，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300731621.webp" alt="2010-07-28_154000" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;ClientIDMode有四个属性值：AutoID、Inherit、Predictable和Static，下面以上面的按钮为例，列出分别在这四种属性值下呈现的ID值：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AutoID：ctl00_MainContent_btnTest&lt;/li&gt;
&lt;li&gt;Inherit：MainContent_btnTest&lt;/li&gt;
&lt;li&gt;Predictable：MainContent_btnTest&lt;/li&gt;
&lt;li&gt;Static：btnTest&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="对viewstate更细致化的管理"&gt;对ViewState更细致化的管理&lt;/h2&gt;
&lt;p&gt;ViewState是让人又爱又恨的东西，控制不好会使页面变得非常庞大，在AspNet4中可以使用ViewStateMode对ViewState进行更细致化的管理。ViewStateMode可以在页面级设置也可以在控件级设置，有三个属性值：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Inherit：从父控件中继承；&lt;/li&gt;
&lt;li&gt;Enabled：当父控件的ViewState处于Disabled状态时可以设置当前控件ViewState可用；&lt;/li&gt;
&lt;li&gt;Disabled：当父控件的ViewState处于Enalbed状态时可以设置当前控件ViewState禁用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在以前的AspNet版本中有个EnableViewState属性可以来设置ViewState，不过ViewStateMode和EnableViewState还是有很大区别的：&lt;/p&gt;
&lt;h3 id="enableviewstate"&gt;EnableViewState&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;其值为布尔类型，决定其控件或是子控件是否开启ViewState；&lt;/li&gt;
&lt;li&gt;优先级别大于ViewStateMode，只要 EnableViewState设置为false，就算设置了ViewStateMode为Enabled，控件的ViewState还是关闭的；&lt;/li&gt;
&lt;li&gt;当设置父控件的EnableViewState为false后，其子控件的ViewState就都关闭了，不能在子控件中单独开启ViewState。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="viewstatemode"&gt;ViewStateMode&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;在父控件以及本身的EnableViewState设置为true时，才会起作用；&lt;/li&gt;
&lt;li&gt;子控件不受父控件ViewStateMode的影响；&lt;/li&gt;
&lt;li&gt;在父控件中设置ViewStateMode为Disabled后，可以在子控件中设置ViewStateMode为Enabled来开启子控件的ViewState。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Net4.0—AspNet中URL重写的改进</title><link>https://fwhyy.com/2010/07/net-4-aspnet-url-rewriting-in-the-improvement/</link><pubDate>Tue, 27 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/net-4-aspnet-url-rewriting-in-the-improvement/</guid><description>&lt;p&gt;URL重写有很多的好处，如有利于SEO、便于记忆、隐藏真实路径使安全性提高、便于更新等等。在AspNet4.0之前的版本中要实现URL重写比较复杂，有时还会借助第三方类库，而在AspNet4.0中可以很方面实现，下面就一步一步来讲解怎样在AspNet4.0中实现URL重写。&lt;/p&gt;
&lt;p&gt;1 打开VS2010，创建一个AspNet项目命名为UrlRewriterDemo。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300727900.webp" alt="2010-07-27_100812" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;可以看到AspNet4中的项目结构有点类似AspNet MVC ，加了很多现成的东西，只需稍加修改就可以变成一个简单的个人站点。&lt;/p&gt;
&lt;p&gt;2 打开Global.asax文件，引用命名空间System.Web.Routing，System.Web.Routing命名空间在Net3.5中就已经存在，不过功能没有4.0中的强大。在该文件中添加如下方法:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;void RegisterRoutes(RouteCollection routes)
{
 routes.MapPageRoute(&amp;#34;productdetail&amp;#34;,
 &amp;#34;products/{category}/{name}&amp;#34;,
 &amp;#34;~/test.aspx&amp;#34;, false,
 new RouteValueDictionary { { &amp;#34;category&amp;#34;, &amp;#34;book&amp;#34; }, { &amp;#34;name&amp;#34;, &amp;#34;aspnet&amp;#34; } });
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;MapPageRoute方法的参数解释：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“productdetail”：路由名称，取一个和当前路由设置相匹配的名称即可。&lt;/li&gt;
&lt;li&gt;“products/{category}/{name}”：URL的重写规则。&lt;/li&gt;
&lt;li&gt;“~/test.aspx”：配置对应的物理文件。&lt;/li&gt;
&lt;li&gt;new RouteValueDictionary { { “category”, “book” }, { “name”, “aspnet” } }：配置默认值。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;3 在Global.asax中的方法Application_Start中添加如下代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;void Application_Start(object sender, EventArgs e)
{
 RegisterRoutes(RouteTable.Routes);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;4 在项目中添加一个页面命名为test.aspx，如果命名为别的名称，在上面的MapPageRoute方法的配置物理文件的参数就应该设置为相应的名称。在test.aspx页面中添加如下内容：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;asp:Content ID=&amp;#34;Content2&amp;#34; ContentPlaceHolderID=&amp;#34;MainContent&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;h1&amp;gt;Url Rewriter Test Page!&amp;lt;/h1&amp;gt;
&amp;lt;/asp:Content&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5 将该项目设置为固定端口，比如10000，按F5运行项目，将URL地址修改为http://localhost:10000/products，此处的products为URL重写规则中配置的名称。运行结果如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300727307.webp" alt="2010-07-27_104717_thumb" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;6 我们在RegisterRoutes中配置了默认参数值category和name，如需要在页面中获取参数值，可以使用RouteData.Values，将test.aspx页面代码修改如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;asp:Content ID=&amp;#34;Content2&amp;#34; ContentPlaceHolderID=&amp;#34;MainContent&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;h1&amp;gt;Url Rewriter Test Page!&amp;lt;/h1&amp;gt;&amp;lt;br /&amp;gt;

 分类名为：&amp;lt;%= RouteData.Values[&amp;#34;category&amp;#34;] %&amp;gt;&amp;lt;br /&amp;gt;
 产品名为：&amp;lt;%= RouteData.Values[&amp;#34;name&amp;#34;] %&amp;gt;
&amp;lt;/asp:Content&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;7 刷新页面可以看到在RegisterRoutes中配置的默认值会呈现在页面上：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300728509.webp" alt="2010-07-27_111408" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;8 将URL修改为http://localhost:10000/products/computer/thinkpad，再刷新页面可以看到页面中呈现的是URL中设置的分类名和产品名:&lt;/p&gt;</description></item><item><title>WCF契约的简单介绍（服务契约 数据契约 消息契约）</title><link>https://fwhyy.com/2010/07/the-simple-introduction-of-wcf-contract/</link><pubDate>Wed, 21 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/the-simple-introduction-of-wcf-contract/</guid><description>&lt;p&gt;本篇博文只是简单说下WCF中的契约的种类、作用以及一些简单的代码示例。在WCF中契约分为服务契约、数据契约和消息契约。下面对这几种契约进行简单的介绍。&lt;/p&gt;
&lt;h2 id="服务契约"&gt;服务契约&lt;/h2&gt;
&lt;p&gt;服务契约描述了暴露给外部的类型（接口或类）、服务所支持的操作、使用的消息交换模式和消息的格式。每个WCF服务必须实现至少一个服务契约。使用服务契约必须要引用命名空间System.ServiceModel 。服务契约中常用到的三个特性：&lt;/p&gt;
&lt;h3 id="servicecontractattribute"&gt;ServiceContractAttribute&lt;/h3&gt;
&lt;p&gt;该特性定义在类或接口上，用来描述一个相关操作的集合。ServiceContractAttribute特性还有如下的一些属性值可以设置：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Name：给服务契约定义一个名称，而不是使用接口或是类的类型名，在客户端添加服务引用时会用到。&lt;/li&gt;
&lt;li&gt;Namespace：命名空间，默认值为http://tempuri.org。&lt;/li&gt;
&lt;li&gt;CallbackContract：将另一个服务契约定义为回调契约，使得客户端可以接收服务端的异步消息。&lt;/li&gt;
&lt;li&gt;ProtectionLevel：控制契约中发送给消息的保护方式是否需要被签名和加密。该属性为System.Net.Security.ProtectionLevel枚举类型。&lt;/li&gt;
&lt;li&gt;SessionMode：确定会话是否为公开服务契约的端点所支持。&lt;/li&gt;
&lt;li&gt;ConfigurationName：服务的配置名称。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[ServiceContract(Name=&amp;#34;HelloWorld&amp;#34;,Namespace=&amp;#34;http://oec2003.cnblogs.com&amp;#34;]
public interface IHelloWorldService
{ 

}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="operationcontractattribute"&gt;OperationContractAttribute&lt;/h3&gt;
&lt;p&gt;用OperationContractAttribute标记的方法即为一个服务操作，简单的使用该特性就可以让一个方法加入到服务契约的操作队列中，可以被客户端所调用。该特性也有一些设置消息交换方式的属性。如下&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Name：定义一个操作名称，而不是使用方法名称。&lt;/li&gt;
&lt;li&gt;Action：该操作消息的动作标题。&lt;/li&gt;
&lt;li&gt;ReplyAction：响应该操作消息的动作标题。&lt;/li&gt;
&lt;li&gt;IsOneWay：设置该操作是否单向和没有回复，如果操作是单向的，将不支持ReplyAction。&lt;/li&gt;
&lt;li&gt;ProtectionLevel：允许你控制特定的操作消息是否被保护，操作中的ProtectionLevel属性将覆盖服务契约中的ProtectionLevel。该属性为System.Net.Security.ProtectionLevel枚举类型。&lt;/li&gt;
&lt;li&gt;IsInitiating：操作是否可以用来初始化会话。&lt;/li&gt;
&lt;li&gt;IsTerminating：操作是否中止一个会话。&lt;/li&gt;
&lt;li&gt;AsyncPattern：将服务操作定义为异步实现模式。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[ServiceContract(Namespace=&amp;#34;http://oec2003.cnblogs.com&amp;#34;,Name=&amp;#34;oec2003&amp;#34;,
 ConfigurationName=&amp;#34;IHelloWorldService&amp;#34;)]
public interface IHelloWorldService
{
 [OperationContract(Name=&amp;#34;oec2003SayHello&amp;#34;,
 Action = &amp;#34;http://oec2003.cnblogs.com/IHelloWorldService/Hello&amp;#34;,
 ReplyAction = &amp;#34;http://oec2003.cnblogs.com/IHelloWorldService/HelloReply&amp;#34;)]
 string SayHello();
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="messageparameterattribute"&gt;MessageParameterAttribute&lt;/h3&gt;
&lt;p&gt;使用 MessageParameterAttribute 可以控制参数或返回值的名称。此属性对于已用 MessageContractAttribute 特性标记的参数无效。该特性只有一个Name属性，看如下代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[ServiceContract(Namespace=&amp;#34;http://oec2003.cnblogs.com&amp;#34;,Name=&amp;#34;oec2003&amp;#34;,
 ConfigurationName=&amp;#34;IHelloWorldService&amp;#34;)]
public interface IHelloWorldService
{
 [OperationContract]
 [return: MessageParameter(Name = &amp;#34;responseString&amp;#34;)]
 string SayHello([MessageParameter(Name = &amp;#34;string&amp;#34;)]string meg);
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="数据契约"&gt;数据契约&lt;/h2&gt;
&lt;p&gt;使用数据契约必须引用System.Runtime.Serialization命名空间，在类型上使用DataContractAttribute可以创建数据契约，类型中的成员使用DataMember标记。代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[DataContract]
public class User
{
 [DataMember]
 public int Age { get; set; }
 [DataMember]
 public string Name { get; set; }
 [DataMember]
 public string Email { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="datacontractattribute"&gt;DataContractAttribute&lt;/h3&gt;
&lt;p&gt;DataContractAttribute特性定义在类型之上，类型包括类、结构、枚举但不包括接口。DataContractAttribute特性不能被继承，即继承自有DataContractAttribute特性标记的类并不是数据契约，必须显示使用DataContractAttribute标记才能成为数据契约。DataContractAttribute特性有IsReference、Name和Namespace三个属性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IsReference：bool类型，表示在进行序列化的时候是否保持对象现有的引用结构。&lt;/li&gt;
&lt;li&gt;Name：名称。&lt;/li&gt;
&lt;li&gt;Namespace：命名空间。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[DataContract(IsReference=true,Name=&amp;#34;MyUser&amp;#34;,Namespace=&amp;#34;http://oec2003.cnblogs.com&amp;#34;)]
public class User
{
 [DataMember]
 public int Age { get; set; }
 [DataMember]
 public string Name { get; set; }
 [DataMember]
 public string Email { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="datamemberattribute"&gt;DataMemberAttribute&lt;/h3&gt;
&lt;p&gt;使用DataMemberAttribute标记的类型成员才能成为数据契约的数据成员。这个和服务契约中的OperationContractAttribute类似。DataMemberAttribute特性有如下四个属性:&lt;/p&gt;</description></item><item><title>WCF问题:“HTTP 错误 404.17 – Not Found 请求的内容似乎是脚本，因而将无法由静态文件处理程序来处理”解决方法</title><link>https://fwhyy.com/2010/07/wcf-problem-http-error-404-17-solution/</link><pubDate>Mon, 19 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/wcf-problem-http-error-404-17-solution/</guid><description>&lt;p&gt;在写&lt;a href="http://blog.fwhyy.com/?p=23"&gt;在IIS中寄存已有WCF服务&lt;/a&gt;文章的时候，创建了WCF Service模板站点，按F5运行的时候会出现“HTTP 错误 404.17 – Not Found 请求的内容似乎是脚本，因而将无法由静态文件处理程序来处理 ”的错误，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290630316.webp" alt="2010-07-19_173102" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在网上查出的解决方为重新注册WCF，在命令提示符中输入如下图的命令运行即可:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290630346.webp" alt="2010-07-19_173337" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;安装成功后再次运行站点就会出现正确的页面，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290638830.webp" alt="image-20220129063819672" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>在IIS中寄存已有WCF服务</title><link>https://fwhyy.com/2010/07/register-existing-wcf-service-in-iis/</link><pubDate>Mon, 19 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/register-existing-wcf-service-in-iis/</guid><description>&lt;p&gt;IIS是WCF服务的宿主之一，在新建Web Site的时候有WCF Service模板可以供选择，不过依据WCF Service模板创建的站点是将服务和宿主整合在一起了，下面就来看看如何将一个已有的WCF服务寄存在IIS中。&lt;/p&gt;
&lt;p&gt;1 在&lt;a href="http://www.cnblogs.com/oec2003/archive/2010/07/15/1778013.html"&gt;一个简单的WCF示例&lt;/a&gt;一文的解决方案中添加新的站点，选择WCF Service模板，地址设置为http://localhost/IISHostedService，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301618792.webp" alt="2010-07-19_154628" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 确定后，WCF Service模板就生成了一个带有服务的站点，因为我们要将已有服务寄存在该站点中，所以要删除站点中自带的服务，服务的文件在App_Code目录中，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301619850.webp" alt="2010-07-19_155053" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 添加对Service项目的引用，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301619979.webp" alt="2010-07-19_161549" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;4 双击项目中Service.svc文件，修改@ServiceHost指令，关联上服务类型，修改后的代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;%@ ServiceHost Language=&amp;#34;C#&amp;#34; Debug=&amp;#34;true&amp;#34; Service=&amp;#34;Service.HelloWorldService&amp;#34; %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5 修改站点的Web.Config文件，找到Service节点，修改Service节点的Name属性、endpoint节点的绑定属性和契约属性，修改后的代码如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301619029.webp" alt="2010-07-19_162314" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;6 将该站点设置为启动项目，按F5运行，如果Web.Config文件中没有配置元数据交换端点，运行后会看到如下页面：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301619804.webp" alt="2010-07-19_164149" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;可以根据上面页面中的步骤一步一步来配置元数据交换端点，配置好后，如果serviceMetadata节点的httpGetEnabled属性设置为false，运行后如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301619610.webp" alt="2010-07-19_164721" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在设置httpGetEnabled属性为true，再次运行可以看到svcutil指令后是一个带有?wsdl的链接地址，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301619381.webp" alt="2010-07-19_1649411" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击这个链接，可以看到服务的WSDL文档，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301620414.webp" alt="2010-07-19_165128" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;7 IIS宿主部分已经写好，现在要做的就是使用SvcUtil工具来生成客户端的代理，打开VS2008 的命令提示窗口，输入先前站点运行后的命令提示，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301620416.webp" alt="2010-07-19_170851" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;8 执行后生成了一个代理文件和一个配置文件，在目录C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC 中，将这两个文件拷贝到客户程序中，配置文件改名为app.config，然后再客户程序中添加如下代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;class Program
{
 static void Main(string[] args)
 {
 oec2003Client proxy = new oec2003Client();
 Console.WriteLine(proxy.SayHello());
 proxy.Close();
 Console.ReadLine();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;9 运行客户程序可以看到如下结果&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301620809.webp" alt="2010-07-19_171432" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>WCF中客户端生成代理的两种方式</title><link>https://fwhyy.com/2010/07/wcf-client-generation-agent-in-two-ways/</link><pubDate>Fri, 16 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/wcf-client-generation-agent-in-two-ways/</guid><description>&lt;p&gt;WCF程序中客户端要生成代理才能调用服务，在客户端生成代理有多种方式，如用ChannelFactory和添加服务引用等。下面就分别来介绍下这两种生成代理的方式。&lt;/p&gt;
&lt;h2 id="使用channelfactory"&gt;使用ChannelFactory&lt;/h2&gt;
&lt;p&gt;使用ChannelFactory创建代理需要的条件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;服务端点的地址，即在宿主中用程序设置的或是配置文件中设置的。&lt;/li&gt;
&lt;li&gt;服务端点的绑定协议。&lt;/li&gt;
&lt;li&gt;服务契约的元数据，可以将服务契约复制一份到客户端或是在客户端添加对服务的引用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下面的代码示例为通过ChannelFactory手动创建代理&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;EndpointAddress ea =
 new EndpointAddress(&amp;#34;http://localhost:10000/Service/HelloWorldService&amp;#34;);
IHelloWorldService proxy =
 ChannelFactory&amp;lt;IHelloWorldService&amp;gt;.CreateChannel(new BasicHttpBinding(),ea);
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;EndpointAddress：端点地址，该类的实例作为CreateChannel方法的一个参数，实例化EndpointAddress时给的地址要和宿主中设置的地址一致。&lt;/li&gt;
&lt;li&gt;IHelloWorldService：这个是服务契约在客户端的一个副本，不包含具体的实现。&lt;/li&gt;
&lt;li&gt;ChannelFactory&lt;T&gt;：一个服务模型类型，可以产生客户代理和基础信道栈，使用该类的CreateChannel可以生成代理，有两个参数，绑定类型和端点地址，绑定类型和端点地址要和宿主中设置的一致。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="添加服务引用的方式"&gt;添加服务引用的方式&lt;/h2&gt;
&lt;p&gt;1 在宿主的配置文件中配置元数据呢交换节点，并在行为中设置serviceMetadata，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290626408.webp" alt="2010-07-16_163822" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 在客户端添加服务引用时必须启动宿主。&lt;/p&gt;
&lt;p&gt;3 配置文件设置好后，启动宿主，然后再客户项目上右击选择“Add Service Reference ”，在地址框中输入正确地址，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290627453.webp" alt="2010-07-16_164810" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Http://localhost:10000/mex：是配置文件中的基地址http://localhost:10000加上端点地址mex组合而成。&lt;/p&gt;
&lt;p&gt;oec2003：为服务契约中设置的属性Name的值，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290627963.webp" alt="2010-07-16_165418" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;HelloWorld：为自己定义的引用到客户端的名称。&lt;/p&gt;
&lt;p&gt;4 添加服务引用后客户端的项目列表显示如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290627665.webp" alt="2010-07-16_165914" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;5 在客户端添加如下代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;class Program
{
 static void Main(string[] args)
 {
 HelloWorld.oec2003Client proxy = new Client.HelloWorld.oec2003Client();
 Console.WriteLine(proxy.SayHello());
 Console.ReadLine();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;6 先运行宿主，然后运行客户程序就可以看到调用服务返回的结果。&lt;/p&gt;</description></item><item><title>一个简单的WCF示例</title><link>https://fwhyy.com/2010/07/a-simple-wcf-example/</link><pubDate>Thu, 15 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/a-simple-wcf-example/</guid><description>&lt;p&gt;WCF程序分为三个部分：服务、宿主和客户端。下面就一步一步按这三个部分来构建一个简单的WCF程序。可以选择这三个部分都创建独立的解决方案，也可以在一个解决方案中创建三个项目。在下面的例子中将采用将三个项目放在一个解决方案中。服务使用类库项目，宿主和客户端使用控制台程序。&lt;/p&gt;</description></item><item><title>WCF的一些基本知识点</title><link>https://fwhyy.com/2010/07/some-basic-knowledge-of-wcf/</link><pubDate>Wed, 14 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/some-basic-knowledge-of-wcf/</guid><description>&lt;p&gt;Windows Communication Foundation (WCF)是Microsoft为构建面向服务的应用提供的分布式通信编程框架，是.NET Framework 3.5的重要组成部分。使用该框架，开发人员可以构建跨平台、安全、可靠和支持事务处理的企业级互联应用解决方案。&lt;/p&gt;
&lt;p&gt;构建一个WCF程序通常分为三个部分：服务类（Server）、宿主（Host）、客户程序（Client）。有一个很重要的程序集（System.ServeiceModel）要引用，它包含WCF的核心功能。&lt;/p&gt;
&lt;p&gt;贯穿整个WCF的程序会涉及到服务、契约、寄存、端点、地址、绑定、与数据、代理、通道、行为等概念，下面一一介绍下&lt;/p&gt;
&lt;h2 id="服务"&gt;服务&lt;/h2&gt;
&lt;p&gt;通常为一个类库项目，在实际开发中建议将服务类独立出来。服务类中封装业务功能并提供可以让外部访问的方法集接口。一些具体的操作通常抽像为接口然后由类来实现，并且接口上要用ServiceContractAtrribute来定义，接口中的方法要用OperationContractAttribute来定义，这样任何实现了该接口的类都是服务类型。当然也可以直接在类上来定义契约。&lt;/p&gt;
&lt;h2 id="契约"&gt;契约&lt;/h2&gt;
&lt;p&gt;契约定义了服务向外界发布的操作，以及WCF 服务与客户相互通讯时的消息格式。WCF 中有四种类型的契约。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;服务契约: 定义一个接口，给接口附加[ServiceContract] ，给接口方法附加[OperationContract]&lt;/li&gt;
&lt;li&gt;数据契约: 数据契约定义将在客户端与服务器端传送的各种数据类型。定义数据契约时需要使用[DataContract] 和[DataMember] 。&lt;/li&gt;
&lt;li&gt;消息契约: 可以使用消息契约来定制WCF 服务与WCF 客户间相互通讯的SOAP 消息格式。&lt;/li&gt;
&lt;li&gt;错误契约: 定义在服务中如何处理异常，以及这些异常又如何传送到客户端。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="寄存"&gt;寄存&lt;/h2&gt;
&lt;p&gt;服务做好了后需要能够运行，因为客户在调用服务的时候服务必须是处在运行状态的，这就需要将服务寄存在一个地方，在一些Demo中会使用控制台程序来做宿主寄存服务，除此之外还可以是WinForm程序、WPF应用、Windows 服务、IIS、WAS等。&lt;/p&gt;
&lt;h2 id="端点"&gt;端点&lt;/h2&gt;
&lt;p&gt;端点的用处是方便客户程序调用服务的操作。端点定义了在什么地方可以访问服务、用什么方式访问以及有哪些操作可用，这就是端点的三要素（地址 绑定 契约）。端点可以在程序中设置也可以用配置文件的形式设置。&lt;/p&gt;
&lt;h2 id="地址"&gt;地址:&lt;/h2&gt;
&lt;p&gt;地址由模式、域、端口和路径组成。模式指所用的传输协议如TCP、命名管线、HTTP、MSMQ等，WCF中针对这些协议的模式为net.tcp 、net.pipe、 http 、net.msmq。看下面例子：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;net.tcp://localhost:10000&lt;/li&gt;
&lt;li&gt;net.pipe://oec2003 [oec2003为机器名]&lt;/li&gt;
&lt;li&gt;http://localhost:10000&lt;/li&gt;
&lt;li&gt;net.msmq://localhost:10000&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;在ServerHost中加入多个端点时，需要为每个端点设置唯一的地址。&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="绑定"&gt;绑定&lt;/h2&gt;
&lt;p&gt;绑定描述了某一端点的协议支持。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP协议：BasicHttpBinding 、 WSHttpBinding 和WSFederationHttpBinding 。&lt;/li&gt;
&lt;li&gt;两个HTTP 通道实现双向通讯：WSDualHttpBinding。&lt;/li&gt;
&lt;li&gt;TCP协议：NetTcpBinding。&lt;/li&gt;
&lt;li&gt;P2P：NetPeerTcpBinding。&lt;/li&gt;
&lt;li&gt;命名管道：NamedPipeBinding。&lt;/li&gt;
&lt;li&gt;消息队列：NetMsmqBinding 和MsmqIntegrationBinding。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="元数据"&gt;元数据&lt;/h2&gt;
&lt;p&gt;这里元数据指的是服务中暴露的接口和服务端点的信息，客户依据这些元数据来生成代理调用服务。元数据可以通过两种方式被调用：1 ServiceHost可以公开一个元数据交换端点（IMetadataExchange）以便客户访问元数据；2 将元数据生成一个WSDL文档来描述端点和服务支持的协议。&lt;/p&gt;
&lt;h2 id="代理"&gt;代理&lt;/h2&gt;
&lt;p&gt;客户端是使用代理和服务通信。一个代理就是一个类型高开服务契约中的操作，客户调用时，对客户隐藏实现细节。客户端可以使用ChannelFactory或通过引用Web服务的方式来创建代理。&lt;/p&gt;
&lt;h2 id="通道"&gt;通道&lt;/h2&gt;
&lt;p&gt;通道是为了方便WCF中客户端和服务的通信而建立的。熟悉Remoting的朋友一定不会感到陌生。ServiceHost会为每一个端点创建一个通道侦听器，用来侦听客户端发送的消息。客户段和服务的两种信道必须相互兼容才能保持通信。&lt;/p&gt;
&lt;h2 id="行为"&gt;行为&lt;/h2&gt;
&lt;p&gt;行为会影响服务对消息的处理方式，当服务和端点确定了核心的通信需求以及和客户端之间共享了元数据后，当行为穿过信道栈时会改变消息的处理方式。行为可以在配置文件中进行配置。&lt;/p&gt;
&lt;p&gt;这些概念有的可能不太好理解，但在WCF的学习过程中会始终伴随着他们，也会随着我们不断的学习进而有较深入的理解。下面我就目前的理解对WCF的开发流程做个简单的总结：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;创建服务，这个通常是个类库项目，可以选择创建一个空的类库项目或是WCF Service Library。如果是创建的空的类库项目，则需要引用程序集System.ServeiceModel。&lt;/li&gt;
&lt;li&gt;在服务中创建服务契约和服务的操作，一般抽象为接口，ServiceContract和OperationContract标记定义在接口和接口中的方法上，然后创建类继承接口给出具体实现即可。&lt;/li&gt;
&lt;li&gt;服务需要寄存，必要要有宿主环境，可以根据需要自己选择任意一种，比如控制台程序。需要引用服务的程序集和System.ServeiceModel。然后就是配置端点和绑定。可以用程序的方式或是配置文件的方式。&lt;/li&gt;
&lt;li&gt;客户端可以是控制台程序、WinForm程序等。拿控制台程序来说吧，创建一个控制台程序，引用程序集System.ServeiceModel。在客户端可以使用ChannelFactory的方式或是通过添加服务引用的方式来创建代理。如果是使用ChannelFactory的方式创建代理，在客户端必须有服务契约的副本，可以将服务中的接口复制到客户端或是添加对服务的引用。创建代理时端点信息可以在程序中写也可以在配置文件中配置。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>WCF中的ServiceHost初始化两种方式</title><link>https://fwhyy.com/2010/07/wcf-servicehost-initialization-in-two-ways/</link><pubDate>Tue, 13 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/wcf-servicehost-initialization-in-two-ways/</guid><description>&lt;p&gt;在宿主程序中初始化ServiceHost有直接写代码和使用配置文件两种方式。使用ServiceHost首先要引用System.ServiceModel 命名空间。&lt;/p&gt;
&lt;h2 id="代码方式"&gt;代码方式&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;using(ServiceHost host=new ServiceHost(typeof(HelloWordService)))
{
 host.AddServiceEndpoint(typeof(IHelloWordService),
 new BasicHttpBinding(), new Uri(&amp;#34;http://localhost:10000/HelloWorldService&amp;#34;));
 host.AddServiceEndpoint(typeof(IHelloWordService),
 new NetTcpBinding(), new Uri(&amp;#34;net.tcp://localhost:10001/HelloWorldService&amp;#34;));

 if (host.State != CommunicationState.Opening)
 host.Open();
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="配置文件方式"&gt;配置文件方式&lt;/h2&gt;
&lt;p&gt;配置文件代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;services&amp;gt;
 &amp;lt;service behaviorConfiguration=&amp;#34;serverBehavior&amp;#34; name=&amp;#34;HelloWordService&amp;#34;&amp;gt;
 &amp;lt;endpoint address=&amp;#34;http://localhost:10000/HelloWorldService&amp;#34;
 binding=&amp;#34;basicHttpBinding&amp;#34; contract=&amp;#34;IHelloWordService&amp;#34;&amp;gt;&amp;lt;/endpoint&amp;gt;
 &amp;lt;endpoint address=&amp;#34;net.tcp://localhost:10001/HelloWorldService&amp;#34;
 binding=&amp;#34;netTcpBinding&amp;#34; contract=&amp;#34;IHelloWorldService&amp;#34;&amp;gt;&amp;lt;/endpoint&amp;gt;
 &amp;lt;/service&amp;gt;
&amp;lt;/services&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;当然也可以使用基地址的方式来配置&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;services&amp;gt;
 &amp;lt;service behaviorConfiguration=&amp;#34;serverBehavior&amp;#34; name=&amp;#34;HelloWordService&amp;#34;&amp;gt;
 &amp;lt;endpoint address=&amp;#34;HelloWorldService&amp;#34;
 binding=&amp;#34;basicHttpBinding&amp;#34; contract=&amp;#34;IHelloWordService&amp;#34;&amp;gt;&amp;lt;/endpoint&amp;gt;
 &amp;lt;endpoint address=&amp;#34;HelloWorldService&amp;#34;
 binding=&amp;#34;netTcpBinding&amp;#34; contract=&amp;#34;IHelloWorldService&amp;#34;&amp;gt;&amp;lt;/endpoint&amp;gt;
 &amp;lt;host&amp;gt;
 &amp;lt;baseAddresses&amp;gt;
 &amp;lt;add baseAddress=&amp;#34;http://localhost:10000/&amp;#34;/&amp;gt;
 &amp;lt;add baseAddress=&amp;#34;net.tcp://localhost:10001/&amp;#34;/&amp;gt;
 &amp;lt;/baseAddresses&amp;gt;
 &amp;lt;/host&amp;gt;
 &amp;lt;/service&amp;gt;
&amp;lt;/services&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;配置好配置文件后就宿主程序中就很简单了，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;using(ServiceHost host=new ServiceHost(typeof(HelloWordService)))
{
 if (host.State != CommunicationState.Opening)
 host.Open();
}
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Windows Server 2008启用无线局域网支持</title><link>https://fwhyy.com/2010/07/windows-server-2008-enabled-wireless-lan-support/</link><pubDate>Tue, 13 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/windows-server-2008-enabled-wireless-lan-support/</guid><description>&lt;p&gt;公司的本装上Windows server 2008后无线网就不能用了，这对移动办公来说及其不方便，在网上搜了解决方法，记录如下：&lt;/p&gt;
&lt;p&gt;1 打开“服务器管理器”，如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290654272.webp" alt="2010-12-30_232936" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 选择“功能”，点击“添加功能”，在弹出的向导列表中勾选“无线 LAN 服务”进行安装。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290654092.webp" alt="2010-12-30_233139" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 安装成功后，无线网就可以正常使用了。&lt;/p&gt;</description></item><item><title>Zend Studio 7.2 汉化包 及安装方法</title><link>https://fwhyy.com/2010/07/zend-studio-7-2-localization-package-and-installation-method/</link><pubDate>Fri, 09 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/zend-studio-7-2-localization-package-and-installation-method/</guid><description>&lt;p&gt;Zend Studio 7.2 汉化包&lt;/p&gt;
&lt;p&gt;&lt;a href="http://download.csdn.net/source/2467231"&gt;点击下载&lt;/a&gt;
安装方法：&lt;/p&gt;
&lt;p&gt;下载解压后有features和plugins两个目录 ，将这两个目录中的文件复制到Zend Studio7.2安装目录中的对应文件夹中，重新启动Zend Studio即可。&lt;/p&gt;
&lt;p&gt;注：在复制文件前，建议将安装目录下的features和plugins两个目录备份下再进行复制。&lt;/p&gt;</description></item><item><title>Net Remoting Error:试图创建未绑定类型的代理</title><link>https://fwhyy.com/2010/07/net-remoting-error-try-to-create-unbounded-types-of-agent/</link><pubDate>Wed, 07 Jul 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/07/net-remoting-error-try-to-create-unbounded-types-of-agent/</guid><description>&lt;p&gt;在使用Net Remoting时 如果客户端程序出现“试图创建未绑定类型的代理”的错误时，只需将远程对象继承MarshalByRefObject类就可以解决了。&lt;/p&gt;</description></item><item><title>Net4.0—Web部署工具</title><link>https://fwhyy.com/2010/06/net-4-the-web-deployment-tool/</link><pubDate>Thu, 03 Jun 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/06/net-4-the-web-deployment-tool/</guid><description>&lt;h2 id="vs2008的web部署和vs2010的web部署"&gt;VS2008的Web部署和VS2010的Web部署&lt;/h2&gt;
&lt;p&gt;VS2010的Web部署工具相较于以前的版本做了很大的改进，下面先来看看VS2010和VS2008的Web部署工具的图片：&lt;/p&gt;
&lt;h3 id="vs2008"&gt;VS2008&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300732166.webp" alt="2010-05-27_143737" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在VS2008种首先是弹出Publish Web对话框，点击选择路径按钮后弹出下图的对话框&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300732168.webp" alt="2010-05-27_143831" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在这个对话框中可以选择任意一种的发布方式。&lt;/p&gt;
&lt;p&gt;在VS2010中做了改进，将多个步骤封装在了一起，也称之为“一键部署”，让部署变得更加容易。如下图：&lt;/p&gt;
&lt;h3 id="vs2010"&gt;VS2010&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300732962.webp" alt="2010-05-27_155506" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在VS2010的Web项目上点击右键选择Publish或是点击VS的工具条中的Publish（如下图）都可以弹出一键部署的对话框&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300732949.webp" alt="2010-06-03_141655" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在Publish Web对话框中，通常我们需要填写下面几项内容&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Publish profile:这个是发布的名称&lt;/li&gt;
&lt;li&gt;Publish method：选择发布方式，有四种（Web Deploy、FTP、File System、FPSE）&lt;/li&gt;
&lt;li&gt;Server Url：如果在本地可以直接填写localhost&lt;/li&gt;
&lt;li&gt;Site/application：发布的站点的名称，在这里我们选择发布到本机的默认站点（Default Web Site）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;输入完成的对话框如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300732196.webp" alt="2010-06-03_143525" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击右上角的Save按钮可以将当前设置保存以便以后使用，这些配置的信息存放在项目的根目录下的一个后缀为.Publish.xml的文件中，该文件的内容如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300732680.webp" alt="2010-06-03_150947" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击Publish按钮后会出现错误，原因是应用程序池的运行时版本不是4.0，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300733208.webp" alt="2010-05-27_142656" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;打开IIS7，修改默认站点的应用程序池的版本为4.0即可，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300733423.webp" alt="2010-05-27_143028" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201300733426.webp" alt="2010-05-27_143107" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;修改完成后，重新发布就可以看到发布成功的提示。&lt;/p&gt;
&lt;h2 id="vs2010web项目中的webconfig文件"&gt;VS2010Web项目中的WebConfig文件&lt;/h2&gt;
&lt;p&gt;在VS2010中的Web项目的webconfig文件和以前版本不同，会多出来debug和release两个文件，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300733922.webp" alt="2010-06-03_151753" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;这两个文件时对应我们在编译项目时是选择的Debug还是Release，可以适应Debug和Release两种模式不同的需求。并且我们还可以自己添加新的配置文件来适应不同的需求，比如说现在需要一个测试环境下的配置文件，可以按下面步骤做：&lt;/p&gt;
&lt;p&gt;1 打开Build-Configuration Manager对话框，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300733480.webp" alt="2010-06-03_152700" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 点击New在弹出的对话框中输入文件名称Testing&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300733835.webp" alt="2010-06-03_153418" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 点击OK按钮Testing就会出现在下拉框中，这时再看项目中的webconfig文件下仍然只有Debug和Release两个文件，新加的Testing没有出现。在webconfig文件上点击右键，选择Add Config Transforms，Testing配置文件就会出现了，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300734304.webp" alt="2010-06-03_153720" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201300734204.webp" alt="2010-06-03_153834" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;4 我们可以通过修改不同的配置文件来达到在不同环境下的需求&lt;/p&gt;
&lt;h2 id="构建部署包"&gt;构建部署包&lt;/h2&gt;
&lt;p&gt;除了通过上面介绍的传统的方式发布Web程序外，还可以通过构建部署包的形式，在Web项目右击，会发现菜单中比以前版本多出来两项：&lt;/p&gt;
&lt;p&gt;1 Build Deployment Package：创建部署包&lt;/p&gt;
&lt;p&gt;2 Package/Publish Settings：创建部署包的设置&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300734292.webp" alt="2010-06-03_155336_thumb" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击Package/Publish Settings 和打开项目的属性然后选择Package/Publish Web的效果是一样的，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300734551.webp" alt="2010-06-03_155724" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;关于该界面中的各种配置选项，自行实验一下就都清楚了。配置好这些后，点击Build Deployment Package，就可以生成部署包了，部署包最终生成为一个zip文件，名称为项目名称。文件存放在项目下的obj\Testing\Package、obj\Debug\Package或obj\Release\Package下，这个要看是用那种模式进行发布的。&lt;/p&gt;
&lt;p&gt;构建了部署包之后只需要生成的zip文件就可以进行部署了，有两种方式可以部署：&lt;/p&gt;
&lt;p&gt;1 在zip文件的同目录下有个和项目同名，后缀为.deploy.cmd的文件，这是一个命令行的文件，执行文件中的一些脚本命令来进行部署，关于这种方式的部署设置在同目录下的ReadMe文件里有详细说明。这种方式的难度较大。&lt;/p&gt;
&lt;p&gt;2 第二种方式需要借助一个名为Web Deploy的第三方软件，可以点击此处&lt;a href="http://www.iis.net/download/webdeploy"&gt;下载&lt;/a&gt;，下载安装后，在IIS7的的站点上右击会多出“部署…”选项，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300734839.webp" alt="2010-06-03_164834" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;我们选择导入应用程序，弹出对话框中选择之前生成的zip文件，然后顺着下一步就行了，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300734339.webp" alt="2010-06-03_165355" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201300735229.webp" alt="2010-06-03_165830_thumb" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201300735872.webp" alt="2010-06-03_170326" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201300735255.webp" alt="2010-06-03_170442_thumb" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;完成后Web程序就会部署在IIS7中了。&lt;/p&gt;</description></item><item><title>SqlServer2008修改表时出现“save changes is not permitted…”解决方法</title><link>https://fwhyy.com/2010/06/sqlserver2008-modifying-a-table-save-changes-is-not-permitted-the-solution/</link><pubDate>Thu, 03 Jun 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/06/sqlserver2008-modifying-a-table-save-changes-is-not-permitted-the-solution/</guid><description>&lt;p&gt;最近使用SqlServer2008，发现在修改完表字段名或是类型后点击保存时会弹出一个对话框，对话框内容大致如下&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Saving changes is not permitted. The changes you have made require the following tables to be dropped and re-created. You have either made changes to a table that can’t be re-created or enabled the option Prevent saving changes that require the table to be re-created&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302001803.webp" alt="2010-06-03_094326" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;如果点击 Save Text File ，会保存一个文本文件，感觉没什么作用，内容如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302001334.webp" alt="2010-06-03_095158" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击 Cancel 后会弹出另一个对话框，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302001972.webp" alt="2010-06-03_095243" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击OK就关闭了对话框，当然我们的修改肯定也没有保存上。&lt;/p&gt;
&lt;h2 id="解决方法"&gt;解决方法&lt;/h2&gt;
&lt;p&gt;打开工具-选项，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302001623.webp" alt="2010-06-03_100942" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在选项对话框中选择：Designers—Table and DataBase Designers ，将右边的Prevent saving changes that require table re-creation 前的勾选去掉，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302001244.webp" alt="2010-06-03_101349" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击OK后，表的结构就可以随意修改保存了&lt;/p&gt;</description></item><item><title>Net4.0—VS2010新特性</title><link>https://fwhyy.com/2010/05/net-4-vs2010-new-features/</link><pubDate>Thu, 27 May 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/05/net-4-vs2010-new-features/</guid><description>&lt;p&gt;VS2010在用户体验上有了很大提升，可以让我们更方便和快捷地来进行编码工作。早在VS2010Beta版的时候，我曾写过&lt;a href="http://blog.fwhyy.com/2009/10/experience-vs2010-improvements/"&gt;一篇文章&lt;/a&gt;介绍VS2010的一些新特性，此文算是对那篇文章的补充吧。&lt;/p&gt;
&lt;h2 id="1-方便地删除recent-projects"&gt;1 方便地删除Recent Projects&lt;/h2&gt;
&lt;p&gt;如果用VS2010打开过项目，那么在启动VS2010后，在Start Page页面的Recent Projects列表中会有记录，之前的VS版本中如果想删除Recent Projects列表记录，需要修改注册表信息，参考&lt;a href="http://blog.fwhyy.com/index.php/2007/12/delete-recently-opened-in-visual-studio-project-and-file-records/"&gt;这里&lt;/a&gt;。在VS2010中可以很方便做到对Recent Projects列表的管理，在某一个项目名称上右击，弹出菜单中会有Remove From List选项，点击后会将当前项目名从列表中删除，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300735497.webp" alt="2010-05-26_155027" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="2-navigate-to"&gt;2 Navigate to&lt;/h2&gt;
&lt;p&gt;Navigate to搜索对话框可以让我们方便地查找内容，并且可以模糊匹配。输入[Ctrl+，] 快捷键便可以打开Nagigate to 对话框，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300735950.webp" alt="2010-05-27_104536" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在Search terms框中输入关键词就可以进行模糊匹配，比如输入PL 就可以匹配到Page_Load事件，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300736023.webp" alt="2010-05-27_104755" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;双击结果中的方法名就可以导航到方法体中。&lt;/p&gt;
&lt;h2 id="3-同名函数的高亮显示"&gt;3 同名函数的高亮显示&lt;/h2&gt;
&lt;p&gt;在以前的VS版本中，要查找一个函数在页面中出现的次数或位置，有两种方法：Ctrl+F查找或是查找该函数的所有引用，这两种方法都不是很方便。在VS2010种新增了同名函数高亮显示功能，选中一个函数名，在同页中所有这个函数名出现的地方会高亮显示，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300736374.webp" alt="2010-05-27_103031" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="4-view-call-hierarchy"&gt;4 View Call Hierarchy&lt;/h2&gt;
&lt;p&gt;在一个方法名上右击，会有View Call Hierarchy选项，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300736242.webp" alt="2010-05-27_103504" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击后会打开一个试图，该试图可以方便看出该方法在那些地方被用到，传入的是什么参数，并且可以很快定位在引用的地方，对于一个代码行数比较多的文件，可以提高开发效率，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300736656.webp" alt="2010-05-27_111025" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;当然在VS2010中好玩的好用的新的功能肯定不止这些，让我们慢慢去发现吧！&lt;/p&gt;</description></item><item><title>Net4.0—Framwork新增特性</title><link>https://fwhyy.com/2010/05/net-4-framwork-of-new-features/</link><pubDate>Wed, 26 May 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/05/net-4-framwork-of-new-features/</guid><description>&lt;h2 id="1-biginteger"&gt;1 BigInteger&lt;/h2&gt;
&lt;p&gt;BigInteger是Net4.0种System.Numerics命名空间下的一个新类，表示任意大小的带符号整数。像以前版本中的Int32，int64等这些都有MinValue和MaxValue属性，也就是说有大小的限制，而BigInteger没有大小的限制，所以理论上来说大数字足够大时可能会出现OutOfMemoryException异常。&lt;/p&gt;
&lt;p&gt;以一个例子来看看BigInteger，下面的例子是一个计算斐波那契的函数：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public static int Fibonacci(int x)
{
 var preValue = -1;
 var curValue = 1;
 for (int i = 0; i &amp;lt;= x; ++i)
 {
 var sum = preValue + curValue;
 preValue = curValue;
 curValue = sum;
 }
 return curValue;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码当x的值为47的时候就会出现溢出，结果如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300729455.webp" alt="2010-05-26_105558" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;现在修改代码，使用BigInteger，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public static BigInteger Fibonacci(int x)
{
 var preValue = new BigInteger(-1);
 var curValue = new BigInteger(1);
 for (int i = 0; i &amp;lt;= x; ++i)
 {
 var sum = preValue + curValue;
 preValue = curValue;
 curValue = sum;
 }
 return curValue;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;再次将x赋值为47，运行结果如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300729877.webp" alt="2010-05-26_111127" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="2-complex"&gt;2 Complex&lt;/h2&gt;
&lt;p&gt;Complex通BigInteger一样也是在System.Numerics命名空间下。简单说就是一个计算复数的类。看下面例子&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;private static void ComplexDemo()
{
 var z1 = new Complex(3, 4);
 var z2 = new Complex(5, 6);

 var r1 = Complex.Add(z1, z2);
 var r2 = Complex.Subtract(z1, z2);
 var r3 = Complex.Multiply(z1, z2);
 var r4 = Complex.Divide(z1, z2);

 Console.WriteLine(&amp;#34;Z1+Z2 :&amp;#34; + r1);
 Console.WriteLine(&amp;#34;Z1-Z2 :&amp;#34; + r2);
 Console.WriteLine(&amp;#34;Z1*Z2 :&amp;#34; + r3);
 Console.WriteLine(&amp;#34;Z1/Z2 :&amp;#34; + r4);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;运行结果如下图：&lt;/p&gt;</description></item><item><title>使用LoadRunner测试WMS</title><link>https://fwhyy.com/2010/05/using-loadrunner-test-wms/</link><pubDate>Fri, 21 May 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/05/using-loadrunner-test-wms/</guid><description>&lt;p&gt;LoadRunner是一款非常强大的测试工具，本文为笔者在对LoadRunner有了初步了解后对WMS的压力测试过程，因为接触时间比较短，不对之处欢迎大家指出。由于Licence的原因，对WMS的测试只支持最多100个虚拟用户。下面就开始测试了。&lt;/p&gt;
&lt;p&gt;1 要有一个可用的WMS的地址，可以在本机的流媒体服务中创建，也可以使用远程的。
2 打开LoadRunner8.1，并运行窗口中点击Create/Edit Srcirpts ,如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290657907.webp" alt="2010-05-20_150059" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 在弹出的窗口中点击New VUser Scripts，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290657630.webp" alt="2010-05-20_150204" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 点击New VUser Script后，会弹出一个窗口让选择脚本协议，在这里我们选择Streaming下面的WMS，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290657385.webp" alt="2010-05-20_150235" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;4 确定后会在窗口中新开一个Lab页，该页面的左边为导航栏，标明了完成测试的5个步骤，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290658818.webp" alt="2010-05-20_152114" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;5 首先执行第一项创建脚本，在WMS中不能录制脚本所以只能手动来写了，有关WMS脚本的写法可以参考LoarRunner自带的帮助文档。点击Create Script，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290658655.webp" alt="2010-05-20_150312" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;6 在右边出现的界面中点击Script View ，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290658471.webp" alt="2010-05-20_150401" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;7 点击Srcipt View后就会出现脚本编辑区域，选择Action，在代码中添加启动WMS的代码，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290658569.webp" alt="2010-05-20_150550" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;8 脚本写好之后就需要执行第二步来验证下脚本是否正确，或是是否能和指定的WMS地址相连接。点击左边的Verify Replay，在右侧的界面中点击Start Replay，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290658124.webp" alt="2010-05-20_151032" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;9 通常会出现如下的错误，原因是在WMS的根目录（C:\wmpub\wmroot）下缺少wmload.asf文件，至于这个文件是做什么用的大家可以网上搜一下。随便找一个asf文件将名称改为wmload然后放在WMS的根目录即可。&lt;/p&gt;
&lt;p&gt;有可能添加wmload.asf文件后仍然不成功，有两个可能的原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;流媒体服务器没有默认的点播发布点，如果没有&lt;a href="http://www.cnblogs.com/oec2003/archive/2010/05/19/1739254.html"&gt;添加默认点播发布点&lt;/a&gt;，路径只想WMS根目录。&lt;/li&gt;
&lt;li&gt;默认点播发布点“拒绝新连接”了，选中“允许新连接”即可。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290658097.webp" alt="2010-05-20_151115" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;10 这些都搞定后，重新验证会出现成功的界面。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290658265.webp" alt="2010-05-20_151742" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;11 点击上图中出现的Run-Time Settings 设置脚本的运行迭代次数等信息。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290659546.webp" alt="2010-05-20_152032" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;12 设置好迭代次数后，就可以执行第三步了，不过第三步主要是设置事务和参数的，在本例中用不上，所以直接执行第四步，点击Concurrent User 出现如下界面：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290659558.webp" alt="2010-05-20_152321" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;13 点击上图中Create Controller Scenario ，创建一个控制场景，在这之前会提示保存脚本信息，这里我们将脚本信息命名为TestWMS ，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290659727.webp" alt="2010-05-20_152405" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;14 保存好脚本信息后，会弹出一个场景设置框，可以设置虚拟用户的个数，我们设置虚拟用户为100，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290659640.webp" alt="2010-05-20_152432" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;15 点击确定后会弹出运行测试的窗口，在此窗口中点击 Edit Schedule 可以设置多用户是以什么形式并发的，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290659921.webp" alt="2010-05-20_152519" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;16 点击上图中的 Edit Schedule 出现设置窗口，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290659479.webp" alt="2010-05-20_152722" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;17 设置完成后，可以点击窗口右侧的Start Scenairo按钮开始运行测试，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290659657.webp" alt="2010-05-20_152814" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;18 测试运行完成后，点击窗口上方的分析结果按钮来查看测试结果，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290659897.webp" alt="2010-05-20_152949" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;19 最后就可以根据结果来编写相应的测试报告了&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290700441.webp" alt="2010-05-20_153020" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;当然LoadRunner的功能远不止这些，本文只是测试WMS的一个非常简单的例子，希望对您有所帮助。&lt;/p&gt;</description></item><item><title>WMS中添加默认发布点</title><link>https://fwhyy.com/2010/05/add-the-default-distribution-point-wms/</link><pubDate>Wed, 19 May 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/05/add-the-default-distribution-point-wms/</guid><description>&lt;p&gt;当我们在服务器中安装了WMS后会自动创建一个默认的点播发布点，对应的目录为C:\WMPub\WMRoot，当然我们也可以根据需要更改。有这个默认发布点，就可以通过mms://ServerName/MediaName  这种方式来访问C:\WMPub\WMRoot目录中的音视频文件。&lt;/p&gt;</description></item><item><title>在批处理文件中启动MediaPlayer播放制定文件</title><link>https://fwhyy.com/2010/05/in-a-batch-file-to-start-the-mediaplayer-play-set-files/</link><pubDate>Wed, 05 May 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/05/in-a-batch-file-to-start-the-mediaplayer-play-set-files/</guid><description>&lt;p&gt;我们知道在运行可以使用wmplayer指令来启动一个MediaPlayer，如果需要让MediaPlayer播放制定的文件或是一个制定的流媒体发布点，我们可以使用如下的命令格式&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;wmplayer “mms://WIN-FW.MiGu.com/12530”
wmplayer “C:\wmpub\wmroot\legacy_content_clip.wmv”
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;但是在运行中来执行命令需要手动去控制，如果将命令写到批处理文件中，就可以通过计划任务等一些手段来动态控制它的执行。&lt;/p&gt;
&lt;p&gt;做批处理文件非常简单，将文本文件的后缀改成bat即可，然后保存上面的内容在文件中，双击就可以执行。不过此时双击会发现并不能启动MediaPlayer，因为缺少了一个步骤。只需将C:\Program Files (x86)\Windows Media Player目录下的wmplayer.exe文件复制到C:\Windows\System32目录下即可。&lt;/p&gt;
&lt;p&gt;注:上面的路径C:\Program Files (x86)\Windows Media Player为64位系统下的路径，如果是32位系统则为C:\Program Files\Windows Media Player&lt;/p&gt;</description></item><item><title>Win2008计算机不能添加到域的解决方法</title><link>https://fwhyy.com/2010/04/win2008-computer-cannot-be-added-to-the-domain-of-the-solution/</link><pubDate>Wed, 28 Apr 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/04/win2008-computer-cannot-be-added-to-the-domain-of-the-solution/</guid><description>&lt;p&gt;最近接触了一点win2008活动目录，所谓万事开头难，本来很简单的事情在刚刚接触时就很费劲。&lt;/p&gt;
&lt;p&gt;在远程的一台机子上成功安装了AD后，想将本机添加到域中，试了很多次都不行，出现下面的错误：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290645332.webp" alt="2010-04-28_114731" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;查了很久的msdn文档，说的都不是很清楚，也许是我对dns的理解不够深入，最后得知原来是dns的指向问题。假如安装了AD的机子的IP为192.168.1.50，就将需要添加到域中的机子的dns设置为192.168.1.50，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290645237.webp" alt="2010-04-28_114829" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;设置好了dns后，再添加计算机到域，就可以出现登录框了：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290646257.webp" alt="2010-04-28_114936" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;输入用户名和密码就会出现欢迎窗口了：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290646603.webp" alt="2010-04-28_115054" loading="lazy" decoding="async"&gt;
&lt;/p&gt;</description></item><item><title>Win2008远程桌面安装AD后的登录问题解决</title><link>https://fwhyy.com/2010/04/win2008-remote-desktop-installation-ad-after-log-in-problem-solving/</link><pubDate>Tue, 27 Apr 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/04/win2008-remote-desktop-installation-ad-after-log-in-problem-solving/</guid><description>&lt;h2 id="问题"&gt;问题&lt;/h2&gt;
&lt;p&gt;本机操作系统为Win2008 ，远程连接的两台机子A和B的的系统也都为Win2008。先远程连接B，然后在B中远程连接A，在A上安装了AD，安装完要求重启A，A重启后再远程连接A，输入正确的密码不能登录了&lt;/p&gt;
&lt;h2 id="解决方法"&gt;解决方法&lt;/h2&gt;
&lt;p&gt;其实很简单，将B添加到域中，然后重启B就可以了&lt;/p&gt;</description></item><item><title>使用Expression Encoder 3发布媒体文件到WebDAV</title><link>https://fwhyy.com/2010/04/use-expression-encoder-3-to-webdav-publishing-media-file/</link><pubDate>Tue, 20 Apr 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/04/use-expression-encoder-3-to-webdav-publishing-media-file/</guid><description>&lt;h2 id="使用环境"&gt;使用环境&lt;/h2&gt;
&lt;p&gt;Windows Server 2008&lt;/p&gt;
&lt;p&gt;IIS7.0 Microsoft&lt;/p&gt;
&lt;p&gt;Expression Encoder3&lt;/p&gt;
&lt;h2 id="准备"&gt;准备&lt;/h2&gt;
&lt;p&gt;在IIS7.0中没有自带WebDAV，可以通过下面的链接进行下载安装，后两个为补丁。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=036269fa-0040-4ccd-ad3d-78da1ee132fb&amp;amp;DisplayLang=en"&gt;Microsoft WebDAV Extension for IIS 7.0 (x86)&lt;/a&gt;
&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=13e97aaa-fb1b-4cf8-b95f-19ae02321385&amp;amp;DisplayLang=en"&gt;Microsoft WebDAV Extension for IIS 7.0 (x64)&lt;/a&gt;
&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=567cb0d6-3e94-4035-a79d-22d1ef307d5e&amp;amp;DisplayLang=en"&gt;Update for WebDAV Extension for IIS 7.0 (KB955137) (x86)&lt;/a&gt;
&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=31fc62d7-abd0-4ac0-b727-d5ef0a50f8cc&amp;amp;DisplayLang=en%5B/url%5D"&gt;Update for WebDAV Extension for IIS 7.0 (KB955137) (x64)&lt;/a&gt;
&lt;a href="http://www.iis.net/download/SmoothStreaming"&gt;Smooth Streaming（x86 x64）&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="安装"&gt;安装&lt;/h2&gt;
&lt;p&gt;根据个人的电脑系统选择下载的安装包进行安装，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302145621.webp" alt="2010-04-20_161454" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;安装WebDAV&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302145136.webp" alt="2010-04-20_171133" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;安装Smooth Streaming&lt;/p&gt;
&lt;p&gt;设置及使用&lt;/p&gt;
&lt;p&gt;安装好WebDAV后，打开“Internet 信息服务（iis）管理器”，新建一个Web站点TestEncoder ，指向D://TestEncoder目录。点击新建的站点在功能区会看到“WebDAV Authoring Rules ” 选项，如下图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302145071.webp" alt="2010-04-20_162328" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;双击[WebDAV Authoring Rules ]项，右边的操作界面如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302145211.webp" alt="2010-04-20_162540" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;首先点击Disable WebDAV 启用WebDAV，然后点击Add Authoring Rule… 添加规则，下图仅供参考，具体设置根据实际应用来&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302145721.webp" alt="2010-04-20_162726" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;再点击WebDAV Settings进行设置，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302141853.webp" alt="2010-04-20_162950" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;设置好了后点击“应用”就可以了。&lt;/p&gt;
&lt;p&gt;到目前为止已经将WebDAV安装好了，不过还要对站点TestEncoder进行一些设置才可以：&lt;/p&gt;
&lt;p&gt;a 点击站点TestEncoder，在中间功能板块中双击“身份验证”，然后启用“windows 身份验证”。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302141337.webp" alt="2010-04-20_170732" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;b 点击站点TestEncoder，在中间功能板块中双击“目录浏览”，然后启用目录浏览。&lt;/p&gt;
&lt;p&gt;现在就开始完成发布过程。&lt;/p&gt;
&lt;p&gt;1 打开Expression Encoder3 ，新建一个JOb，名为为TestWebDAV，在媒体内容区域点击“导入”从本地选择一个媒体文件。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302141614.webp" alt="2010-04-20_164233" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 在“编码”面板中选择输出格式为“IIS Smooth Streaming ” 。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302141082.webp" alt="2010-04-20_165100" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 在“输出”面板中，任意选择一个模板，这个模板是Silvelight播放器的样式的模板，选择后再下方会有一个效果的预览视频。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302141363.webp" alt="2010-04-20_165319" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;4 在“输出”面板中展开“发布”节点，设置如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302141560.webp" alt="2010-04-20_170127" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;5 在“媒体内容”面板中点击“编码”，首先是对媒体文件进行编码，编码完成后就会直接发布到先前创建的站点TestEncoder 中。通过地址&lt;a href="http://192.168.1.160:8080/TestWenDAV/default.html"&gt;http://192.168.1.160:8080/TestWenDAV/default.html&lt;/a&gt; 可以直接访问了。&lt;/p&gt;</description></item><item><title>HTTP 错误 500.19 – Internal Server Error 错误解决方法</title><link>https://fwhyy.com/2010/04/http-error-500-19-internal-server-error-solution/</link><pubDate>Thu, 15 Apr 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/04/http-error-500-19-internal-server-error-solution/</guid><description>&lt;p&gt;刚在本机部署了一个WebService测试，浏览的时候出现了“HTTP 错误 500.19 – Internal Server Error ”错误，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300701743.webp" alt="2010-04-15_134600" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;经过检查发现是由于先安装vs2008后安装iis的缘故，只需重新注册下AspNet就可以了，具体步骤如下&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;打开运行，输入cmd进入到命令提示符窗口。&lt;/li&gt;
&lt;li&gt;进入到C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 目录。&lt;/li&gt;
&lt;li&gt;输入aspnet_regiis.exe –i 执行既可&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;注意：如果系统为64位 第二步的路径为C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727&lt;/p&gt;</description></item><item><title>Asp.Net控件开发(1)—入门介绍</title><link>https://fwhyy.com/2010/02/aspnet-controls-development-1-the-introduction/</link><pubDate>Tue, 09 Feb 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/02/aspnet-controls-development-1-the-introduction/</guid><description>&lt;p&gt;AspNet为我们提供了很多的控件，尽管如此，很多时候我们还是会感觉这些控件不够用，想根据自己的需求去定制一些控件，比如想在DropDownList控件中实现可以输入，AspNet并没有为我们提供这样的控件，这时就需要我们去编写自定义控件来满足需要。 本系列文章打算对AspNet控件开发做个入门级介绍，如果想了解更详细和深入可以参考&lt;a href="http://www.douban.com/subject/2268475/"&gt;《深入解析ASP.NET 2.0控件开发》&lt;/a&gt;和&lt;a href="http://www.douban.com/subject/3626223/"&gt;《纵向切入ASP.NET 3.5控件和组件开发技术》&lt;/a&gt;这两本书。&lt;/p&gt;
&lt;p&gt;言归正传，通常我们开发自定义控件会创建一个类库项目，编写完代码后编译会生成一个dll文件，这个dll文件就是我们自己开发的控件了。假设现在已经有一个名为HelloWorld.dll的控件，按照下面方法可以将该控件用在我们的项目中。&lt;/p&gt;
&lt;p&gt;1 在工具箱中点击右键-&amp;gt;添加选项卡。选项卡可以任意命名，比如：MyControls&lt;/p&gt;
&lt;p&gt;2 在新添加的选项卡区域中右键-&amp;gt;选择项。选择HelloWorld.dll文件后确定，会看到控件已经添加到工具箱中，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290824855.webp" alt="2010-12-28_235751" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 使用自定义控件和使用普通的AspNet控件一样，直接拖到页面中即可。将该控件拖入到页面中后，源视图中会添加如下代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;%@ Register Assembly=&amp;#34;ControlsDemo1&amp;#34; Namespace=&amp;#34;ControlsDemo1&amp;#34; TagPrefix=&amp;#34;cc1&amp;#34; %&amp;gt;

 &amp;lt;cc1:HelloWorld ID=&amp;#34;HelloWorld2&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;/cc1:HelloWorld&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面代码的第一行是注册该控件，TagPrefix属性指定控件的前缀，cc1是系统默认的前缀，我们也可以根据自己的喜好来自定义前缀，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;%@ Register Assembly=&amp;#34;ControlsDemo1&amp;#34; Namespace=&amp;#34;ControlsDemo1&amp;#34; TagPrefix=&amp;#34;oec2003&amp;#34; %&amp;gt;
 &amp;lt;oec2003:HelloWorld ID=&amp;#34;HelloWorld1&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;/oec2003:HelloWorld&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;&amp;lt;%@ Resgiter /&amp;gt;&lt;/code&gt;指令只是在单个页面中使用，我们还可以通过在web.config中配置来使全局都能够使用。web.config配置如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;system.web&amp;gt;
 &amp;lt;pages&amp;gt;
 &amp;lt;controls&amp;gt;
 &amp;lt;add assembly=&amp;#34;ControlsDemo1&amp;#34; namespace=&amp;#34;ControlsDemo1&amp;#34; tagPrefix=&amp;#34;oec2003&amp;#34;/&amp;gt;
 &amp;lt;/controls&amp;gt;
 &amp;lt;/pages&amp;gt;
&amp;lt;/system.web&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面简单介绍了怎样使用一个已经编写好的自定义控件，并且知道编写一个自定义控件通常是创建一个类库项目。现在就来看看一个自定义控件的具体实现方法。&lt;/p&gt;
&lt;p&gt;实现一个自定义控件，我们需要选择一个基类，这些基类有控件需要的最基本的功能，下面的三个类就是开发控件常用的基类。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;System.Web.UI.Control
System.Web.UI.WebControls.WebControl
System.Web.UI.WebControls.CompositeControl
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;Control：控件开发的基类，所有控件都直接或间接继承该类。该类的扩展性和灵活性最强。&lt;/li&gt;
&lt;li&gt;WebControl：该类继承自Control类，除了有Control的所有属性外，还提供布局样式等特性。比较适合对布局和外观样式要求较高的控件。和Control相同的是都适用于开发单个控件。&lt;/li&gt;
&lt;li&gt;CompositeControl：该类为AspNet2.0提供的一个控件基类。如果想把现有控件组合起来创建一个组合控件时，可以继承此类，此类继承了WebControl并实现了INamingContainer接口。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果我们只是对某一个现有的AspNet控件进行简单的扩充，我们可以用现有的任一控件作为基类。&lt;/p&gt;
&lt;p&gt;Control类最基础灵活性最强，那么就先以Control类为基类实现一个简单的HelloWorld控件。在新建的项目中创建一个类HelloWorld，继承Control，并重写Render方法，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class HelloWorld:Control
{
 protected override void Render(HtmlTextWriter writer)
 {
 writer.WriteLine(&amp;#34;hello world!&amp;#34;);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;编译后按照上面介绍的方法添加到工具箱中，然后拖到页面，运行后会在页面上呈现Hello world文本。现在对上面的代码做点改动让hello world文本的显示区加上边框和背景色，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class HelloWorld:Control
{
 protected override void Render(HtmlTextWriter writer)
 {
 writer.WriteLine(@&amp;#34;&amp;lt;div style=&amp;#34;&amp;#34;width:200px;height:100px;
 border:1px solid #4DA9C2;background-color:#C3D9FF&amp;#34;&amp;#34; &amp;gt;&amp;#34;);
 writer.WriteLine(&amp;#34;hello world!&amp;#34;);
 writer.WriteLine(@&amp;#34;&amp;lt;/div&amp;gt;&amp;#34;);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;运行后的效果：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290825971.webp" alt="2010-12-28_235833" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;效果虽然出来了，但是代码中是使用直接输出html代码和内嵌样式的方式，这样做当然是不好的，不是很好扑捉错误并且生成到客户端的html代码格式也不好。这个问题我们可以通过HtmlTextWriterAttribute、HtmlTextWriterTag、HtmlTextWriterStyle这三个枚举来解决。看下面代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class HelloWorld:Control
{
 protected override void Render(HtmlTextWriter writer)
 {
 writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, &amp;#34;1px&amp;#34;);
 writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, &amp;#34;solid&amp;#34;);
 writer.AddStyleAttribute(HtmlTextWriterStyle.BorderColor, &amp;#34;#4DA9C2&amp;#34;);
 writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, &amp;#34;#C3D9FF&amp;#34;);
 writer.AddStyleAttribute(HtmlTextWriterStyle.Width, &amp;#34;200px&amp;#34;);
 writer.AddStyleAttribute(HtmlTextWriterStyle.Height, &amp;#34;100px&amp;#34;);
 writer.RenderBeginTag(HtmlTextWriterTag.Div);

 writer.WriteLine(&amp;#34;hello world!&amp;#34;);

 writer.RenderEndTag();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;运行后效果和上面一样。并且查看页面的源代码可以看出用这种方式生成的html有规范的缩进，并且代码也是符合xhtml规范的，所以建议尽量使用这种方式而不是直接拼写html代码。&lt;/p&gt;</description></item><item><title>jQuery 1.4.1 VS智能提示文件下载</title><link>https://fwhyy.com/2010/02/jquery-1-4-1-vs-intellisense-file-downloads/</link><pubDate>Tue, 09 Feb 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/02/jquery-1-4-1-vs-intellisense-file-downloads/</guid><description>&lt;p&gt;vs2008中默认的jquery版本为1.3.2 ，我在 &lt;a href="http://blog.fwhyy.com/posts/87"&gt;在vs2008中设置jquery智能提示&lt;/a&gt; 一文中做了详细介绍。主要是靠一个vsdoc文件实现。在vs2010中默认的jquery的版本为1.4.1，现在已经又相对应的vsdoc文件下载，设置方法与vs2008中相同。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.jquery.com/jquery-1.4.1-vsdoc.js"&gt;点击此处下载&lt;/a&gt;
更多详细介绍参考&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/02/08/jquery-1-4-1-intellisense-with-visual-studio.aspx"&gt;http://weblogs.asp.net/scottgu/archive/2010/02/08/jquery-1-4-1-intellisense-with-visual-studio.aspx&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Asp.Net MVC 2 RC 2 发布</title><link>https://fwhyy.com/2010/02/aspnet-mvc-2-rc-2-release/</link><pubDate>Fri, 05 Feb 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/02/aspnet-mvc-2-rc-2-release/</guid><description>&lt;p&gt;刚刚在&lt;a href="http://weblogs.asp.net/scottgu/default.aspx"&gt;ScottGu&lt;/a&gt;的blog上看到了ASP.NET MVC 2 RC 2发布的消息，该版本的IDE只支持VS2008.在该版本中修复了一些bug，并添加修改了一些API。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=7aba081a-19b9-44c4-a247-3882c8f749e3&amp;amp;displaylang=en"&gt;点击下载&lt;/a&gt;
有关此版本详细的介绍请看ScottGu的博文 。&lt;/p&gt;
&lt;p&gt;博客园的SZW对该文进行了翻译 ：&lt;a href="http://www.cnblogs.com/szw/archive/2010/02/05/1664704.html"&gt;http://www.cnblogs.com/szw/archive/2010/02/05/1664704.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;当然也可以稍后访问&lt;a href="http://blog.joycode.com/scottgu"&gt;ScottGu博客&lt;/a&gt;中文版进行了解&lt;/p&gt;</description></item><item><title>设计模式笔记(25)—总结</title><link>https://fwhyy.com/2010/02/design-patterns-notes-25-summary/</link><pubDate>Wed, 03 Feb 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/02/design-patterns-notes-25-summary/</guid><description>&lt;p&gt;断断续续经历了几个月的时间将WebCast的设计模式讲座重新完整听了一遍，并做了笔记，才有了这个设计模式笔记系列，本系列的文章大部分只是给出了基本代码的实现，而并没有去衍生其他的一些例子，笔者认为通过基本的代码实现就能够了解到模式的应用场景，弄出些花哨的例子反倒会让人眼花缭乱，可能并达不到预期的效果，毕竟在实际的应用中我们不是去套用模式。本文作为该系列的最后一篇，将对设计模式做个总结。&lt;/p&gt;
&lt;p&gt;首先看下创建型、结构型、行为型这三种类型的模式的解释&lt;/p&gt;
&lt;h2 id="创建型"&gt;创建型&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Singleton模式解决的是实体对象个数的问题。除了Singleton之外，其他创建型模式解决的都是new所带来的耦合关系。&lt;/li&gt;
&lt;li&gt;Factory Method, Abstract Factory, Builder都需要一个额外的工厂类来负责实例化“易变对象”，而 Prototype则是通过原型 （一个特殊的工厂类）来克隆“易变对象”。&lt;/li&gt;
&lt;li&gt;如果遇到“易变类”，起初的设计通常从FactoryMethod开始，当遇到更多的复杂变化时，再考虑重构为其他三种工厂模式 （Abstract Factory 、Builder 、Prototype ）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="结构型"&gt;结构型&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Adapter模式注重转换接口，将不吻合的接口适配对接。&lt;/li&gt;
&lt;li&gt;Bridge模式注重分离接口与其实现，支持多维度变化。&lt;/li&gt;
&lt;li&gt;Composite模式注重统一接口，将“一对多”的关系转化为“一对一”的关系。&lt;/li&gt;
&lt;li&gt;Decorator模式注重稳定接口，在此前提下为对象扩展功能。&lt;/li&gt;
&lt;li&gt;Façade模式注重简化接口，简化组件系统与外部客户程序的依赖关系。&lt;/li&gt;
&lt;li&gt;Flyweight 模式注重保留接口，在内部使用共享技术对对象存储进行优化。&lt;/li&gt;
&lt;li&gt;Proxy 模式注重假借接口，增加间接层来实现灵活控制。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="行为型"&gt;行为型&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Template Method模式封装算法结构，支持算法子步骤变化。&lt;/li&gt;
&lt;li&gt;Strategy模式注重封装算法，支持算法的变化。&lt;/li&gt;
&lt;li&gt;State模式注重封装与状态相关的行为，支持状态的变化。&lt;/li&gt;
&lt;li&gt;Memento模式注重封装对象状态变化，支持状态保存/恢复。&lt;/li&gt;
&lt;li&gt;Mediator模式注重封装对象间的交互，支持对象交互的变化。&lt;/li&gt;
&lt;li&gt;Chain Of Responsibility模式注重封装对象责任，支持责任的变化。&lt;/li&gt;
&lt;li&gt;Command模式注重将请求封装为对象，支持请求的变化。&lt;/li&gt;
&lt;li&gt;Iterator 模式注重封装集合对象内部结构，支持集合的变化。&lt;/li&gt;
&lt;li&gt;Interpreter模式注重封装特定领域变化，支持领域问题的频繁变化。&lt;/li&gt;
&lt;li&gt;Observer模式注重封装对象通知，支持通信对象的变化。&lt;/li&gt;
&lt;li&gt;Visitor模式注重封装对象操作变化，支持在运行时为类层次结构动态添加新的操作。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="设计模式应用总结"&gt;设计模式应用总结&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;设计模式建立在对系统变化点的基础上进行，哪里有变化点，哪里应用设计模式。&lt;/li&gt;
&lt;li&gt;设计模式应该以演化的方式来获得，系统的变化点往往是经过不断演化才能准确定位。&lt;/li&gt;
&lt;li&gt;不能为了模式而模式，设计模式是一种软件设计的软力量，而非规范标准。不应夸大设计模式的作用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上面的大部分内容都为讲座中的内容，并没有做更多的改动，因为那些概况已经非常简明扼要。软件发展到今天，可以说远远不止这23中模式，只是常常被大家所提及的是这23中经典而已。这些模式的提出时因为软件的需求总是在发生变化，如果说不存在需求的变化，那么设计模式也就没有存在的必要了。这种情况是不可能存在，所以为了在需求变化的时候能够很好的应对，提供代码复用，降低成本就需要应用设计模式。所以说设计模式并不是在软件设计之初就存在，而是随着需求的变化一步一步重构而来的。&lt;/p&gt;
&lt;p&gt;设计模式虽然很多，但万变不离其宗，不管怎么变都脱离不了5大设计原则（SRP OCP LSP DIP ISP），掌握了这五大设计原则，勤思考多实践，那么在项目中遇到变化时就可以灵活运行设计模式了。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>SqlServer数据库的语句及一些操作整理</title><link>https://fwhyy.com/2010/02/some-tips-of-sqlserver/</link><pubDate>Tue, 02 Feb 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/02/some-tips-of-sqlserver/</guid><description>&lt;p&gt;临近年终，在工作之余对工作和学习中遇到的问题以及常用的一些知识点做了些整理，以备后用。本文涉及的内容为数据库,算是对开发总结(1)—数据库一文的补充。&lt;/p&gt;
&lt;p&gt;1 对于主键设置了Identity的表，在删除表中数据后再往表中插入数据，Identity列不是从1起始了，如果想删除数据后Indentity列仍从1起始，可以用下面代码来删除数据。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;truncate table tablename
DBCC CHECKIDENT(tablename,RESEED,1)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 判断指定表在数据库中是否存在&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;if exists(select name from sysobjects where name=&amp;#39;tablename&amp;#39; and type=&amp;#39;u&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;3 判断指定列在指定表中是否存在&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;if exists(select * from sys.columns,sys.tables
 where sys.columns.object_id = sys.tables.object_id
 and sys.tables.name=&amp;#39;tablename&amp;#39; and sys.columns.[name]=&amp;#39;columnname&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;4 在编写代码生成器之类的程序的时候，通常需要取出数据库中所有的表名以及表中字段的一些基本信息，如字段长度、字段类型、描述等。实现上面要求的sql语句如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;--取数据库中表的集合
select * from sysobjects where xtype=&amp;#39;u&amp;#39; order by name

--取表中字段的一些基本信息
select
 sys.columns.name, --字段名
 sys.types.name as typename, --字段类型
 sys.columns.max_length, --字段长度
 sys.columns.is_nullable, --是否可空
 (select
 count(*)
 from
 sys.identity_columns
 where
 sys.identity_columns.object_id = sys.columns.object_id
 and
 sys.columns.column_id = sys.identity_columns.column_id
 ) as is_identity ,--是否自增

 (select
 value
 from
 sys.extended_properties
 where
 sys.extended_properties.major_id = sys.columns.object_id
 and
 sys.extended_properties.minor_id = sys.columns.column_id
 ) as description --注释
from
 sys.columns, sys.tables, sys.types
where
 sys.columns.object_id = sys.tables.object_id
and
 sys.columns.system_type_id=sys.types.system_type_id
and
 sys.tables.name=&amp;#39;tablename&amp;#39;
order by sys.columns.column_id
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5 在存储过程中使用事务&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;create procedure procname
as
begin tran
 --执行sql语句

if @@ERROR!=0
begin
 rollback tran --失败
end
else
begin
 commit tran --成功
end 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;6 清除数据库日志&lt;/p&gt;</description></item><item><title>设计模式笔记(24)—访问者模式（行为型）</title><link>https://fwhyy.com/2010/02/design-patterns-notes-24-visitor-pattern/</link><pubDate>Tue, 02 Feb 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/02/design-patterns-notes-24-visitor-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;表示一个作用于某对象结构中的各元素的操作。它可以在不改变各元素的类的前提下定义作用于这些元素的新的操作。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，由于需求的改变，某些类层次结构中常常需要增加新的行为（方法），如果直接在基类中做这样的更改，将会给子类带来很繁重的变更负担，甚至破坏原有设计。如何在不更改类层次结构的前提下，在运行时根据需要透明地为类层次结构上的各个类动态添加新的操作，从而避免上述问题？请看下面访问者模式结构图和代码。&lt;/p&gt;
&lt;p&gt;访问者模式结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290611525.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;基本代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 声明了一个或多个需要添加的操作
/// &amp;lt;/summary&amp;gt;
public abstract class Visitor
{
 public abstract void VisitorConcreteElementA(ConcreteElementA concreteElementA);
 public abstract void VisitorConcreteElementB(ConcreteElementB concreteElementB);
}
/// &amp;lt;summary&amp;gt;
/// 操作的具体类1
/// &amp;lt;/summary&amp;gt;
public class ConcreteVisitor1:Visitor
{
 public override void VisitorConcreteElementA(ConcreteElementA concreteElementA)
 {
 Console.WriteLine(&amp;#34;{0}访问{1}&amp;#34;, this.GetType().Name, concreteElementA.GetType().Name);
 }
 public override void VisitorConcreteElementB(ConcreteElementB concreteElementB)
 {
 Console.WriteLine(&amp;#34;{0}访问{1}&amp;#34;, this.GetType().Name, concreteElementB.GetType().Name);
 }
}
/// &amp;lt;summary&amp;gt;
/// 操作的具体类2
/// &amp;lt;/summary&amp;gt;
public class ConcreteVisitor2 : Visitor
{
 public override void VisitorConcreteElementA(ConcreteElementA concreteElementA)
 {
 Console.WriteLine(&amp;#34;{0}访问{1}&amp;#34;, this.GetType().Name, concreteElementA.GetType().Name);
 }
 public override void VisitorConcreteElementB(ConcreteElementB concreteElementB)
 {
 Console.WriteLine(&amp;#34;{0}访问{1}&amp;#34;, this.GetType().Name, concreteElementB.GetType().Name);
 }
}
/// &amp;lt;summary&amp;gt;
/// 接受Visitor并使用其操作的抽象类
/// &amp;lt;/summary&amp;gt;
public abstract class Element
{
 public abstract void Accept(Visitor visitor);
}
/// &amp;lt;summary&amp;gt;
/// 接受Visitor并使用其操作的具体类
/// &amp;lt;/summary&amp;gt;
public class ConcreteElementA : Element
{
 public override void Accept(Visitor visitor)
 {
 visitor.VisitorConcreteElementA(this);
 }
 public void OperationA() { }
}
/// &amp;lt;summary&amp;gt;
/// 接受Visitor并使用其操作的具体类
/// &amp;lt;/summary&amp;gt;
public class ConcreteElementB : Element
{
 public override void Accept(Visitor visitor)
 {
 visitor.VisitorConcreteElementB(this);
 }
 public void OperationB() { }
}
public class ObjectStructure
{
 private List&amp;lt;Element&amp;gt; list = new List&amp;lt;Element&amp;gt;();
 public void Add(Element element)
 {
 list.Add(element);
 }
 public void Del(Element element)
 {
 if(list.Contains(element))
 list.Remove(element);
 }
 public void Accept(Visitor visitor)
 {
 foreach (Element e in list)
 {
 e.Accept(visitor);
 }
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端代码
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 ObjectStructure os = new ObjectStructure();
 os.Add(new ConcreteElementA());
 os.Add(new ConcreteElementB());
 Visitor cv1 = new ConcreteVisitor1();
 Visitor cv2 = new ConcreteVisitor2();
 os.Accept(cv2);
 os.Accept(cv1);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="visitor模式的几个要点"&gt;Visitor模式的几个要点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Visitor模式通过所谓双重分发（double dispatch）来实现在不更改Element类层次结构的前提下，在运行时透明地为类层次结构上的各个类动态添加新的操作。&lt;/li&gt;
&lt;li&gt;Visitor模式通过所谓双重分发（double dispatch）来实现在不更改Element类层次结构的前提下，在运行时透明地为类层次结构上的各个类动态添加新的操作。&lt;/li&gt;
&lt;li&gt;Visitor模式的最大缺点在于扩展类层次结构（增添新的Element子类），会导致Visitor类的改变。因此Vistor模式适用于“Element类层次结构稳定，而其中的操作却经常面临频繁改动”。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>设计模式笔记(23)—策略者模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-23-strategy-pattern/</link><pubDate>Sun, 31 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-23-strategy-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;定义一系列算法，把它们一个个封装起来，并且使它们可互相替换。该模式使得算法可独立于使用它的客 户而变化。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，某些对象使用的算法可能多种多样，经常改变，如果将这些算法都编码到对象中，将会使对象变得异常复杂；而且有时候支持不使用的算法也是一个性能负担。如何在运行时根据需要透明地更改对象的算法？将算法与对象本身解耦，从而避免上述问题？看下面的策略者模式的结构图和基本代码，策略者模式比较简单，下面只是给出基本的代码实现。&lt;/p&gt;
&lt;p&gt;策略者模式结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290610502.webp" alt="image-20220129061002254" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;基本实现代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 抽象算法类
/// &amp;lt;/summary&amp;gt;
public abstract class Strategy
{
 //抽象算法方法
 public abstract void AlgorithmInterface();
}
/// &amp;lt;summary&amp;gt;
/// 具体算法A
/// &amp;lt;/summary&amp;gt;
public class ConcretestrategyA : Strategy
{
 public override void AlgorithmInterface()
 {
 Console.WriteLine(&amp;#34;算法A的实现&amp;#34;);
 }
}
/// &amp;lt;summary&amp;gt;
/// 具体算法B
/// &amp;lt;/summary&amp;gt;
public class ConcretestrategyB : Strategy
{
 public override void AlgorithmInterface()
 {
 Console.WriteLine(&amp;#34;算法B的实现&amp;#34;);
 }
}
/// &amp;lt;summary&amp;gt;
/// 具体算法C
/// &amp;lt;/summary&amp;gt;
public class ConcretestrategyC : Strategy
{
 public override void AlgorithmInterface()
 {
 Console.WriteLine(&amp;#34;算法C的实现&amp;#34;);
 }
}
/// &amp;lt;summary&amp;gt;
/// 上下文
/// &amp;lt;/summary&amp;gt;
public class Context
{
 private Strategy _strategy;
 public Context(Strategy stragtety)
 {
 this._strategy = stragtety;
 }
 public void ContextInterface()
 {
 _strategy.AlgorithmInterface();
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端代码
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 Context context;
 context = new Context(new ConcretestrategyA());
 context.ContextInterface();
 context = new Context(new ConcretestrategyB());
 context.ContextInterface();
 context = new Context(new ConcretestrategyC());
 context.ContextInterface();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;运行结果如下：&lt;/p&gt;</description></item><item><title>设计模式笔记(22)—状态模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-22-state-pattern/</link><pubDate>Thu, 28 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-22-state-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，某些对象的状态如果改变，其行为也会随之而发生变化，比如文档处于只读状态，其支持的行为和读写状态支持的行为就可能完全不同。如何在运行时根据对象的状态来透明地更改对象的行为？而不会为对象操作和状态转化之间引入紧耦合？看下面状态模式的结构图和代码。&lt;/p&gt;
&lt;p&gt;状态模式结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290611919.webp" alt="2010-12-29_110619" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;日常生活中我们常见的灯会有两种状态开和关，当灯亮着时我们可以用开关使之熄灭，反之则变量，看下面的代码就是改变灯的开关状态的一个过程：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 灯的状态开和关
/// &amp;lt;/summary&amp;gt;
public enum LightState
{
 On,
 Off
}
public class ChangeLightState
{
 private LightState _state = LightState.On;
 public LightState Change()
 {
 if (_state == LightState.On)
 {
 _state = LightState.Off;
 }
 else if (_state == LightState.Off)
 {
 _state = LightState.On;
 }
 return _state;
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端程序
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 ChangeLightState l = new ChangeLightState();
 l.Change();
 l.Change();
 l.Change();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码使用if语句来解决了灯开关状态的问题，不过在实际开发中的一些状态不可能是简单的枚举，这时如果依然使用if语句就会显得比较复杂，而且随着状态的改变会频繁进行修改if语句。所以需要将状态转换和处理的变化封装在抽象后的具体类中，看上面结构图的对应代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class State
{
 public abstract void Handle(Context context);
}
public class ConcreteStateA : State
{
 public override void Handle(Context context)
 {
 context.State = new ConcreteStateB();
 }
}
public class ConcreteStateB : State
{
 public override void Handle(Context context)
 {
 context.State = new ConcreteStateA();
 }
}
public class Context
{
 private State _state;
 public Context(State state)
 {
 this._state = state;
 }
 public State State
 {
 get { return _state; }
 set { _state = value;}
 }
 public void Request()
 {
 _state.Handle(this);
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端程序
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 Context context = new Context(new ConcreteStateA());
 context.Request();
 context.Request();
 context.Request();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;根据状态模式将上面的灯开关的代码改进如下：&lt;/p&gt;</description></item><item><title>设计模式笔记(20)—职责链模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-20-chain-of-responsibility-pattern/</link><pubDate>Wed, 27 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-20-chain-of-responsibility-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;使多个对象都有机会处理请求，从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链，并沿着这条链传递请求，直到有一个对象处理它为止。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，一个请求可能被多个对象处理，但是每个请求在运行时只能有一个接受者，如果显式指定，将必不可少地带来请求发送者与接受者的紧耦合。如何使请求的发送者不需要指定具体的接受者？让请求的接受者自己在运行时决定来处理请求，从而使两者解耦。&lt;/p&gt;
&lt;p&gt;职责链模式结构图如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290613054.webp" alt="2010-12-29_111712" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;代码实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 抽象处理类
/// &amp;lt;/summary&amp;gt;
public abstract class BaseHandler
{
 public BaseHandler(BaseHandler next)
 {
 this.Next = next;
 }
 public BaseHandler Next { get; set; }
 protected abstract bool CanHandleRequest(Request request);
 public virtual void HandleRequest(Request request)
 {
 if (Next != null)
 {
 this.Next.HandleRequest(request);
 }
 }
}
public class AHandler:BaseHandler
{
 public AHandler(BaseHandler next)
 : base(next)
 {

 }
 protected override bool CanHandleRequest(Request request)
 {
 return request.Name == &amp;#34;A&amp;#34;;
 }
 public override void HandleRequest(Request request)
 {
 if (this.CanHandleRequest(request))
 {
 Console.WriteLine(&amp;#34;处理A的请求&amp;#34;);
 }
 else
 {
 base.HandleRequest(request);
 }
 }
}
public class BHandler : BaseHandler
{
 public BHandler(BaseHandler next)
 : base(next)
 {

 }
 protected override bool CanHandleRequest(Request request)
 {
 return request.Name == &amp;#34;B&amp;#34;;
 }
 public override void HandleRequest(Request request)
 {
 if (this.CanHandleRequest(request))
 {
 Console.WriteLine(&amp;#34;处理B的请求&amp;#34;);
 }
 else
 {
 base.HandleRequest(request);
 }
 }
}
public class CHandler : BaseHandler
{
 public CHandler(BaseHandler next)
 : base(next)
 {

 }
 protected override bool CanHandleRequest(Request request)
 {
 return request.Name == &amp;#34;C&amp;#34;;
 }
 public override void HandleRequest(Request request)
 {
 if (this.CanHandleRequest(request))
 {
 Console.WriteLine(&amp;#34;处理C的请求&amp;#34;);
 }
 else
 {
 base.HandleRequest(request);
 }
 }
}
public class Sender
{
 public Request _request;
 public Sender(Request request)
 {
 this._request = request;
 }
 public void Process(BaseHandler handler)
 {
 handler.HandleRequest(_request);
 }
}
/// &amp;lt;summary&amp;gt;
/// 请求的信息类
/// &amp;lt;/summary&amp;gt;
public class Request
{
 public string Name { get; set; }
 public Request(string name)
 {
 this.Name = name;
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端程序
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 Sender sender = new Sender(new Request(&amp;#34;A&amp;#34;));
 BaseHandler handler1 = new AHandler(null);
 BaseHandler handler2 = new BHandler(handler1);
 BaseHandler handler3 = new CHandler(handler2);
 sender.Process(handler3);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="chain-of-responsibility模式的几个要点"&gt;Chain of Responsibility模式的几个要点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Chain of Responsibility 模式的应用场合在于“一个请求可能有多个接受者，但是最后真正的接受者只有一个”，只有这时候请求发送者与接受者的耦合才有可能出现“变化脆弱”的症状，职责链的目的就是将二者解耦，从而更好地应对变化。&lt;/li&gt;
&lt;li&gt;应用了Chain of Responsibility 模式后，对象的职责分派将更具灵活性。我们可以在运行时动态添加/修改请求的处理职责。&lt;/li&gt;
&lt;li&gt;如果请求传递到职责链的末尾仍得不到处理，应该有一个合理的缺省机制。这也是每一个接受对象的责任，而不是发出请求的对象的责任&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>设计模式笔记(21)—备忘录模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-21-memo-pattern/</link><pubDate>Wed, 27 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-21-memo-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;在不破坏封装性的前提下，捕获一个对象的内部状态，并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，某些对象的状态在转换过程中，可能由于某种需要，要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些公有接口来让其他对象得到对象的状态，便会暴露对象的细节实现。如何实现对象状态的良好保存与恢复？但同时又不会因此而破坏对象本身的封装性，看下面的结构图和代码。&lt;/p&gt;
&lt;p&gt;备忘录模式结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290613625.webp" alt="2010-12-29_111357" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;上图中Originator为原发器，也可以讲发起者，可以创建一个备忘录（CreateMemento），Memento为备忘录，负责存储原发器中的内部状态。Caretaker主要负责存储备忘录。代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 备忘录类
/// &amp;lt;/summary&amp;gt;
public class Memento
{
 private string _state;
 public string State
 {
 get{return _state;}
 }
 public Memento(string state)
 {
 this._state = state;
 }
}
/// &amp;lt;summary&amp;gt;
/// 原发器类
/// &amp;lt;/summary&amp;gt;
public class Originator
{
 public string State { get; set; }
 public Memento CreateMemento()
 {
 return new Memento(State);
 }
 public void SetMemento(Memento memento)
 {
 State = memento.State;
 }
}
/// &amp;lt;summary&amp;gt;
/// 管理者
/// &amp;lt;/summary&amp;gt;
public class Caretaker
{
 public Memento Memento { get; set; }
}
/// &amp;lt;summary&amp;gt;
/// 客户端程序
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 //实例化原发器并设置状态名称
 Originator o = new Originator();
 o.State = &amp;#34;oec2003&amp;#34;;
 Console.WriteLine(&amp;#34;设置状态名字为:&amp;#34; + o.State);
 //实例化管理者，创建一个备忘储存在管理者中
 Caretaker c = new Caretaker();
 c.Memento = o.CreateMemento();
 //更改了原发器的状态名称
 o.State = &amp;#34;oec2004&amp;#34;;
 Console.WriteLine(&amp;#34;改后的状态名字为:&amp;#34; + o.State);
 //将备忘信息设置给原发器
 o.SetMemento(c.Memento);
 Console.WriteLine(&amp;#34;原来的状态名字为:&amp;#34; + o.State);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="memento模式的几个要点"&gt;Memento模式的几个要点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;备忘录（Memento）存储原发器（Originator）对象的内部状态，在需要时恢复原发器状态。Memento模式适用于“由原发器管理，却又必须存储在原发器之外的信息”。&lt;/li&gt;
&lt;li&gt;在实现Memento模式中，要防止原发器以外的对象访问备忘录对象。备忘录对象有两个接口，一个为原发器使用的宽接口；一个为其他对象使用的窄接口。&lt;/li&gt;
&lt;li&gt;在实现Memento模式时，要考虑拷贝对象状态的效率问题，如果对象开销比较大，可以采用某种增量式改变来改进Memento模式。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>设计模式笔记(19)—观察者模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-19-observer-pattern/</link><pubDate>Mon, 25 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-19-observer-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;定义对象间的一种一对多的依赖关系，以便当一个对象的状态发生改变时，所有依赖于它的对象都得到通 知并自动更新&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，我们需要为某些对象建立一种“通知依赖关系” ——一个对象（目标对象）的状态发生改变，所有的依赖对象（观察者对象）都将得到通知。如果这样的依赖关系过于紧密，将使软件不能很好地抵御变化。使用面向对象技术，可以将这种依赖关系弱化，并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。&lt;/p&gt;
&lt;p&gt;看这样一个场景，银行的ATM机在处理完成银行账户的存入或取出后会给用户发送手机短信和电子邮件，那么就会有这样三个对象，BankAccount Emailer Mobile，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class BankAccount
{
 Emailer emailer;
 Mobile mobile;
 public void Withdraw(int data)
 {
 //处理存入或取出
 emailer.SendEmail(&amp;#34;&amp;#34;);
 mobile.SendMsg(&amp;#34;&amp;#34;);
 }
}
public class Emailer
{
 public void SendEmail(string to)
 {
 //发送邮件
 }
}
public class Mobile
{
 public void SendMsg(string phoneNumber)
 {
 //发送短信
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码中BankAccount和Emailer Mobile之间有很强的依赖关系，Emailer和Mobile的变化会对BankAccount产生很大的影响，接下来要做的就是使BankAccount不要去依赖Emailer和Mobile这样的具体类，而应该去依赖他们的抽象，抽象的东西通常是稳定的，这样BankAccount和抽象之间的依赖就是一种比较弱的依赖关系，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class UserAccountArgs
{
 public string Email { get; set; }
 public string PhoneNumber { get; set; }
 public UserAccountArgs(string email, string phoneNumer)
 {
 Email = email;
 PhoneNumber = phoneNumer;
 }
}
public interface IAccountObserver
{
 void Update(UserAccountArgs args);
}
public class Emailer : IAccountObserver
{
 public void Update(UserAccountArgs args)
 {
 Console.WriteLine(&amp;#34;消息已发送邮件至邮箱：&amp;#34; + args.Email);
 }
}
public class Mobile : IAccountObserver
{
 public void Update(UserAccountArgs args)
 {
 Console.WriteLine(&amp;#34;消息已发短信至手机：&amp;#34; + args.PhoneNumber);
 }
}
public class BankAccount
{
 List&amp;lt;IAccountObserver&amp;gt; list = new List&amp;lt;IAccountObserver&amp;gt;();
 public void Withdraw(int data)
 {
 //处理存入或取出
 if(data&amp;gt;0)
 {
 Console.WriteLine(&amp;#34;您的账户存入了&amp;#34;+data+&amp;#34;元&amp;#34;);
 }
 else
 {
 Console.WriteLine(&amp;#34;您的账户取出了&amp;#34; + Math.Abs(data) + &amp;#34;元&amp;#34;);
 }
 UserAccountArgs args = 
new UserAccountArgs(&amp;#34;oec2003@gmail.com&amp;#34;,&amp;#34;1388888****&amp;#34;);
 foreach (IAccountObserver observer in list)
 {
 observer.Update(args);
 }
 }
 public void AddObserver(IAccountObserver observer)
 {
 list.Add(observer);
 }
 public void RemoveObserver(IAccountObserver observer)
 {
 list.Remove(observer);
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端调用
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 BankAccount bankAccount = new BankAccount();
 bankAccount.AddObserver(new Emailer());
 bankAccount.AddObserver(new Mobile());
 bankAccount.Withdraw(-500);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;运行结果如下：&lt;/p&gt;</description></item><item><title>设计模式笔记(18)—迭代器模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-18-iterator-pattern/</link><pubDate>Sun, 24 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-18-iterator-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;提供一种方法顺序访问一个聚合对象中的各个元素， 而又不暴露该对象的内部表示。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，集合对象内部结构常常变化各异。但对于这些集合对象，我们希望在不暴露其内部结构的同时，可以让外部客户代码透明地访问其中包含的元素；同时这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供了可能。使用面向对象技术将这种遍历机制抽象为“迭代器对象”为“应对变化中的集合对象”提供了一种优雅的方式。&lt;/p&gt;</description></item><item><title>Lable和Literal控件的使用和区别</title><link>https://fwhyy.com/2010/01/the-use-of-the-lable-and-literal-controls-and-differences/</link><pubDate>Sat, 23 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/the-use-of-the-lable-and-literal-controls-and-differences/</guid><description>&lt;p&gt;Lable和Literal这两个控件是我们非常熟悉的两个控件，都是用作内容呈现用的，但他们之间也有不同之处，分别应用于不同的地方。Lable控件会将内容呈现在html标签span中，即Lable控件的Text属性的值会包含在&lt;span&gt;标签中。而Literal控件生成的代码则比较干净，它的Text属性的值将直接显示在页面中，看下面两段代码：&lt;/p&gt;
&lt;p&gt;Lable：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;asp:Label ID=&amp;#34;lblUserName&amp;#34; runat=&amp;#34;server&amp;#34; Text=&amp;#34;用户名&amp;#34;&amp;gt;&amp;lt;/asp:Label&amp;gt;
&amp;lt;asp:TextBox ID=&amp;#34;txtUserName&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;&amp;lt;/asp:TextBox&amp;gt;&amp;lt;br /&amp;gt;
&amp;lt;asp:Label ID=&amp;#34;lblPwd&amp;#34; runat=&amp;#34;server&amp;#34; Text=&amp;#34;密码&amp;#34;&amp;gt;&amp;lt;/asp:Label&amp;gt;
&amp;lt;asp:TextBox ID=&amp;#34;txtPwd&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;&amp;lt;/asp:TextBox&amp;gt;&amp;lt;br /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Literal：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;asp:Literal runat=&amp;#34;server&amp;#34; ID=&amp;#34;litUserName&amp;#34; Text=&amp;#34;用户名&amp;#34;&amp;gt;&amp;lt;/asp:Literal&amp;gt;
&amp;lt;asp:TextBox ID=&amp;#34;txtUserName1&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;&amp;lt;/asp:TextBox&amp;gt;&amp;lt;br /&amp;gt;
&amp;lt;asp:Literal runat=&amp;#34;server&amp;#34; ID=&amp;#34;litPwd&amp;#34; Text=&amp;#34;密码&amp;#34;&amp;gt;&amp;lt;/asp:Literal&amp;gt;
&amp;lt;asp:TextBox ID=&amp;#34;txtPwd1&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;&amp;lt;/asp:TextBox&amp;gt;&amp;lt;br /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面两段程序运行的结果都如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201302120262.webp" alt="2010-12-29_1138351" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;再来看看上面的代码生成的源码：&lt;/p&gt;
&lt;p&gt;Lable&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;span id=&amp;#34;lblUserName&amp;#34;&amp;gt;用户名&amp;lt;/span&amp;gt;
&amp;lt;input name=&amp;#34;txtUserName&amp;#34; type=&amp;#34;text&amp;#34; id=&amp;#34;txtUserName&amp;#34; /&amp;gt;&amp;lt;br /&amp;gt;
&amp;lt;span id=&amp;#34;lblPwd&amp;#34;&amp;gt;密码&amp;lt;/span&amp;gt;
&amp;lt;input name=&amp;#34;txtPwd&amp;#34; type=&amp;#34;text&amp;#34; id=&amp;#34;txtPwd&amp;#34; /&amp;gt;&amp;lt;br /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Literal&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;用户名
&amp;lt;input name=&amp;#34;txtUserName1&amp;#34; type=&amp;#34;text&amp;#34; id=&amp;#34;txtUserName1&amp;#34; /&amp;gt;&amp;lt;br /&amp;gt;
密码
&amp;lt;input name=&amp;#34;txtPwd1&amp;#34; type=&amp;#34;text&amp;#34; id=&amp;#34;txtPwd1&amp;#34; /&amp;gt;&amp;lt;br /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;从源码中可以很清楚看出Lable最终在客户端会生成Span标签，而Literal则直接显示文本，记得曾经维护过的一个自定义控件，在不同留言器中有样式问题，调试很久最终发现就是Lable生成的Span惹的祸，最终换成Literal得以解决，所以后来但凡要显示文本的地方我基本都是用Literal。不过Lable也不是一无是处，Lable控件有一个AssociatedControlID，可以将该属性指向一个表单控件的ID，通常为TextBox，看下面代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;asp:Label ID=&amp;#34;lblUserName&amp;#34; runat=&amp;#34;server&amp;#34; AssociatedControlID=&amp;#34;txtUserName&amp;#34; Text=&amp;#34;用户名&amp;#34;&amp;gt;&amp;lt;/asp:Label&amp;gt;
&amp;lt;asp:TextBox ID=&amp;#34;txtUserName&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;&amp;lt;/asp:TextBox&amp;gt;&amp;lt;br /&amp;gt;
&amp;lt;asp:Label ID=&amp;#34;lblPwd&amp;#34; runat=&amp;#34;server&amp;#34; AssociatedControlID=&amp;#34;txtPwd&amp;#34; Text=&amp;#34;密码&amp;#34;&amp;gt;&amp;lt;/asp:Label&amp;gt;
&amp;lt;asp:TextBox ID=&amp;#34;txtPwd&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;&amp;lt;/asp:TextBox&amp;gt;&amp;lt;br /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;和上面的代码基本一样只是添加了AssociatedControlID属性，分别指向了两个TextBox控件的ID，添加了这个属性后生成的源码就变了，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;label for=&amp;#34;txtUserName&amp;#34; id=&amp;#34;lblUserName&amp;#34;&amp;gt;用户名&amp;lt;/label&amp;gt;
&amp;lt;input name=&amp;#34;txtUserName&amp;#34; type=&amp;#34;text&amp;#34; id=&amp;#34;txtUserName&amp;#34; /&amp;gt;&amp;lt;br /&amp;gt;
&amp;lt;label for=&amp;#34;txtPwd&amp;#34; id=&amp;#34;lblPwd&amp;#34;&amp;gt;密码&amp;lt;/label&amp;gt;
&amp;lt;input name=&amp;#34;txtPwd&amp;#34; type=&amp;#34;text&amp;#34; id=&amp;#34;txtPwd&amp;#34; /&amp;gt;&amp;lt;br /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;可以看出有Span标签变成了lable标签 for属性指向了TextBox的id。AssociatedControlID属性的使用能够给残障人士带来方便，如果使用读屏器之类的辅助设备来和网站进行交互，AssociatedControlID属性能帮助辅助设备将标签和字段关联起来。除此之外还有一个好处就是当点击标签时，所关联的TextBox就会获得焦点。&lt;/p&gt;
&lt;p&gt;由于Lable控件的内容最终呈现在Span标签中，所以Lable控件也支持Span标签的一些属性，如BackColor，CssClass等。Literal控件不生成Span标签，当然也不支持那些属性，不过Literal控件有个Mode属性，该属性有三个值&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Encode ：在编码Html内容后再显示控件的内容&lt;/li&gt;
&lt;li&gt;PassThrough ：显示控件的内容不进行编码&lt;/li&gt;
&lt;li&gt;Transform ：清除一些不支持的标记后在呈现内容&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;看下面的代码：&lt;/p&gt;</description></item><item><title>设计模式笔记(17)—中介者模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-17-mediator-pattern/</link><pubDate>Wed, 20 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-17-mediator-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式的相互引用，从而使其耦合松散，而且可以独立地改变它们之间的交互。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，经常会出现多个对象互相关联交互的情况，对象之间常常会维持一种复杂的引用关系，如果遇到一些需求的更改，这种直接的引用关系将面临不断的变化。在这种情况下，我们可使用一个“中介对象”来管理对象间的关联关系，避免相互交互的对象之间的紧耦合引用关系，从而更好地抵御变化。&lt;/p&gt;
&lt;p&gt;中介者模式的结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290617750.webp" alt="2010-12-29_114801" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;代码实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 抽象的中介者
/// &amp;lt;/summary&amp;gt;
public abstract class Mediator
{
 public abstract void Send(string msg, Colleague colleague);
}
/// &amp;lt;summary&amp;gt;
/// 抽象的同事类
/// &amp;lt;/summary&amp;gt;
public abstract class Colleague
{
 protected Mediator _mediator;
 public Colleague(Mediator mediator)
 {
 _mediator = mediator;
 }
}
/// &amp;lt;summary&amp;gt;
/// 具体的中介者对象
/// &amp;lt;/summary&amp;gt;
public class ConcreteMediator : Mediator
{
 public ConcreteCollegue1 Colleague1 { get; set; }
 public ConcreteCollegue2 Colleague2 { get; set; }
 public override void Send(string msg, Colleague colleague)
 {
 if (colleague == Colleague1)
 {
 Colleague2.Notify(msg);
 }
 else
 {
 Colleague1.Notify(msg);
 }
 }
}
/// &amp;lt;summary&amp;gt;
/// 具体的同事类1
/// &amp;lt;/summary&amp;gt;
public class ConcreteCollegue1:Colleague
{
 public ConcreteCollegue1(Mediator mediator)
 : base(mediator)
 {

 }

 public void Send(string msg)
 {
 _mediator.Send(msg,this);
 }
 public void Notify(string msg)
 {
 Console.WriteLine(&amp;#34;通知同事1：&amp;#34;+msg);
 }
}
/// &amp;lt;summary&amp;gt;
/// 具体的同事类2
/// &amp;lt;/summary&amp;gt;
public class ConcreteCollegue2:Colleague
{
 public ConcreteCollegue2(Mediator mediator)
 : base(mediator)
 {

 }

 public void Send(string msg)
 {
 _mediator.Send(msg,this);
 }
 public void Notify(string msg)
 {
 Console.WriteLine(&amp;#34;通知同事2：&amp;#34;+msg);
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端调用
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 ConcreteMediator cm = new ConcreteMediator();
 ConcreteCollegue1 cc1 = new ConcreteCollegue1(cm);
 ConcreteCollegue2 cc2 = new ConcreteCollegue2(cm);
 cm.Colleague1 = cc1;
 cm.Colleague2 = cc2;
 cc1.Send(&amp;#34;看阿凡达了吗？&amp;#34;);
 cc2.Send(&amp;#34;呵呵，周末公司组织去看。&amp;#34;);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="mediator模式的几个要点"&gt;Mediator模式的几个要点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;将多个对象间复杂的关联关系解耦，Mediator模式将多个对象间的控制逻辑进行集中管理，变“多个对象互相关联”为“多个对象和一个中介者关联”，简化了系统的维护，抵御了可能的变化。&lt;/li&gt;
&lt;li&gt;随着控制逻辑的复杂化，Mediator具体对象的实现可能相当复杂。这时候可以对Mediator对象进行分解处理。&lt;/li&gt;
&lt;li&gt;Façade模式是解耦系统外到系统内（单向）的对象关联关系；Mediator模式是解耦系统内各个对象之间（双向）的关联关系。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>设计模式笔记(16)—解释器模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-16-interpreter-pattern/</link><pubDate>Tue, 19 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-16-interpreter-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;给定一个语言，定义它的文法的一种表示，并定义一种解释器，这个解释器使用该表示来解释语言中的句 子。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，如果某一特定领域的问题比较复杂，类似的模式不断重复出现，如果使用普通的编程方式来实现将面临非常频繁的变化。在这种情况下，将特定领域的问题表达为某种语法规则下的句子，然后构建一个解释器来解释这样的句子，从而达到解决问题的目的。&lt;/p&gt;
&lt;p&gt;下面看下解释器模式的结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290616838.webp" alt="2010-12-29_115427" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;基本代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 上下文信息
/// &amp;lt;/summary&amp;gt;
public class Context
{
 public string Data { get; set; }
}
/// &amp;lt;summary&amp;gt;
/// 抽象表达式，声明一个抽象的解释操作
/// &amp;lt;/summary&amp;gt;
public abstract class AbstractExpression
{
 public abstract void Interpret(Context context);
}
public class TerminalExpression:AbstractExpression
{
 public override void Interpret(Context context)
 {
 context.Data += &amp;#34;终端,&amp;#34;;
 }
}
public class NonterminalExpression : AbstractExpression
{
 public override void Interpret(Context context)
 {
 context.Data += &amp;#34;非终端,&amp;#34;;
 }
}
public class App
{
 static void Main(string[] args)
 {
 Context context = new Context();
 List&amp;lt;AbstractExpression&amp;gt; list = new List&amp;lt;AbstractExpression&amp;gt;();
 list.Add(new TerminalExpression());
 list.Add(new NonterminalExpression());
 list.Add(new TerminalExpression());

 foreach (AbstractExpression exp in list)
 {
 exp.Interpret(context);
 }
 Console.WriteLine(context.Data);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;接下来看一个实际的应用，功能是数字的转换，如将“五百二十”转换成“520“，首先创建一个Context类用来储存上下文信息，类中有两个属性Statement和Data，分别用来存放汉字的数字和阿拉伯数字。&lt;/p&gt;</description></item><item><title>jQuery上传插件Uploadify使用详解</title><link>https://fwhyy.com/2010/01/jquery-upload-plugin-uploadify-use-explanation/</link><pubDate>Wed, 06 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/jquery-upload-plugin-uploadify-use-explanation/</guid><description>&lt;h2 id="本文uploadify版本为210已经过时截止2016-09-25最新版本321的详细介绍请移步jquery上传插件uploadify使用详解321"&gt;本文Uploadify版本为2.1.0，已经过时，截止（2016-09-25）最新版本3.2.1的详细介绍请移步《&lt;a href="http://fwhyy.com/2016/09/jquery-upload-plugin-uploadify-3-2-1-use-explanation/"&gt;jQuery上传插件Uploadify使用详解(3.2.1)&lt;/a&gt;》&lt;/h2&gt;
&lt;p&gt;Uploadify是jQuery的一个上传插件，实现的效果非常不错，带进度显示。不过官方提供的实例时php版本的，本文将详细介绍Uploadify在Aspnet中的使用，您也可以点击下面的链接进行演示或下载。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.uploadify.com/download"&gt;官方下载&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.uploadify.com/documentation"&gt;官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.uploadify.com/demo"&gt;官方演示&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;首先按下面的步骤来实现一个简单的上传功能。&lt;/p&gt;
&lt;p&gt;1 创建Web项目，命名为JQueryUploadDemo，从官网上下载最新的版本解压后添加到项目中。&lt;/p&gt;
&lt;p&gt;2 在项目中添加UploadHandler.ashx文件用来处理文件的上传。&lt;/p&gt;
&lt;p&gt;3 在项目图:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300722377.webp" alt="2010-12-29_120720" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;4 Default.aspx的html页的代码修改如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;html xmlns=&amp;#34;http://www.w3.org/1999/xhtml&amp;#34;&amp;gt;
&amp;lt;head runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;title&amp;gt;Uploadify&amp;lt;/title&amp;gt;
 &amp;lt;link href=&amp;#34;JS/jquery.uploadify-v2.1.0/example/css/default.css&amp;#34;
 rel=&amp;#34;stylesheet&amp;#34; type=&amp;#34;text/css&amp;#34; /&amp;gt;
 &amp;lt;link href=&amp;#34;JS/jquery.uploadify-v2.1.0/uploadify.css&amp;#34;
 rel=&amp;#34;stylesheet&amp;#34; type=&amp;#34;text/css&amp;#34; /&amp;gt;

 &amp;lt;script type=&amp;#34;text/javascript&amp;#34;
 src=&amp;#34;JS/jquery.uploadify-v2.1.0/jquery-1.3.2.min.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;

 &amp;lt;script type=&amp;#34;text/javascript&amp;#34;
 src=&amp;#34;JS/jquery.uploadify-v2.1.0/swfobject.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;

 &amp;lt;script type=&amp;#34;text/javascript&amp;#34;
 src=&amp;#34;JS/jquery.uploadify-v2.1.0/jquery.uploadify.v2.1.0.min.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;

 &amp;lt;script type=&amp;#34;text/javascript&amp;#34;&amp;gt;
 $(document).ready(function()
 {
 $(&amp;#34;#uploadify&amp;#34;).uploadify({
 &amp;#39;uploader&amp;#39;: &amp;#39;JS/jquery.uploadify-v2.1.0/uploadify.swf&amp;#39;,
 &amp;#39;script&amp;#39;: &amp;#39;UploadHandler.ashx&amp;#39;,
 &amp;#39;cancelImg&amp;#39;: &amp;#39;JS/jquery.uploadify-v2.1.0/cancel.png&amp;#39;,
 &amp;#39;folder&amp;#39;: &amp;#39;UploadFile&amp;#39;,
 &amp;#39;queueID&amp;#39;: &amp;#39;fileQueue&amp;#39;,
 &amp;#39;auto&amp;#39;: false,
 &amp;#39;multi&amp;#39;: true
 });
 });
 &amp;lt;/script&amp;gt;

&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
 &amp;lt;div id=&amp;#34;fileQueue&amp;#34;&amp;gt;&amp;lt;/div&amp;gt;
 &amp;lt;input type=&amp;#34;file&amp;#34; name=&amp;#34;uploadify&amp;#34; id=&amp;#34;uploadify&amp;#34; /&amp;gt;
 &amp;lt;p&amp;gt;
 &amp;lt;a href=&amp;#34;javascript:$(&amp;#39;#uploadify&amp;#39;).uploadifyUpload()&amp;#34;&amp;gt;上传&amp;lt;/a&amp;gt;|
 &amp;lt;a href=&amp;#34;javascript:$(&amp;#39;#uploadify&amp;#39;).uploadifyClearQueue()&amp;#34;&amp;gt;取消上传&amp;lt;/a&amp;gt;
 &amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5 UploadHandler类的ProcessRequest方法代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public void ProcessRequest(HttpContext context)
{
 context.Response.ContentType = &amp;#34;text/plain&amp;#34;;
 context.Response.Charset = &amp;#34;utf-8&amp;#34;; 

 HttpPostedFile file = context.Request.Files[&amp;#34;Filedata&amp;#34;];
 string uploadPath =
 HttpContext.Current.Server.MapPath(@context.Request[&amp;#34;folder&amp;#34;])+&amp;#34;\\&amp;#34;; 

 if (file != null)
 {
 if (!Directory.Exists(uploadPath))
 {
 Directory.CreateDirectory(uploadPath);
 }
 file.SaveAs(uploadPath + file.FileName);
 //下面这句代码缺少的话，上传成功后上传队列的显示不会自动消失
 context.Response.Write(&amp;#34;1&amp;#34;);
 }
 else
 {
 context.Response.Write(&amp;#34;0&amp;#34;);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;6 运行后效果如下图：&lt;/p&gt;</description></item><item><title>设计模式笔记(15)—命令模式（行为型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-15-command-pattern/</link><pubDate>Wed, 30 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-15-command-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;将一个请求封装为一个对象，从而使你可用不同的请求对客户进行参数化；对请求排队或记录请求日志，以及支持可撤销的操作。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合——比如需
要对行为进行“记录、撤销/重做（undo/redo）、事务”等处理，这种无法抵御变化的紧耦合是不合适的。在这种情况下，如何将“行为请求者”与“行为实现者”解耦？将一组行为抽象为对象，可以实现二者之间的松耦合。&lt;/p&gt;
&lt;p&gt;先来看个反例（版本1），假设在一个应用程序中需要用到要用到很多的一些外部的类，并且要对这些类中的操作进行撤销、记录等操作，如果像下面这样实现就会很乱并且不容易实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Application
{
 public void Process()
 {
 Document doc = new Document();
 doc.ShowText();
 Graphics gra = new Graphics();
 gra.Draw();
 //需要进行undo 记录等操作
 }
}
public class Document
{
 public void ShowText() { }
}
public class Graphics
{
 public void Draw(){ }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;要满足上面提的那些要求就需要用命令模式，命令模式结构图如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290617303.webp" alt="2010-12-29_121609" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;改进后的代码（版本2），将ShowText Draw这种行为抽象起来放到一个接口中，接口命名为ICommand，并且在该接口中还有一个方法签名Undo，用来做撤销处理，当然根据需要还可以加其他的操作。ICommand代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public interface ICommand
{
 void Execute();
 void Undo();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Document类和Graphics类实现该接口，并提供自己的实现，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Document:ICommand
{
 public string Name { get;set;}
 public Document(string name)
 {
 Name = name;
 }
 public void Execute()
 {
 Console.WriteLine(&amp;#34;显示文本 &amp;#34;+Name);
 }
 public void Undo()
 {
 Console.WriteLine(&amp;#34;撤销显示文本 &amp;#34;+Name);
 }
}

public class Graphics : ICommand
{
 public string Name { get;set;}
 public Graphics(string name)
 {
 Name = name;
 }
 public void Execute()
 {
 Console.WriteLine(&amp;#34;画图 &amp;#34;+Name);
 }
 public void Undo()
 {
 Console.WriteLine(&amp;#34;撤销画图 &amp;#34;+Name);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;客户端调用的代码：&lt;/p&gt;</description></item><item><title>关于多线程的一个例子（UI实时显示）</title><link>https://fwhyy.com/2009/12/an-example-in-respect-to-multithreading/</link><pubDate>Sun, 20 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/an-example-in-respect-to-multithreading/</guid><description>&lt;p&gt;在开发Window应用程序的时候，经常需要在界面上显示出已经执行到什么步骤了，拿一个简单例子来说，创建一个Winform程序，在窗体上访一个Button和一个Label，点击Button时做100次循环，在Label上实时显示当前循环的次数。一种简单的做法就是使用Application.DoEvents，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;private void btnTest_Click(object sender, EventArgs e)
{
 for (int i = 0; i &amp;lt; 100; i++)
 {
 Thread.Sleep(100);
 label1.Text = i + &amp;#34;/100&amp;#34;;
 Application.DoEvents();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码如果将Application.DoEvents();去掉当点击Button时，程序会卡住，直到这个循环执行完成，当这个循环足够大时是不能忍受的。不过小数据量用Application.DoEvents()还行，数据量大了使用Application.DoEvents()就会带来性能的问题。所以Application.DoEvents()要慎用，在大数据量的时候可以使用多线程解决。如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;private void btnTest_Click(object sender, EventArgs e)
{
 Thread thread = new Thread(new ThreadStart(DoWork));
 thread.Start();
}
private void DoWork()
{
 for (int i = 0; i &amp;lt; 100; i++)
 {
 Thread.Sleep(100);
 label1.Text = i + &amp;#34;/100&amp;#34;;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;嗯？出现异常了是吧，没错上面的代码运行后后会出现“线程间操作无效: 从不是创建控件“label1”的线程访问它。”的异常。关于什么原因造成的，大家可以google一下。不过上面代码在vs03中貌似可以正常运行。将代码改成下面这样就可以正常运行了：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;private void btnTest_Click(object sender, EventArgs e)
{
 Thread thread = new Thread(new ThreadStart(DoWork));
 thread.Start();
}
private void DoWork()
{
 for (int i = 0; i &amp;lt; 100; i++)
 {
 Thread.Sleep(100);
 this.Invoke(new Action&amp;lt;string&amp;gt;(this.ChangeLabel),i.ToString());
 }
}
private void ChangeLabel(string i)
{
 label1.Text = i + &amp;#34;/100&amp;#34;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果嫌多写一个ChangeLabel方法费事，可以写成匿名方法的形式，如下：&lt;/p&gt;</description></item><item><title>设计模式笔记(14)—模板方法模式（行为型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-14-template-method-pattern/</link><pubDate>Mon, 14 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-14-template-method-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;定义一个操作中的算法的骨架，而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个 算法的结构即可重定义该算法的某些特定步骤。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，对于某一项任务，它常常有稳定的整体操作结构，但各个子步骤却有很多改变的需求，或者由于固有的原因（比如框架与应用之间的关系）而无法和任务的整体结构同时实现。如何在确定稳定操作结构的前提下，来灵活应对各个子步骤的变化或者晚期实现需求？&lt;/p&gt;
&lt;p&gt;模板方法模式结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290615923.webp" alt="2010-12-29_122541" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;AbstractClass类：这个抽象类中定义了一个模板方法TemplateMethod，该方法通常为一个具体方法，将抽象类中的一些抽象的操作组合在其中，推迟到子类实现。&lt;/p&gt;
&lt;p&gt;ConcreteClass类:按照需求实现父类定义的一个或多个抽象方法。&lt;/p&gt;
&lt;p&gt;一个小的例子来反映上面的结构：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 测试车的类---&amp;gt;AbstractClass
/// &amp;lt;/summary&amp;gt;
public abstract class Vehical
{
 protected abstract void Start(); //PrimitiveOperation
 protected abstract void Run(); //PrimitiveOperation
 protected abstract void Trun(); //PrimitiveOperation
 protected abstract void Stop(); //PrimitiveOperation
 /// &amp;lt;summary&amp;gt;
 /// 相当于TemplateMethod
 /// &amp;lt;/summary&amp;gt;
 public void Test()
 {
 //做记录等操作
 Start();
 Run();
 Trun();
 Stop();
 }
}

/// &amp;lt;summary&amp;gt;
/// 红旗车---&amp;gt;ConcreteClass
/// &amp;lt;/summary&amp;gt;
public class HongQiCar : Vehical
{
 protected override void Start()
 {
 Console.WriteLine(&amp;#34;测试红旗车启动&amp;#34;);
 }
 protected override void Run()
 {
 Console.WriteLine(&amp;#34;测试红旗车行驶&amp;#34;);
 }
 protected override void Trun(int degree)
 {
 Console.WriteLine(&amp;#34;测试红旗车转向&amp;#34;);
 }
 protected override void Stop()
 {
 Console.WriteLine(&amp;#34;测试红旗车停止&amp;#34;);
 }
}
/// &amp;lt;summary&amp;gt;
/// QQ车---&amp;gt;ConcreteClass
/// &amp;lt;/summary&amp;gt;
public class QQCar : Vehical
{
 protected override void Start()
 {
 Console.WriteLine(&amp;#34;测试QQ车启动&amp;#34;);
 }
 protected override void Run()
 {
 Console.WriteLine(&amp;#34;测试QQ车行驶&amp;#34;);
 }
 protected override void Trun(int degree)
 {
 Console.WriteLine(&amp;#34;测试QQ车转向&amp;#34;);
 }
 protected override void Stop()
 {
 Console.WriteLine(&amp;#34;测试QQ车停止&amp;#34;);
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户代码
/// &amp;lt;/summary&amp;gt;
public class App
{
 static void Main()
 {
 Vehical vehical;
 vehical = new HongQiCar();
 vehical.Test();

 vehical = new QQCar();
 vehical.Test();
 Console.ReadLine();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="template-method模式的几个要点"&gt;Template Method模式的几个要点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Template Method模式是一种非常基础性的设计模式，在面向对象系统中有着大量的应用。它用最简洁的机制（虚函数的多态性）为很多应用程序框架提供了灵活的扩展点，是代码复用方面的基本实现结构。&lt;/li&gt;
&lt;li&gt;除了可以灵活应对子步骤的变化外，“不要调用我，让我来调用你”的反向控制结构是Template Method的典型应用。&lt;/li&gt;
&lt;li&gt;在具体实现方面，被Template Method调用的虚方法可以具有实现，也可以没有任何实现（抽象方法、纯虚方法），但一般推荐将它们设置为protected方法。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>在JS方法中返回多个值的三种方法</title><link>https://fwhyy.com/2009/12/in-js-method-return-multiple-values-of-the-three-methods/</link><pubDate>Fri, 11 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/in-js-method-return-multiple-values-of-the-three-methods/</guid><description>&lt;p&gt;在使用JS编程中，有时需要在一个方法返回两个个或两个以上的数据，用下面的几种方法都可以实现：&lt;/p&gt;
&lt;p&gt;1 使用数组的方式，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
 &amp;lt;title&amp;gt;JS函数返回多个值--oec2003&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
 &amp;lt;input type=&amp;#34;button&amp;#34; onclick=&amp;#34;getNames()&amp;#34; value=&amp;#34;test&amp;#34; /&amp;gt;

 &amp;lt;script type=&amp;#34;text/javascript&amp;#34;&amp;gt;
function getData()
{
 var names=new Array(&amp;#34;oec2003&amp;#34;,&amp;#34;oec2004&amp;#34;);
 return names;
}
function getNames()
{
 var names=getData();
 alert(getData()[0]); //返回oec2003
}
&amp;lt;/script&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 将数据封装到Json中返回，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;JS函数返回多个值--oec2003&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;input type=&amp;#34;button&amp;#34; onclick=&amp;#34;getInfo()&amp;#34; value=&amp;#34;test&amp;#34;/&amp;gt;
&amp;lt;script type=&amp;#34;text/javascript&amp;#34;&amp;gt;
function getData()
{
 var info={&amp;#34;name&amp;#34;:&amp;#34;oec2003&amp;#34;,&amp;#34;age&amp;#34;:&amp;#34;25&amp;#34;};
 return info;
}
function getInfo()
{
 var info=getData();
 var name=info[&amp;#34;name&amp;#34;];
 var age=info[&amp;#34;age&amp;#34;];
 alert(&amp;#34;姓名：&amp;#34;+name+&amp;#34; 年龄：&amp;#34;+age);
}
&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;更详细的Json的介绍请看这里&lt;/p&gt;
&lt;p&gt;3 这是最简单的一种方法，看下面代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;JS函数返回多个值--oec2003&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;input type=&amp;#34;button&amp;#34; onclick=&amp;#34;getInfo()&amp;#34; value=&amp;#34;test&amp;#34;/&amp;gt;
&amp;lt;script type=&amp;#34;text/javascript&amp;#34;&amp;gt;
 function getData()
 {
 return [&amp;#34;oec2003&amp;#34;, 25]
 }
 function getInfo()
 {
 var info = getData();
 alert(&amp;#34;姓名：&amp;#34; + info[0] + &amp;#34;年龄：&amp;#34; + info[1]);
 }
&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>设计模式笔记(13)—代理模式（结构型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-13-proxy-pattern/</link><pubDate>Thu, 10 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-13-proxy-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;为其他对象提供一种代理以控制对这个对象的访问。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在面向对象系统中，有些对象由于某种原因（比如对象创建的开销很大，或者某些操作需要安全控制，或者需要进程外的访问等），直接访问会给使用者、或者系统结构带来很多麻烦。如何在不失去透明操作对象的同时来管理/控制这些对象特有的复杂性？增加一层间接层是软件开发中常见的解决方式。看下结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290619654.webp" alt="2010-12-29_124225" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Subject：该类中定义了一些RealSubject和Proxy中共有的方法。&lt;/p&gt;
&lt;p&gt;RealSubject：这个类是Proxy所要代理的实体类，客户端只和Proxy交互。&lt;/p&gt;
&lt;p&gt;代码实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 公共接口
/// &amp;lt;/summary&amp;gt;
interface ISubject
{
 void Request();
}
/// &amp;lt;summary&amp;gt;
/// 被代理的类
/// &amp;lt;/summary&amp;gt;
public class RealSubject : ISubject
{
 public void Request()
 {
 Console.WriteLine(&amp;#34;被代理类的请求&amp;#34;);
 }
}
/// &amp;lt;summary&amp;gt;
/// 代理类
/// &amp;lt;/summary&amp;gt;
public class Proxy : ISubject
{
 RealSubject realSubject=new RealSubject();
 public void Request()
 {
 realSubject.Request();
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户代码
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&amp;#34;args&amp;#34;&amp;gt;&amp;lt;/param&amp;gt;
static void Main(string[] args)
{
 Proxy proxy = new Proxy();
 proxy.Request();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码非常简单，在客户端使用的是Proxy类，其实调用的是RealSubject类中的方法，起到了代理的目的。&lt;/p&gt;
&lt;h2 id="proxy模式的应用场景"&gt;Proxy模式的应用场景&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;远程代理，也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在不同地址空间的事实。（net中的webservice）&lt;/li&gt;
&lt;li&gt;虚拟代理，根据需要创建开销很大的对象。通过他来存放实例化需要很长时间的真实对象。&lt;/li&gt;
&lt;li&gt;安全代理，用来控制真实对象访问时的权限。&lt;/li&gt;
&lt;li&gt;智能指引，指当调用这是对象时，代理处理另外一些事情。
[以上四点摘自《大话设计模式》]&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="proxy模式的几个要点"&gt;Proxy模式的几个要点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;“增加一层间接层”是软件系统中对许多复杂问题的一种常见解决方法。在面向对象系统中，直接使用某些对象会带来很多问题，作为间接层的proxy对象便是解决这一问题的常用手段。&lt;/li&gt;
&lt;li&gt;具体proxy设计模式的实现方法、实现粒度都相差很大，有些可能对单个对象做细粒度的控制，如copy-on-write技术，有些可能对组件模块提供抽象代理层,在架构层次对对象做proxy。&lt;/li&gt;
&lt;li&gt;Proxy并不一定要求保持接口的一致性，只要能够实现间接控制，有时候损及一些透明性是可以接受的。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>设计模式笔记(12)—享元模式（结构型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-12-flyweight-pattern/</link><pubDate>Wed, 09 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-12-flyweight-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;运用共享技术有效地支持大量细粒度的对象。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中，从而带来很高的运行时代价——主要指内存需求方面的代价。如何在避免大量细粒度对象问题的同时，让外部客户程序仍然能够透明地使用面向对象的方式来进行操作？这需要用到享元模式，不过应用享元模式是需要进行评估的，也就是说在当前情况下是否会对系统造成性能上的影响，如果会那么就是用，下面先来看个小例子是如何进行评估的。&lt;/p&gt;
&lt;p&gt;假设有一个字符的类Charator，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Charator
{
 char c;
 Font f;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;为了方便评估，Charator类中的Font类型采用自定义的类型：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Font
{
 string fontName;
 int size;
 Color color;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在客户代码中使用Charator类&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class App
{
 static void Main()
 {
 List&amp;lt;Charator&amp;gt; list=new List&amp;lt;Charator&amp;gt;(100000);
 for (int i = 0; i &amp;lt; list.Count; i++)
 {
 Charator charator = new Charator();
 list.Add(charator);
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在客户代码中将Charator类实例化了100000次，Charator类中有两个成员，并且有个成员为Font类型，Font类型中又定义了三个成员，下面将在代码注释中标出要占用的内存量：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 如果有n个Font对象占用大小为12bytes*n 其实字符串类型
/// 除了本身占用的4bytes外 还有一个引用指针要占用4bytes，
/// 不过这个 不会构成倍乘效应，也就是当有n个对象时不会
/// 以n的倍数增长，所以可以忽略
/// &amp;lt;/summary&amp;gt;
public class Font
{
 string fontName; //4bytes
 int size; //4bytes
 Color color; //4bytes
}
/// &amp;lt;summary&amp;gt;
/// 总共占用2+20+4+8+2=36bytes
/// 第三个的4为指向font的指针
/// 第四个的8为虚表指针和垃圾回收和同步
/// 最后的2为char的填充位
/// &amp;lt;/summary&amp;gt;
public class Charator
{
 /// &amp;lt;summary&amp;gt;
 /// 占用2bytes
 /// &amp;lt;/summary&amp;gt;
 char c;
 /// &amp;lt;summary&amp;gt;
 /// 总占用12bytes+4bytes+4bytes =20bytes
 /// 其中12bytes是三个成员的，另外的两个4bytes分别为
 /// 虚表指针和net垃圾回收机制所需要的一些位，因为每个
 /// 类型最终都可以追溯到object类型，所以默认都会有虚函数
 /// 4byte的虚表指针式不可少的
 /// &amp;lt;/summary&amp;gt;
 Font f; 

}
/// &amp;lt;summary&amp;gt;
/// 36bytes * 100000=3600000bytes =3600k=3.6mb
/// &amp;lt;/summary&amp;gt;
public class App
{
 static void Main()
 {
 List&amp;lt;Charator&amp;gt; list=new List&amp;lt;Charator&amp;gt;(100000);
 for (int i = 0; i &amp;lt; list.Count; i++)
 {
 Charator charator = new Charator();
 list.Add(charator);
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码执行会带来3mb多的内存数据，这个对于现在的机器来说算不了什么，上面例子中是做了100000次的计算，那如果再加两个数量级到10000000又会怎么样了，那就会有300多mb，这个数字肯定是不能接受的，那么这个时候就要考虑用享元模式了。 看下面改进后的代码：&lt;/p&gt;</description></item><item><title>设计模式笔记(11)—外观模式（结构型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-11-appearance-pattern/</link><pubDate>Mon, 07 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-11-appearance-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;为子系统中的一组接口提供一个一致的界面，Façade模式定义了一个高层接口，这个接口使得这一子系统更加容易使用。&lt;/p&gt;
&lt;p&gt;先来看个小例子，假设我们需要开发一个坦克模拟系统用于模拟坦克车在各种作战环境中的行为，其中坦克系统由引擎、控制器、车轮、车身等各子系统构成。就会有下面这些类的产生&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Wheel{ }
public class Engine{ }
public class Controller{ }
public class BodyWork{ }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;不同的场景中的要求都不一样，可能会用到某些子系统，也可能不会用到，这些不同的场景就相当是外部接口，这些场景和子系统的关系如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290618615.webp" alt="2010-12-29_125236" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;图1&lt;/p&gt;
&lt;p&gt;上图中的关系感觉很混乱，场景和子系统之间的耦合度很高，要降低这种耦合度，就要使和场景之间交互的不是这些子系统了，而是相对单一的一个中间层，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290618206.webp" alt="2010-12-29_125304" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;图2&lt;/p&gt;
&lt;p&gt;上图的Facade就将子系统隐藏了，不同的场景都是直接和Facade交互。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;上面图1方案的问题在于组件的客户和组件中各种复杂的子系统有了过多的耦合，随着外部客户程序和各子系统的演化，这种过多的耦合面临很多变化的挑战。如何简化外部客户程序和系统间的交互接口？如何将外部客户程序的演化和内部子系统的变化之间的依赖相互解耦？这就要用到Facade模式，先来看结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290618557.webp" alt="2010-12-29_125333" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;代码实现，先定义一些子系统类&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Wheel
{
 public void WAction1() { }
 public void WAction2() { }
}
public class Engine
{
 public void EAction1() { }
 public void EAction2() { }
}
public class Controller
{
 public void CAction1() { }
 public void CAction2() { }
}
public class BodyWork
{
 public void BAction1() { }
 public void BAction2() { }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Facade类，用来组合这些子系统&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class TankFacade
{
 Wheel[] wheels = new Wheel[4];
 Engine[] engines = new Engine[4];
 BodyWork bodywork = new BodyWork();
 Controller controller = new Controller();

 public void Start()
 {
 //用到子系统中的一个或多个
 }
 public void Stop()
 {
 //用到子系统中的一个或多个
 }
 public void Run()
 {
 //用到子系统中的一个或多个
 }
 public void Shot()
 {
 //用到子系统中的一个或多个
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;客户端调用&lt;/p&gt;</description></item><item><title>设计模式笔记(10)—装饰模式（结构型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-10-decorative-pattern/</link><pubDate>Fri, 04 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-10-decorative-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;动态地给一个对象增加一些额外的职责。就增加功能而言，Decorator模式比生成子类更为灵活。&lt;/p&gt;
&lt;p&gt;首先来看一个小例子，假如我们需要给游戏开发一种坦克，除了各种不同型号的坦克外，还希望在不同的场合来给坦克增加以下的一种或多种功能：比如红外线夜视功能、水陆两栖功能、GPS定位功能等。通常做法如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 抽象坦克
/// &amp;lt;/summary&amp;gt;
public abstract class Tank
{
 public abstract void Shot();
 public abstract void Run();
}

//型号
public class T50 : Tank { }
public class T60 : Tank { }
public class T70 : Tank { }

//在不同场合下的各种功能都抽象为接口，
//如果某种型号的坦克需要某种功能就继承该功能接口
//下面的IA IB IC 为功能A B C的接口
/// &amp;lt;summary&amp;gt;
/// 有A功能的T50型号
/// &amp;lt;/summary&amp;gt;
public class T50A : T50, IA { }
/// &amp;lt;summary&amp;gt;
/// 有A B两种功能的T60型号
/// &amp;lt;/summary&amp;gt;
public class T60AB : T60, IA, IB { }
/// &amp;lt;summary&amp;gt;
/// 有A B C三种功能的T70型号
/// &amp;lt;/summary&amp;gt;
public class T70ABC : T70, IA, IB, IC { }
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;上面描述的问题的根源在于我们“过多地使用了继承来扩展对象的功能”，由于继承为赖幸引入了静态特质，使得这种扩展方式缺乏灵活性，并且随着子类的增多（扩展功能的增多)，各种子类的组合（扩展功能的组合）会导致更多子类的膨胀（多继承）。那么如何使“对象功能的扩展”能够根据需要来动态地实现，同时避免“扩展功能的增多”带来的子类膨胀问题，从而使得任何“功能的变化”所导致的影响减为最低呢？这就需要用到装饰模式（Decorator）。下面先来看下装饰模式的结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290619381.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Component：对应上面例子中的Tank。&lt;/p&gt;
&lt;p&gt;ConcreteComponent：对应坦克的型号 T50 T60 T70等。&lt;/p&gt;
&lt;p&gt;DeCorator ConcreteDecoratorA ConcreteDecoratorB 这三个类就是接下来要实现了。&lt;/p&gt;</description></item><item><title>设计模式笔记(9)—组合模式（结构型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-9-portfolio-pattern/</link><pubDate>Wed, 02 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-9-portfolio-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;将对象组合成树形结构以表示“部分–整体”的层次结构。Composite使得用户对单个对象和组合对象使用具有一致性。&lt;/p&gt;
&lt;p&gt;在面向对象系统中，我们经常会遇到一类具有”容器“特征的对象—即他们在充当对象的同时，又是其他对象的容器。比如在一些管理系统中就会出现总公司下面有很多的分公司，分公司下面有很多的部门，每个部门下又有很多的员工，像分公司和部门就是既充当了“对象”的角色也充当了“容器”的角色；还有我们可能玩过的“俄罗斯套娃”也是这种结构，一个大娃娃里面装个小娃娃，小的里面又有个小的直到最小的一个，中间的娃娃就是既充当了“对象”也充当了“容器”。先看下面这个例子:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;interface IBox
{
 void Process();
}
/// &amp;lt;summary&amp;gt;
/// 相当于树的叶子节点，没有子对象了
/// &amp;lt;/summary&amp;gt;
public class SingleBox : IBox
{
 public void Process()
 { 

 }
}
/// &amp;lt;summary&amp;gt;
/// 容器
/// &amp;lt;/summary&amp;gt;
public class ContainerBox : IBox
{
 List&amp;lt;IBox&amp;gt; list = new List&amp;lt;IBox&amp;gt;();
 public void Process() { }
 public List&amp;lt;IBox&amp;gt; GetBoxes()
 {
 return list;
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户代码
/// &amp;lt;/summary&amp;gt;
public class App
{
 static void Mina()
 {
 ///此处从工厂方法中得到盒子的对象，但我们不知道是SingleBox还是ContainerBox
 ///所以要做判断
 IBox box = Factory.Create();
 if (box is ContainerBox)
 {
 box.Process();
 List&amp;lt;IBox&amp;gt; list = ((ContainerBox)box).GetBoxes();
 }
 else if(box is SingleBox)
 {
 box.Process();
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;上面代码的问题的根据在于：客户代码过多地依赖对象容器复杂的内部实现结构，对象容器内部实现结构（而非抽象接口）的变化将引起客户代码的频繁变化，带来了代码的维护性、扩展性等弊端。&lt;/p&gt;
&lt;p&gt;如何将“客户代码与复杂的对象容器结构”解耦？让对象容器自己来实现自身的复杂结构，从而使得客户代码就像处理简单对象一样来处理复杂的对象容器？&lt;/p&gt;
&lt;p&gt;这就要使用Composite模式了，先看下Composite模式的结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201281850646.webp" alt="image-20220128185053657" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Component：定义了Leaf和Composite的一些共有特性。&lt;/li&gt;
&lt;li&gt;Composite：有容器特征的类型。&lt;/li&gt;
&lt;li&gt;Leaf：叶节点，即一个单独的个体，下面没有子节点。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;依据上面的结构图完成代码实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class Component
{
 protected string _name;
 public Component(string name)
 {
 _name = name;
 }
 public abstract void Operation();
 public abstract void Add(Component component);
 public abstract void Remove(Component component);
}

public class Leaf : Component
{
 public Leaf(string name) : base(name) { }
 public override void Add(Component component)
 {
 throw new NotSupportedException();
 }
 public override void Remove(Component component)
 {
 throw new NotSupportedException();
 }

 public override void Operation()
 {
 //...do something
 }
}

public class Composite : Component
{
 public Composite(string name):base(name){}
 List&amp;lt;Component&amp;gt; list = new List&amp;lt;Component&amp;gt;();
 /// &amp;lt;summary&amp;gt;
 /// 添加
 /// &amp;lt;/summary&amp;gt;
 /// &amp;lt;param name=&amp;#34;conponent&amp;#34;&amp;gt;&amp;lt;/param&amp;gt;
 public override void Add(Component component)
 {
 if (list != null)
 {
 list = new List&amp;lt;Component&amp;gt;();
 }
 list.Add(component);
 }
 /// &amp;lt;summary&amp;gt;
 /// 删除
 /// &amp;lt;/summary&amp;gt;
 /// &amp;lt;param name=&amp;#34;component&amp;#34;&amp;gt;&amp;lt;/param&amp;gt;
 public override void Remove(Component component)
 {
 if (list == null)
 {
 throw new NullReferenceException();
 }
 list.Remove(component);
 }

 public override void Operation()
 {
 if (list != null)
 {
 foreach (Component c in list)
 {
 c.Operation();
 }
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Leaf类为叶子节点类，它的实例是没有子节点的，但是在抽象类中的方法Add和Remove方法必须要实现，按理说这样的实现是没有意义的，所以在此处抛出了NotSupportedException 异常，在客户端调用捕获到再做相应的处理，这种模式称之为“透明足组合模式”，这样做的好处是叶子（Leaf）和容器（Composite）对于外界没有分别，它们具有一致的接口行为。还有一种情况叫“安全组合模式”，在抽象类（Component）中不定义Add Remove方法，而是在容器的实现类中去定义，这样就各司其职了，看下面结构图：&lt;/p&gt;</description></item><item><title>设计模式笔记(8)—桥接模式（结构型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-8-bridge-pattern/</link><pubDate>Tue, 01 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-8-bridge-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;将抽象部分与实现部分分离，使他们都可以独立地变化。&lt;/p&gt;
&lt;p&gt;先来看一个简单的例子，假设我们需要开发一个同时支持PC和手机的坦克游戏，游戏在PC和手机上的功能都一样，有同样的类型，有同样的功能需求变化，而这些游戏中的坦克有多种不同的型号：T50 T60等。根据面向对象的思想，我们可以很容易设计一个坦克(Tank)的抽象类，然后不同的型号都继承抽象类，并且PC和手机上的图形绘制，操作等都是不相同的，所以不同的平台都要提供自己的一套实现：&lt;/p&gt;
&lt;p&gt;坦克抽象类&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 坦克的抽象类
/// &amp;lt;/summary&amp;gt;
public abstract class Tank
{
 public abstract void Start();
 public abstract void Attack();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;各种不同的型号&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// T50型号
/// &amp;lt;/summary&amp;gt;
public class T50:Tank
{
 public override void Attack(){}
 public override void Start(){}
}
/// &amp;lt;summary&amp;gt;
/// T60型号
/// &amp;lt;/summary&amp;gt;
public class T60:Tank
{
 public override void Attack(){}
 public override void Start(){}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;手机上的实现&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// MobileT50型号
/// &amp;lt;/summary&amp;gt;
public class MobileT50 : T50
{
 /// &amp;lt;summary&amp;gt;
 /// 启动
 /// &amp;lt;/summary&amp;gt;
 public override void Start(){}
 /// &amp;lt;summary&amp;gt;
 /// 攻击
 /// &amp;lt;/summary&amp;gt;
 public override void Attack(){}
}
/// &amp;lt;summary&amp;gt;
/// MobileT60型号
/// &amp;lt;/summary&amp;gt;
public class MobileT60 : Tank
{
 /// &amp;lt;summary&amp;gt;
 /// 启动
 /// &amp;lt;/summary&amp;gt;
 public override void Start(){}
 /// &amp;lt;summary&amp;gt;
 /// 攻击
 /// &amp;lt;/summary&amp;gt;
 public override void Attack(){}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;PC上的实现&lt;/p&gt;</description></item><item><title>设计模式笔记(7)—适配器模式（结构型）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-7-adapter-pattern/</link><pubDate>Thu, 26 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-7-adapter-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;将一个类的接口转换成客户所希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件系统中，由于应用环境的变化，常常要将“一些现存的对象”放在心的环境中应用，但是新环境要求的接口是这些现存对象所不满足的。&lt;/p&gt;
&lt;p&gt;适配的意思是在不改变原有实现的基础上，将原先不兼容的接口转换为兼容的接口。在我们的生活中有着很多适配器的例子，笔记本的电源适配器、一些卡的USB读卡器等等。&lt;/p&gt;
&lt;p&gt;在Gof23这本书中将适配器模式分成了两种：对象适配器和类适配器&lt;/p&gt;
&lt;p&gt;对象适配器&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201281852658.webp" alt="2010-12-29_140647" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;上图中的Target是客户所期待的，希望去使用的类或接口。Adaptee是被适配的对象。Adapter为适配的对象。首先将上图中的结构还原成代码，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
 /// 客户要使用的类
 /// &amp;lt;/summary&amp;gt;
 public abstract class Target
 {
 public abstract void Request();
 }

 /// &amp;lt;summary&amp;gt;
 /// 被适配的类
 /// &amp;lt;/summary&amp;gt;
 public class Adaptee
 {
 public void SpecificRequest()
 { 

 }
 }

 /// &amp;lt;summary&amp;gt;
 /// 适配对象
 /// &amp;lt;/summary&amp;gt;
 public class Adapter : Target
 {
 private Adaptee adapee = new Adaptee();

 public void Request()
 {
 adapee.SpecificRequest();
 }
 }

 /// &amp;lt;summary&amp;gt;
 /// 客户程序
 /// &amp;lt;/summary&amp;gt;
 public class App
 {
 static void Main(string[] args)
 {
 Target target = new Adapter();
 //对客户来说是调用的Request，实际上是调用的SpecificRequest
 target.Request();
 }
 }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;接着根据上面的思路来看一个实际例子，我们要来实现一个对栈的操作，有一个IStact接口，里面有三个方法Push(进栈)、Pop(出栈)和GetTopItem(取最顶层元素)，这个IStact接口将相当于上面的Target，想要实现进栈出栈的操作，如果自己去实现数据结构显得比较麻烦，在此可以将net提供的ArrayList类拿来一用，ArrayList类就是被适配的对象，相当于上面的Adaptee。在写一个适配类StactAdapter类完成功能就可以了。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 栈的接口
/// &amp;lt;/summary&amp;gt;
public interface IStack
{
 void Push(object item);
 void Pop();
 Object GetTopItem();
}
/// &amp;lt;summary&amp;gt;
/// 对象适配器
/// &amp;lt;/summary&amp;gt;
public class StactAdapter:IStack
{
 ArrayList list;
 /// &amp;lt;summary&amp;gt;
 /// 构造函数中实例化ArrayList
 /// &amp;lt;/summary&amp;gt;
 public StactAdapter()
 {
 list = new ArrayList();
 }
 /// &amp;lt;summary&amp;gt;
 /// 进栈
 /// &amp;lt;/summary&amp;gt;
 /// &amp;lt;param name=&amp;#34;item&amp;#34;&amp;gt;压入栈的元素&amp;lt;/param&amp;gt;
 public void Push(object item)
 {
 list.Add(item);
 }
 /// &amp;lt;summary&amp;gt;
 /// 出栈
 /// &amp;lt;/summary&amp;gt;
 public void Pop()
 {
 list.RemoveAt(list.Count - 1);
 }
 /// &amp;lt;summary&amp;gt;
 /// 取最顶层的元素
 /// &amp;lt;/summary&amp;gt;
 /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
 public Object GetTopItem()
 {
 return list[list.Count - 1];
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户调用
/// &amp;lt;/summary&amp;gt;
public class App
{
 static void Main(string[] args)
 {
 IStack myStack = new StactAdapter();
 myStack.Push(&amp;#34;oec2003&amp;#34;);
 myStack.Push(&amp;#34;oec2004&amp;#34;);
 myStack.Push(&amp;#34;oec2005&amp;#34;);
 myStack.Pop();
 Console.WriteLine(myStack.GetTopItem());
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Adapter模式理解起来也非常简单，IStact中的Push和Pop方法就是添加元素和移除元素的功能，正好系统类ArrayList中就提供了Add和RemoveAt这样的方法，所以就可以拿来借用，通过适配器类（StactAdapter）的转换使得Push和Pop方法可以支持添加和移除元素的功能，就像我们经常使用的笔记本一样，本来现实中的电压和笔记本所需要的电压不相符，通过电源适配器的转换就将现实中的电压转换成笔记本所需要的电压。&lt;/p&gt;</description></item><item><title>设计模式笔记(6)—原型模式（创建型）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-6-prototype-pattern/</link><pubDate>Tue, 24 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-6-prototype-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;使用原型实例指定创建对象的种类，然后通过拷贝这些原型来创建新的对象。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件系统中，经常面临着“某些结构复杂的对象”的创建工作，但由于需求的变化，这些对象将成面临着剧烈的变化，但他们拥有比较稳定一致的接口。&lt;/p&gt;
&lt;p&gt;假设在一些打斗游戏场景中，有这样一些角色，普通(NormalActor),可以飞的(FlyActor)，可以潜水的(WaterActor)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class NormalActor { }
public abstract class FlyActor { }
public abstract class WaterActor { }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的三个类都是抽象类，自然会有具体的类来继承这些抽象类&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class NormalActorA : NormalActor { }
public class FlyActorA : FlyActor { }
public class WaterActorA : WaterActor { }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在游戏运行中就会去使用这些角色的具体类，如下&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class GameSystem
{
 public void Run()
 {
 NormalActorA normalActor1 = new NormalActorA();
 NormalActorA normalActor2 = new NormalActorA();
 NormalActorA normalActor3 = new NormalActorA();
 NormalActorA normalActor4 = new NormalActorA();
 NormalActorA normalActor5 = new NormalActorA();

 FlyActorA flyActor1 = new FlyActorA();
 FlyActorA flyActor2 = new FlyActorA();

 WaterActorA waterActor1 = new WaterActorA();
 WaterActorA waterActor2 = new WaterActorA();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在GameSystem类中，我们直接使用具体类（NormalActorA）等来创建对象，GameSystem就对这些具体类产生了依赖，在DIP（依赖倒置原则）中讲到抽象不应依赖具体实现，具体实现应依赖于抽象，所以GameSystem中的代码要进行如下改动&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class GameSystem
{
 public void Run(NormalActor normalActor, FlyActor flyActor,
 WaterActor waterActor)
 {
 NormalActor normalActor1 = normalActor.Clone();
 NormalActor normalActor2 = normalActor.Clone();
 NormalActor normalActor3 = normalActor.Clone();
 NormalActor normalActor4 = normalActor.Clone();
 NormalActor normalActor5 = normalActor.Clone();

 FlyActor flyActor1 = flyActor.Clone();
 FlyActor flyActor2 = flyActor.Clone();

 WaterActor waterActor1 = waterActor.Clone();
 WaterActor waterActor2 = waterActor.Clone();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;经过修改在GameSystem类中已经看不到具体类的影子了，创建对象是通过传入的抽象类类型的参数的Clone方法来创建，关于Clone方法在后面讲到，这样GameSystem就只依赖于抽象了。&lt;/p&gt;</description></item><item><title>设计模式笔记(5)—工厂方法模式（创建型）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-5-factory-method-pattern/</link><pubDate>Sun, 22 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-5-factory-method-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;定义一种用于创建对象的借口，让子类决定实例化哪一个类，Factory Method使得一个类的实例化延迟到子类。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件系统中，经常面临着“某个对象”的创建工作；由于需求的变化，这个对象经常面临着剧烈的变化，但是它却拥有比较稳定的借口。&lt;/p&gt;
&lt;p&gt;假设有这样的一个场景，有一个汽车类和一个汽车测试框架类，汽车测试框架负责对汽车来进行测试，通常情况下我们会想下面这样写。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Car
{
 public void Startup() { }

 public void Run(){ }

 public void Turn(Direction direction) { }

 public void Stop() { }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;测试框架类&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;class CarTestFramework
{
 public void BuildTestContext()
 {
 Car car = new Car();
 //do something
 }

 public void DoTest()
 {
 Car car = new Car();
 //do something
 }

 public void GetTestData()
 {
 Car car = new Car();
 //do something
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在上面的测试框架类CarTestFramework中的每个方法都有可能去实例化Car类。上面的代码中是直接实例化的
Car类。这样测试框架类和汽车之间有很强的依赖关系。实际中我们的测试框架类不可能只测试一种类型的汽车，
所以当被测试的车的类型发生变化时，测试框架类中也要变化，这当然不是我们想要的。现在就把汽车类给抽象
起来。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class AbstractCar
{
 public abstract void Startup();

 public abstract void Run();

 public abstract void Turn(Direction direction);

 public abstract void Stop();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;抽象的汽车类创建了，那么测试框架类也会发生相应的变化，我们可能会很快地拿AbstractCar特换掉Car，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;class CarTestFramework
{
 public void BuildTestContext()
 {
 AbstractCar car = new AbstractCar();
 //do something
 }

 //....
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;很容易可以看出来，上面的代码其实是错误的，抽象类不能实例化。这时可能还会想到另外一种方法用抽象类来实例化子类。&lt;/p&gt;</description></item><item><title>设计模式笔记(4)—生成器模式（创建型）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-4-generator-pattern/</link><pubDate>Sat, 21 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-4-generator-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;将一个复杂对象的构建与其表示相分离，使其同样的构建过程可以创建不同的表示。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件系统中，有时侯面临着一个复杂对象的创建工作，这个发展对象通常是由各个部分的子对象用一定的算法构成；由于需求的变化，这个复杂的对象的各个部分经常面临着巨大的变化，但是将他们组合起来的算法相对稳定。&lt;/p&gt;
&lt;p&gt;还是拿游戏中的房屋作为例子来讲，房屋由门、窗户、墙、地板、天花板组成。这些组成部分可能是经常要发生变化的。如果按常规设计，这些组成部分中的任何一个发生变化时都将使房屋重建，生成器模式的作用就是要使这些组件的变化不影响到房屋。首先构建一个House类&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class House
{
 //该类中可能包含复杂的创建逻辑
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;下面的是一个抽象的构建类，用类构建房屋的组件&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class Builder
{
 public abstract void BuildDoor();
 public abstract void BuildWall();
 public abstract void BuildWindow();
 public abstract void BuildFloor();
 public abstract void BuildHouseCeiling();

 public abstract House GetHouse();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;假设在一个游戏管理类（GameManager）中来完成对房屋的构建&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class GameManager
{
 public static House CreateHouse(Builder builder)
 {
 builder.BuildDoor();

 builder.BuildWindow();
 builder.BuildWindow();

 builder.BuildWall();
 builder.BuildWall();
 builder.BuildWall();
 builder.BuildWall();

 builder.BuildFloor();
 builder.BuildHouseCeiling();

 return builder.GetHouse();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在GameManager类中都是使用的抽象类来完成房屋的构建，所以GameManager类基本上是稳定的，可能出现变化的是创建门或是窗户的个数，当然这个我们可以在数据库中记录。稳定的部分已经创建，现在就来创建经常会变动的部分，假设现在需要构建一个罗马风格的房屋，可以写一个RomanHouse和一个RomanHouseBuilder类来继承House类和Builder类。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class RomanHouse:House {}

public class RomanHouseBuilder : Builder
{
 public override void BuildDoor() { }
 public override void BuildFloor() {}
 public override void BuildHouseCeiling(){ }
 public override void BuildWall(){}
 public override void BuildWindow(){}
 public override House GetHouse()
 {
 return new RomanHouse();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果需要其他风格的访问，同可以创建相应的类继承House和HouseBuilder就可以。&lt;/p&gt;
&lt;p&gt;客户端调用的代码如下&lt;/p&gt;</description></item><item><title>VS中的经典字体推荐</title><link>https://fwhyy.com/2009/11/vs-font-recommended/</link><pubDate>Fri, 20 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/vs-font-recommended/</guid><description>&lt;p&gt;每天编码眼睛看着vs，一个好的字体和背景色能使我们的心情更愉悦，眼睛的疲劳度也随之降低。&lt;/p&gt;
&lt;p&gt;微软发布过针对VS2005的编程字体Consolas，个人感觉这个字体还不错，可以点击下面链接下载&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=22e69ae4-7e40-4807-8a86-b3d36fab68d3&amp;amp;displaylang=en"&gt;猛击这里下载&lt;/a&gt;
对于背景色我比较喜欢浅黄色，据说能保护眼睛，虽然有点夸张但确实比纯白色看着要舒服。&lt;/p&gt;</description></item><item><title>设计模式笔记(3)—抽象工厂模式（创建型）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-3-abstract-factory-pattern/</link><pubDate>Fri, 20 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-3-abstract-factory-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;提供一个借口，让该接口负责创建一系列_相关或者相互依赖的对象_，无需指定他们具体的类。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件系统中经常面临着_一系列相互依赖的对象_的创建的工作，同时由于需求的变化，往往存在着更对系列对象的创建。&lt;/p&gt;
&lt;p&gt;常规的对象创建的方法，直接使用new关键字&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Road road = new Road();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这样直接new会有一个问题，不能应对具体实例化类型的变化，比如说有不同的Road类型需要被实例化的时候就需要来更改此处的代码。解决这个问题的办法就是封装变化点，变化点也是相对而言的，比如在项目中有些地方会经常更具客户的需求而作改动，我们就可以将其封装起来。拿上面的那行代码来说，因为可能有不同类型的Road需要被创建，变化点就是“对象的创建”。&lt;/p&gt;
&lt;p&gt;一种比较简单的解决方法，看下面的代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class RoadFactory
{
 public static Road CreateRoad()
 {
 return new Road();
 }
}
//调用的代码
public class Test
{
 static void Main(string[] args)
 {
 Road road = RoadFactory.CreateRoad();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;现在需求有了改变，需要创建一种另一种类型的路HighRoad，只需更改工厂类的代码就可以，调用的地方不用做修改，如下&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class RoadFactory
{
 public static Road CreateRoad()
 {
 return new HighRoad();
 }
} 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;现在需求又有了改变，比如在游戏的开发场景中，我们需要构建道路、房屋、丛林等等对象，按照上面的思路我 可以写成下面这样的代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;//客户程序
 public class Test
 {
 static void Main(string[] args)
 {
 Road road = GameObjectFactory.CreateRoad();
 Building building = GameObjectFactory.CreateBuilding();
 Jungle jungle = GameObjectFactory.CreateJungle();
 }
 }

 public class GameObjectFactory
 {
 public static Road CreateRoad()
 {
 return new Road();
 }
 public static Building CreateBuilding()
 {
 return new Building();
 }
 public static Jungle CreateJungle()
 {
 return new Jungle();
 }
 }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;以上的代码属于一种简单工厂的实现，将对象的创建放到一个单独的工厂类中，实现了和客户程序的分离，不过 不能应对不同系列对象的变化，比如有不同风格的游戏场景，对于要实现不同风格场景中的道路、房屋等对象的 创建，上面的代码就难以实现。对于有_不同系列对象_这样的需求，变化点转移到了工厂类的内部，上面的代码中 对象的创建是在工厂类中的静态方法中写死的，不能应对变化，如果我们另外创建一个能适应其他系列的工厂类， 那么客户程序就会发生改变，这不是我们希望看到的。要解决此类问题必须使用面向对象的技术来封装变化点。
结构图&lt;/p&gt;</description></item><item><title>设计模式笔记(2)—单件模式（创建型）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-2-singleton-pattern/</link><pubDate>Thu, 19 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-2-singleton-pattern/</guid><description>&lt;h2 id="gof-定义"&gt;Gof 定义&lt;/h2&gt;
&lt;p&gt;保证一个类仅有一个实例，并提供一个该实例的全局访问点。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;保证在系统中只存在一个实例，这样才能保证逻辑的正确性和良好的效率。&lt;/p&gt;
&lt;h2 id="单件模式单线程环境下实现"&gt;单件模式单线程环境下实现&lt;/h2&gt;
&lt;p&gt;看下面一段代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Singleton
{
 private static Singleton _instance;
 //定义为私有，让类的使用者不能直接new一个该类的实例
 private Singleton() { }
 public static Singleton Instance
 {
 get
 {
 if (_instance == null)
 {
 _instance = new Singleton();
 }
 return _instance;
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码中将Singleton类的构造函数设置为私有，如果试图去用new去创建一个Singleton的实例，会出现编译错误&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Test
{
 public static void Main()
 {
 //Singleton不可访问，因为他受保护级别限制
 Singleton t = new Singleton();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;要创建Singleton的实例我们可以像下面这样做&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Test
{
 public static void Main()
 {
 Singleton t = Singleton.Instance;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码完成了一个最简单的单例模式的实现，保证了实例的唯一性，如下的测试代码是可以顺利通过的&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[TestMethod()]
public void Test()
{
 Singleton t1 = Singleton.Instance;
 Singleton t2 = Singleton.Instance;

 Assert.AreEqual(true, t1.Equals(t2));
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="单件模式多线程环境下实现"&gt;单件模式多线程环境下实现&lt;/h2&gt;
&lt;p&gt;在多线程环境下上面代码仍然有可能得到Singleton类的多个对象实例，为什么在多线程环境下会可能创建出多个实例呢？看下面代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Singleton
{
 private static Singleton _instance;
 //定义为私有，让类的使用者不能直接new一个该类的实例
 private Singleton() { }
 public static Singleton Instance
 {
 get
 {
 //线程A执行到此进行if判断，会进入到if语句里面
 //在线程A执行_instance = new Singleton(); 前，线程B也到了if判断处，
 //此时_instance还没有被创建出来仍然为null，线程B也会进入到if语句中
 //这样线程A和线程B会各自构建一个Singleton的实例
 if (_instance == null)
 {
 _instance = new Singleton();
 }
 return _instance;
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;所以上面的代码示例只能应用在单线程的环境下，如果需要实现在多线程环境下的单件模式就需要对上面的代码进行改进，如下&lt;/p&gt;</description></item><item><title>设计模式笔记(1)—开篇（文章索引）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-1-index/</link><pubDate>Wed, 18 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-1-index/</guid><description>&lt;h2 id="概念"&gt;概念&lt;/h2&gt;
&lt;p&gt;设计模式描述了软件设计过程中某一类常见问题的一般性的解决方案。&lt;/p&gt;
&lt;p&gt;面向对象的设计模式描述了面向对象设计过程中，在特定场景下类与相互通讯的对象之间常见的组织关系。&lt;/p&gt;
&lt;h2 id="设计模式与面向对象"&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;面向对象设计模式不像算法技巧，可以照搬照用，他是建立在对“面象对象”纯熟、深入的理解的基础上的经验性认识。&lt;/p&gt;
&lt;h2 id="从设计原则到设计模式"&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;使用重构得到模式—设计模式的应用不宜先入为主，一上来就是用设计模式是对设计模式的最大无用。没有一步到位的设计模式。&lt;/p&gt;
&lt;h2 id="几个设计原则"&gt;几个设计原则&lt;/h2&gt;
&lt;p&gt;在设计模式的使用中无时无刻都在贯穿着下面这几个原则，所以说理解了这几个设计原则对学习和理解设计模式有很大的帮助。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ol&gt;
&lt;li&gt;单一职责原（SRP）：一个类应该仅有一个引起它变化的原因。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start="2"&gt;
&lt;li&gt;开放封闭原则（OCP）：类模块应该是可以扩展的，但是不可以修改（多扩展开放，对修改封闭）&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start="3"&gt;
&lt;li&gt;Liskov替换原则（LSP）：子类必须能够替换他们的基类&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start="4"&gt;
&lt;li&gt;依赖倒置原则（DIP）：高层模块不应该依赖于底层模块，二者都应该依赖于抽象；抽象不应该依赖于实现细节，实现细节应该依赖于抽象。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start="5"&gt;
&lt;li&gt;接口隔离原则（ISP）：不应该强迫客户程序依赖于他们不用的方法。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上面只是简单给出了定义，网上有很多关于这些原则的详细介绍。&lt;/p&gt;
&lt;p&gt;下面简单谈一下我自己对设计模式的认识，设计模式很早就接触了，不过实际在项目中使用过的也只是很少的几个，现在市面上有很多关于设计模式的书，其中不乏有些很生动的例子，非常容易理解，但设计模式并不是写些简单的Demo，个人感觉从很熟悉那些简单的Demo到能够灵活在项目中运用这中间有很长的路要走，需要我们多写、多思考，多总结。之所以要使用设计模式，是因为当变化来临时我们能更方便快捷地解决问题，并且有利于以后的维护。如果没有需求的变化，完全可以用自己认为最简单直接的方式去实现功能，不过需求往往是多变的。我们通常所讲的设计模式指的是面向对象设计模式，所以学习好面向对象的知识是学习面向对象设计模式的前提。最近又将几年前的关于设计模式的webcast讲座翻出来听了听，感觉收获颇多，也顺便做了些笔记以备后用。&lt;/p&gt;
&lt;h2 id="设计模式的分类"&gt;设计模式的分类&lt;/h2&gt;
&lt;p&gt;设计模式分类创建型、结构型、行为型三类。&lt;/p&gt;
&lt;h3 id="创建型"&gt;创建型&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-2-singleton-pattern/"&gt;Singleton 单件&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-3-abstract-factory-pattern/"&gt;Abstract Factory 抽象工厂模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-4-generator-pattern/"&gt;Builder 生成器模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-5-factory-method-pattern/"&gt;Factory Method 工厂方法模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-6-prototype-pattern/"&gt;Prototype 原型模式&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="结构性"&gt;结构性&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-7-adapter-pattern/"&gt;Adapter 适配器模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-8-bridge-pattern/"&gt;Bridge 桥接模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-9-portfolio-pattern/"&gt;Composite 组合模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-10-decorative-pattern/"&gt;Decorator 装饰模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-11-appearance-pattern/"&gt;Facade 外观模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-12-flyweight-pattern/"&gt;Flyweight 享元模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-13-proxy-pattern/"&gt;Proxy 代理模式&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="行为型"&gt;行为型&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-14-template-method-pattern/"&gt;TemplateMethod 模板方法模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-15-command-pattern/"&gt;Command 命令模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-16-interpreter-pattern/"&gt;Interpreter 解释器模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-17-mediator-pattern/"&gt;Mediator 中介者模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-18-iterator-pattern/"&gt;Iterator 迭代器模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-19-observer-pattern/"&gt;Observer 观察者模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-20-chain-of-responsibility-pattern/"&gt;Chain Of Responsibility 职责链模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-21-memo-pattern/"&gt;Memento 备忘录模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-22-state-pattern/"&gt;State 状态模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-23-strategy-pattern/"&gt;Strategy 策略模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/02/design-patterns-notes-24-visitor-pattern/"&gt;Visitor 访问者模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/02/design-patterns-notes-25-summary/"&gt;总结&lt;/a&gt;&lt;/p&gt;</description></item><item><title>体验vs2010 （功能改进篇）</title><link>https://fwhyy.com/2009/10/experience-vs2010-improvements/</link><pubDate>Sat, 24 Oct 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/10/experience-vs2010-improvements/</guid><description>&lt;p&gt;下午在使用vs2010进行了一些简单的编码体验，下面谈一下和以前版本的一些不同的地方，仅限于工具的使用方面，有关Net4.0方面的知识将在以后深入研究。&lt;/p&gt;
&lt;p&gt;首先来看下创建项目的对话框，在左边的Installed Templates里多出了几个选项，如Cloud Service、F#等。点击左边栏中的C#，在右边的模板列表中可以看到Silverlight、asp.net mvc2 已经集成在其中了。而在在选择net framework 版本的下拉框的右边有一个排序的对话框，可以根据名称对模板列表进行排序。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300643854.webp" alt="2010-12-29_153755" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;作为一个web开发人员，当然是首先要试试asp.net web application了，点击C#下面的Web，可以在右边的模板列表中看到有Asp.net Web Application 和Empty Asp.net Web Application 两个Asp.net的模板，先来创建一个Asp.net Web Application 。会发现多了一些目录&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300643911.webp" alt="2010-12-29_153841" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;目录相对于以前的版本多了不少，而且还加入了jquery，乍一看好像是创建了Asp.net mvc项目。个人感觉在这些多出了目录用处也不是很多。如果觉得不需要这么多的自动创建的目录和文件可以选择创建Empty Asp.net Web Application 项目，这可是觉得干净的一个项目就只有一个Web.config文件&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300643074.webp" alt="2010-12-29_153930" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;说起Web.config文件，跟vs08里的Web.config文件实在是简化太多了，这个改进也是我非常喜欢的。Net4对应的CLR版本是4.0 以前的2.0、3.0.3.5的CLR版本都是2.0 ，所以Net4中的machine.config文件时和先前版本中的machine.config是并列安装的。新的.NET 4 machine.config文件现在自动注册我们以前所有的ASP.NET 标识部分（section）, 处理器和模块等。所以在项目中见到的Web.config文件时非常简洁的&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34;?&amp;gt;
&amp;lt;configuration&amp;gt;

 &amp;lt;system.web&amp;gt;
 &amp;lt;compilation debug=&amp;#34;true&amp;#34; targetFramework=&amp;#34;4.0&amp;#34; /&amp;gt;
 &amp;lt;/system.web&amp;gt;
 &amp;lt;system.webServer&amp;gt;
 &amp;lt;modules runAllManagedModulesForAllRequests=&amp;#34;true&amp;#34;/&amp;gt;
 &amp;lt;/system.webServer&amp;gt;

&amp;lt;/configuration&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在界面的编码框部分我发现了一个小细节，大家都知道我们可以以标签的形式打开很多的页面，在以前的版本中，关闭的小叉是在最右边，或者是直接再当前标签上点击右键选择关闭。在vs2010中每个标签页上都有一个关闭小叉叉，和现在很多的多标签浏览器类似，这样确实方便了不少。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300643127.webp" alt="2010-12-29_154008" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;现在就来开始编码的体验了，发现vs2010中的代码智能提示相对于以前版本的智能提示有了一个小的改进，不过这个小小的改进还是很有用的，比如在以前版本中输入一个Response会出现所有列表，而在vs2010中会对显示的内容进行过滤只显示和Response相关的。&lt;/p&gt;
&lt;p&gt;vs2008&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300643506.webp" alt="2010-12-29_154409" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;vs2010&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300644084.webp" alt="2009-10-24_221338" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;除了能过滤外还可以对关键词进行搜索，看下图就很清楚了，输入ind后就自动把TabIndex搜索出来了。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300644289.webp" alt="2010-12-29_154545" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在智能提示中还有一种比骄有趣的功能，比如Textbox有BackColor和BorderColor属性，这两个属性都是由两个单词组成，是要输入每个单词的首字母就能将这两个属性过滤出来，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300644676.webp" alt="2009-10-24_223717" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;好了，先就写这么多吧，更多的功能还有待慢慢研究和使用。&lt;/p&gt;
&lt;p&gt;ps 该攒钱买本了啊，我这老爷本跑vs2010还是很吃力啊&lt;/p&gt;</description></item><item><title>体验VS2010（安装篇）</title><link>https://fwhyy.com/2009/10/experience-vs2010-installation/</link><pubDate>Sat, 24 Oct 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/10/experience-vs2010-installation/</guid><description>&lt;p&gt;本来是打算等到vs2010正式版出来之后再安装vs2010体验，不过鉴于才2g多的大小，就提前下载安装了，下面的是安装过程中的一些截图。和以前装vs2008不同的是，在安装过程中，出现了两次重启电脑。必须重启后才能继续安装。安装的东西很多所以时间也比装vs2008长了不少。&lt;/p&gt;</description></item><item><title>Visual Studio 2010 Beta 2 公开下载地址</title><link>https://fwhyy.com/2009/10/visual-studio-2010-beta-2-download-address-publicly/</link><pubDate>Thu, 22 Oct 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/10/visual-studio-2010-beta-2-download-address-publicly/</guid><description>&lt;p&gt;前天就在博客园见了lyj的那篇介绍Visual Studio 2010 Beta 2的文章了，今天终于开发下载了。
下载地址：&lt;a href="http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx"&gt;http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;看了下别人的安装截图感觉漂亮了不少，不过我还是想等到正式版出来后再下载安装，希望到时能换一个配置好点的本本，现在的这个已经陪伴我三四年的老本跑起来确实很吃力啊。&lt;/p&gt;
&lt;h2 id="相关文章"&gt;相关文章&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/10/experience-vs2010-improvements/"&gt;体验vs2010 （功能改进篇）&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/10/experience-vs2010-installation/"&gt;体验VS2010（安装篇）&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/05/net-4-vs2010-new-features/"&gt;Net4.0—VS2010新特性&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/07/net-4-data-bound-controls-the-clientidrowsuffix-properties/"&gt;Net4.0—数据绑定控件（GridView ListView…）中的ClientIDRowSuffix属性&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/07/net-4-purification-processing-of-html/"&gt;Net4.0—对HTML净化的处理&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/07/net-4-aspnet-controls-the-hyperlink-in-the-improvement/"&gt;Net4.0—AspNet中的控件HyperLink的改进（支持路由跳转）&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/07/net-4-aspnet-url-rewriting-in-the-improvement/"&gt;Net4.0—AspNet中URL重写的改进&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/06/net-4-the-web-deployment-tool/"&gt;Net4.0—Web部署工具&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/05/net-4-framwork-of-new-features/"&gt;Net4.0—Framwork新增特性&lt;/a&gt;&lt;/p&gt;</description></item><item><title>强大的VS插件—Resharper</title><link>https://fwhyy.com/2009/10/powerful-vs-plug-in-resharper/</link><pubDate>Sat, 17 Oct 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/10/powerful-vs-plug-in-resharper/</guid><description>&lt;p&gt;ReSharper是一款Visual.net的插件，主要提升VS.net代码编辑能力，包括对C#、VB.net、XML、XAML和ASP.net，并包括这些语言的交叉关联引用。ReSharper让Visual Studio开发人员更加便捷，包括代码分析、单元测试方案、Goto Symbol支持、To-do探测器等各种特性，ReSharper可以说是辅助Visual Studio开发的一把瑞士军刀，将IntelliJ IDEA在代码编辑方面的智能特性全面带入到Visual Studio中，积极提升.net开发人员的工作效率。ReSharper提供三个版本：Full, C#和VB.net，这样开发人员可以更精准地选择所需的特性。&lt;/p&gt;
&lt;p&gt;很早就听同事说过这个插件很好用，但是听说安装后会拖慢vs的速度，所以就迟迟没敢装，最近还是经不住诱惑装上了这个插件，果然没让我失望。&lt;/p&gt;
&lt;p&gt;下载地址：&lt;a href="http://www.jetbrains.com/resharper/download/"&gt;http://www.jetbrains.com/resharper/download/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;需要注意的是Resharper是收费的，不过网上可以很容易找到注册码，这里就不提供链接了&lt;/p&gt;
&lt;p&gt;博客园的飞刀针对1.0版自己写过注册机，有兴趣的朋友可以研究下。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/feidao/archive/2004/08/12/32537.aspx"&gt;http://www.cnblogs.com/feidao/archive/2004/08/12/32537.aspx&lt;/a&gt;&lt;/p&gt;</description></item><item><title>在数据库中将字表中的多行合并到一列中</title><link>https://fwhyy.com/2009/10/words-in-the-table-in-the-database-multi-line-merged-into-a-column/</link><pubDate>Thu, 15 Oct 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/10/words-in-the-table-in-the-database-multi-line-merged-into-a-column/</guid><description>&lt;p&gt;几年前就做过这样的查询，在最近的项目中又遇到这样的需求，在此记录一下。&lt;/p&gt;
&lt;p&gt;假设有一个文章表Post和一个评论表Comments，可以对文章进行多次评论，现在希望在对Post表查询时能将Post的所有评论内容组合到一个字段中显示。&lt;/p&gt;
&lt;p&gt;首先创建表Post和Comments&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;create table Post
(
 [PostID] int identity(1,1) primary key not null,
 [Title] nvarchar(50),
 [Content] text,
 [CreateDate] datetime default getdate()
)

create table Comments
(
 [CommentID] int identity(1,1) primary key not null,
 [PostID] int,
 [Content] text,
 [CreateDate] datetime default getdate()
)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;给这两个表添加一些测试数据&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;insert into Post select &amp;#39;钓鱼岛是中国的吗？&amp;#39;,&amp;#39;钓鱼岛是中国的&amp;#39;,getdate()
insert into Comments select 1,&amp;#39;绝对是&amp;#39;,getdate()
insert into Comments select 1,&amp;#39;必须是的&amp;#39;,getdate()
insert into Comments select 1,&amp;#39;谁说不是呢&amp;#39;,getdate()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;评论内容的组合使用一个函数来实现，在函数中使用游标去遍历给定PostID的所有评论然后进行拼接，函数代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;create FUNCTION fn_GetAllComments(@PostID int)
RETURNS NVARCHAR(4000)
AS
BEGIN
 DECLARE @result VARCHAR(4000)
 SET @result=&amp;#39;&amp;#39;
 DECLARE getAllComments CURSOR
 FOR
 select CommentID from Comments where PostID=@PostID
 OPEN getAllComments
 DECLARE @ID SYSNAME
 FETCH FROM getAllComments INTO @ID
 WHILE @@fetch_status=0
 BEGIN
 SET @result=@result+(select convert(nvarchar(20),CreateDate,120)
 from Comments where CommentID=@ID)+&amp;#39;:&amp;#39;+
 (select cast([Content] as nvarchar(4000))
 from Comments where CommentID=@ID)+&amp;#39;；&amp;#39;
 FETCH FROM getAllComments INTO @ID
 END
 CLOSE getAllComments
 SET @result= substring(@result,0,len(@result))
 DEALLOCATE getAllComments
 RETURN @result
END
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;现在写SQL语句来测试一下结果&lt;/p&gt;</description></item><item><title>Windows Live Writer中的语法高亮插件</title><link>https://fwhyy.com/2009/09/windows-live-writer-syntax-highlighting-in-the-plug-in/</link><pubDate>Tue, 22 Sep 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/09/windows-live-writer-syntax-highlighting-in-the-plug-in/</guid><description>&lt;h2 id="vspaste"&gt;VSPaste&lt;/h2&gt;
&lt;p&gt;该插件的作用是可以将 VS、 DELPHI 、VS STUDIO 6 、 SharpDevelop、Zend Studio 等IDE中的代码原样复制到Live Writer中。可以点击&lt;a href="http://files.cnblogs.com/oec2003/VSPaste.zip"&gt;此处&lt;/a&gt;下载，下载后解压，将dll文件复制到Live Writer安装目录中的Plugins目录中，如果是安装在C盘，路径如下：C:\Program Files\Windows Live\Writer\Plugins。&lt;/p&gt;
&lt;p&gt;从IDE中复制了代码后点击下图中红色标记处就可以将代码复制到Live Writer中&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290641313.webp" alt="2010-12-29_160715" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="highlight4writer"&gt;highlight4writer&lt;/h2&gt;
&lt;p&gt;该插件安装后可以在一个弹出的对话框中选择c c# xml sql 等十几种语言，可以点击此处下载，下载后同样是将解压的文件复制到Plugins目录下，然后打开Live Writer可以看到如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290641270.webp" alt="2010-12-29_160911" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;点击就会弹出输入代码的对话框，如下图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290641466.webp" alt="2010-12-29_160950" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;就我个人感觉而言，使用第一种比较好些，因为第二种会产生很多的html代码，而第一种的html相对简洁，并且代码在一个class为Code的div中，可以自己设置css来改变代码部分的样式。&lt;/p&gt;
&lt;p&gt;下面是仿老赵的代码样式的css，打开博客园后台管理–》选项—》Configure ，在《通过css定制页面》下的文本框中加入下面的css样式&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;.Code{
 background: #F8F8EE;
 border-left:solid 3px #6CE26C;
 border-top:dashed 1px #BBBBBB;
 border-right:dashed 1px #BBBBBB;
 border-bottom:dashed 1px #BBBBBB;
 padding: 5px;
 margin: 0 5px 0 5px;
 font-family: Verdana,Helvetica, &amp;#34;微软雅黑&amp;#34; , Arial, &amp;#34;宋体&amp;#34;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;然后在文章中添加的代码效果如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Test
{
}
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Asp.net MVC V2 Preview 1 初探</title><link>https://fwhyy.com/2009/08/aspnet-mvc-v2-preview-1/</link><pubDate>Thu, 06 Aug 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/08/aspnet-mvc-v2-preview-1/</guid><description>&lt;p&gt;Asp.net MVC1.0正式版刚刚出来才几个月，ASP.NET MVC ASP.NET MVC2 Preview 1 Released 就跟我们见面了 ，您可以点击&lt;a href="http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;amp;FamilyID=d34f9eaa-fcbe-4e20-b2fd-a9a03de7d6dd#tm"&gt;这儿&lt;/a&gt;下载。该版本可以和以前的Asp.net MVC1.0 兼容，安装了ASP.NET MVC2后，打开vs2008 ，新建项目，可以看到同时存在1.0和2的模板，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290821727.webp" alt="2010-12-29_161754" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在ASP.NET MVC2版中，包含了区域（Area）、数据标记验证（Data Annotation Validation）、强类型UI辅助方法和模板化辅助方法（TemplatedHelper）四个特性，下面就分别来看下这个四个特性。&lt;/p&gt;
&lt;h2 id="区域areas"&gt;区域（Areas）&lt;/h2&gt;
&lt;p&gt;区域（Areas）可以将Asp.net MVC应用的功能进行分割和组合，它可以将Controller和View进行分组管理。如下图中就是将博客（blogs）和相册（Albums）的部分通过Areas提出来单独管理。遗憾的是在预览版1中还没有任何工具的支持，所以Areas项目必须通过手动添加和配置。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290821872.webp" alt="2010-12-29_161937" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;h2 id="数据标记验证data-annotation-validation"&gt;数据标记验证（Data Annotation Validation）&lt;/h2&gt;
&lt;p&gt;DataAnnotation提供了一个简单的方式，在应用中的Model（模型）和ViewModel（视图模型）类中添加验证规则，在ASP.NET MVC中有自动的绑定和UI辅助方法验证支持。首先创建一个实体类Users，代码如下:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;namespace Mvc2Demo.Models
{
 public class Users
 {
 [Required(ErrorMessage = &amp;#34;用户名不能为空！&amp;#34;)]
 public String UserName { get; set; }

 [Range(0, 150, ErrorMessage = &amp;#34;年龄必须在0-150之间！&amp;#34;)]
 [Required(ErrorMessage = &amp;#34;年龄不能为空！&amp;#34;)]
 public Int32 Age { get; set; }

 [Required(ErrorMessage = &amp;#34;邮箱地址不能为空！&amp;#34;)]
 [RegularExpression(&amp;#34;\\w+([-+.&amp;#39;]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*&amp;#34;,
 ErrorMessage = &amp;#34;邮箱格式不正确，请重新填写！&amp;#34;)]
 public String Email { get; set; }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;使用Required 、RegularExpression 等属性需要引用命名空间&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;using System.ComponentModel.DataAnnotations;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在Controllers目录下创建UserController.cs，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;namespace Mvc2Demo.Controllers
{
 public class UserController : Controller
 {
 public ActionResult Index()
 {
 return View();
 }
 public ActionResult Create()
 {
 Users user = new Users();
 return View(user);
 }
 //在ASP.NET MVC2预览一版中使用[HttpPost]
 //1.0版中使用[AcceptVerbs(HttpVerbs.Post)]
 [HttpPost]
 public ActionResult Create(Users user)
 {
 if (!ModelState.IsValid)
 {
 return View(user);
 }
 return View(&amp;#34;Success&amp;#34;);
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在上面的任意一个Create方法上右击，选择Add View … ，在弹出的对话框中做相应的设置，然后点击Add，就会在View下添加相应的目录和页面文件，如下图：&lt;/p&gt;</description></item><item><title>CLR Via C# 学习笔记（6） 方法参数相关（out ref params）</title><link>https://fwhyy.com/2009/07/clr-via-csharp-learning-notes-6-the-method-parameters-related/</link><pubDate>Thu, 16 Jul 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/07/clr-via-csharp-learning-notes-6-the-method-parameters-related/</guid><description>&lt;blockquote&gt;
&lt;p&gt;CLR Via C#》这本书以前就粗略看过两遍，但一直都没能深入理解，而且很多内容也忘记了，现在准备重新看一遍，并将看过的部分写出来，因为写的过程也是一个加深理解的过程。本系列算是学习的一个记录吧，也可以方便以后自己查阅，如果对大家还有些帮助的话，我就很高兴了。书我是选择性的看的，所以顺序和书中的顺序可能不一样。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;通常我们在使用方法的时候，方法的参数是按值传递的，如果传递的参数是引用类型的对象，是将引用对象的地址传给方法。如果传递的是值类型实例，传递给方法的是该实例的一个副本。允许使用在方法中按引用来传递参数，C#中使用out和ref关键字来体现。下面就来介绍out和ref的使用。&lt;/p&gt;
&lt;h2 id="out"&gt;out&lt;/h2&gt;
&lt;p&gt;1 使用out时在方法的参数定义和方法的调用时都要用out关键字，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;static void Main(string[] args)
{
 string name = string.Empty;
 GetStr(out name); //调用时加out
 Console.WriteLine(name);
}
private static void GetStr(out string name) //方法参数定义时的out
{
 name = &amp;#34;oec2003&amp;#34;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 如果一个方法有out修饰的参数，在方法结束前必须给给参数赋值，否则不能通过编译，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;static void Main(string[] args)
{
 string name = &amp;#34;oec2003&amp;#34;;
 GetStr(out name);
 Console.WriteLine(name);
}
private static void GetStr(out string name)
{
 //没有给name赋值，编译时会出现“控制离开当前方法之前必须对
 //out 参数“name”赋值”异常
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;3 在调用有out参数的方法时，没有必要给out参数赋初始值，因为赋的值不会传递到方法的内部，如果在方法的内部要强行使用out参数会有编译错误。代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;static void Main(string[] args)
{
 //给out参数name赋初始值oec2003
 string name = &amp;#34;oec2003&amp;#34;;
 GetStr(out name);
 Console.WriteLine(name);
}
private static void GetStr(out string name)
{
 name = &amp;#34;hello&amp;#34; + name;
 //name在调用前虽赋值为oec2003 ，
 //但此处会报错“使用了未赋值的 out 参数name”
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;4 通常我们需要在一个方法中返回多个值的时候就可以使用out参数。&lt;/p&gt;
&lt;p&gt;5 如果两个方法的参数个数和类型都相同，区别只是其中一个为out参数，那么这两个方法是可以进行重载的，下面的代码可以正常运行。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;private static void GetStr(out string name)
{
 name = &amp;#34;oec2003&amp;#34;;
}
private static void GetStr(string name)
{
 name = &amp;#34;oec2003&amp;#34;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="ref"&gt;ref&lt;/h2&gt;
&lt;p&gt;1 和out参数一样，使用ref时在方法的参数定义和方法的调用时都要用ref关键字。&lt;/p&gt;</description></item><item><title>AjaxPro版自动完成（Autocomplete）功能实现</title><link>https://fwhyy.com/2009/07/ajaxpro-autocomplete-function-implementation/</link><pubDate>Mon, 13 Jul 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/07/ajaxpro-autocomplete-function-implementation/</guid><description>&lt;p&gt;07年的时候写过一篇有关自动完成(Atuocomplete)的文章 &lt;a href="http://www.cnblogs.com/oec2003/archive/2007/08/18/860870.html"&gt;asp.net Ajax —AutoComplete控件使用&lt;/a&gt; ，那篇文章中使用的是Asp.net Ajax ControlTollKit中的一个控件，虽然那时对里面几十个控件都研究过，不过遗憾的是在实际开发中确从未用到过，鉴于现在Ajaxpro的易用性和普遍性，本文将使用ajaxpro来实现自动完成的功能。&lt;/p&gt;</description></item><item><title>CLR Via C# 学习笔记（5） 静态构造函数的性能</title><link>https://fwhyy.com/2009/07/clr-via-csharp-learning-notes-5-the-performance-of-the-static-constructor/</link><pubDate>Wed, 08 Jul 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/07/clr-via-csharp-learning-notes-5-the-performance-of-the-static-constructor/</guid><description>&lt;blockquote&gt;
&lt;p&gt;CLR Via C#》这本书以前就粗略看过两遍，但一直都没能深入理解，而且很多内容也忘记了，现在准备重新看一遍，并将看过的部分写出来，因为写的过程也是一个加深理解的过程。本系列算是学习的一个记录吧，也可以方便以后自己查阅，如果对大家还有些帮助的话，我就很高兴了。书我是选择性的看的，所以顺序和书中的顺序可能不一样。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在上一篇《CLR Via C# 学习笔记（4） 方法 构造函数 》中讲到了一些静态构造函数方面的知识，现在也回顾一下，大概总结如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;静态构造函数是私有的（private） ，而且不能人为去修改访问修饰符。&lt;/li&gt;
&lt;li&gt;静态构造函数不应该去调用基类的静态构造函数，因为静态字段不会被继承到子类。&lt;/li&gt;
&lt;li&gt;静态构造函数在一个类型中有且仅有一个，并且是无参的。&lt;/li&gt;
&lt;li&gt;静态构造函数中只能初始化静态字段。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;从上面的第一点可以知道静态构造函数都是private的，所以不能显示区进行调用，关于JIT何时会去生成调用静态构造函数的代码。存在着两种说法。通常被称为Precise和BeforeFieldInit。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Precise方式JIT编译器生成调用的时机：首次创建类型的代码之前；访问类的非继承字段或成员代码之前。&lt;/li&gt;
&lt;li&gt;BeforeFieldInit方式JIT编译器生成调用的时机：在访问费继承静态字段代码之前。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这两种方式的主要区别就是选择调用静态构造函数的时机是否是确定的，Precise方式CLR会在确定的时刻调用静态构造函数，而BeforeFieldInit方式CLR可以自由选择调用静态构造函数的时机，利用这一点，CLR可以根据类型是否在程序域中加载来选择静态构造函数的调用次数，以便能生成执行更快的代码。&lt;/p&gt;
&lt;p&gt;下面来看来个类分别展现了这两种方式&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public classUserPrecise
{
 public static string_name = &amp;#34;内联赋值：oec2003&amp;#34;;
 staticUserPrecise()
 {
 _name = &amp;#34;构造函数赋值：oec2003&amp;#34;;
 }
}
public classUserBeforeFieldInit
{
 public static string_name = &amp;#34;内联赋值：oec2003&amp;#34;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;通过IL代码可以看出在UserBeforeFieldInit 的元数据上有BeforeFieldInit的标记，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290802573.webp" alt="2010-12-29_173428" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;既然上面提到BeforeFieldInit方式CLR可以选择调用构造函数的次数从而来生成执行更快的代码，下面就写一段测试代码来看看究竟怎样。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;span class="lnt"&gt;50
&lt;/span&gt;&lt;span class="lnt"&gt;51
&lt;/span&gt;&lt;span class="lnt"&gt;52
&lt;/span&gt;&lt;span class="lnt"&gt;53
&lt;/span&gt;&lt;span class="lnt"&gt;54
&lt;/span&gt;&lt;span class="lnt"&gt;55
&lt;/span&gt;&lt;span class="lnt"&gt;56
&lt;/span&gt;&lt;span class="lnt"&gt;57
&lt;/span&gt;&lt;span class="lnt"&gt;58
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Test1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Test2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Test1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Stopwatch&lt;/span&gt; &lt;span class="n"&gt;sw&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stopwatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartNew&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;UserBeforeFieldInit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oec2003&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Test1-UserBeforeFieldInit 用时：&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;sw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Elapsed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sw&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stopwatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartNew&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;UserPrecise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oec2003&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Test1-UserPrecise 用时：&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;sw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Elapsed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Test2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Stopwatch&lt;/span&gt; &lt;span class="n"&gt;sw&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stopwatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartNew&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;UserBeforeFieldInit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oec2003&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Test2-UserBeforeFieldInit 用时：&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;sw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Elapsed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sw&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stopwatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartNew&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;UserPrecise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oec2003&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Test2-UserPrecise 用时：&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;sw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Elapsed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserBeforeFieldInit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserPrecise&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;UserPrecise&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oec2003&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;测试结果如下：&lt;/p&gt;</description></item><item><title>CLR Via C# 学习笔记（4） 方法 构造函数</title><link>https://fwhyy.com/2009/07/clr-via-csharp-learning-notes-5-methods-the-constructor/</link><pubDate>Fri, 03 Jul 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/07/clr-via-csharp-learning-notes-5-methods-the-constructor/</guid><description>&lt;blockquote&gt;
&lt;p&gt;《CLR Via C#》这本书以前就粗略看过两遍，但一直都没能深入理解，而且很多内容也忘记了，现在准备重新看一遍，并将看过的部分写出来，因为写的过程也是一个加深理解的过程。本系列算是学习的一个记录吧，也可以方便以后自己查阅，如果对大家还有些帮助的话，我就很高兴了。书我是选择性的看的，所以顺序和书中的顺序可能不一样。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;构造函数是可以将类型实例初始化为有效状态的特殊方法。构造函数在元数据中通常用.ctor来表示，通过IL代码可以看到。在创建一个类型的实例时，通常分为三步：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;为实例的数据字段分配内存。&lt;/li&gt;
&lt;li&gt;创建对象指针和同步索引块。&lt;/li&gt;
&lt;li&gt;调用类型的实例构造器来设置对象的初始状态。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="引用类型的实例构造器"&gt;引用类型的实例构造器&lt;/h2&gt;
&lt;p&gt;在创建一个引用类型的对象是，调用类型的实例构造函数之前，会将对象分配的内存做清零处理，就是说在构造函数中没有显示赋值的所有字段都将设置为0或null。&lt;/p&gt;
&lt;p&gt;实例构造函数和一般方法不同，他永远都不能被继承，所有以下的关键字也不能用于实例构造函数（virtual new override sealed abstract）。&lt;/p&gt;
&lt;p&gt;一个类中如果没有显示定义任何构造函数，C#编译器将定义一个默认的无参构造函数。&lt;/p&gt;
&lt;p&gt;抽象（abstract）类的默认构造函数的访问修饰符为protected。&lt;/p&gt;
&lt;p&gt;构造函数可以初始化字段，不过在c#语言中提供了一种简单的方法，在定义字段的时候直接赋值以初始化。如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class User
{
 private int _age = 25;
 private string _name = &amp;#34;oec2003&amp;#34;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;像上面那样的确很方便，但如果有好几个已经初始化的实例字段和多个重载的构造函数同时存在的情况下，就应该将实例字段的初始化放到一个公共的构造函数中，其他的构造函数通过this来显示调用该构造函数，这样可以减少代码生成的大小，看下面的例子。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class User
{
 private int _age = 25;
 private string _name = &amp;#34;oec2003&amp;#34;;
 private string _email = &amp;#34;oec2003@gmail.com&amp;#34;;

 public User(Int32 age)
 {
 this._age = age;
 }

 public User(string name)
 {
 this._name = name;
 }

 public User(Int32 age, String name, String email)
 {
 this._age = age;
 this._name = name;
 this._email = email;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;正确的写法应该像下面这样&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class User
{
 private int _age;
 private string _name;
 private string _email;

 public User()
 {
 _age = 25;
 _name = &amp;#34;oec2003&amp;#34;;
 _email = &amp;#34;oec2003@gmail.com&amp;#34;;
 }

 public User(Int32 age)
 : this()
 {
 this._age = age;
 }

 public User(string name)
 : this()
 {
 this._name = name;
 }

 public User(Int32 age, String name, String email)
 : this()
 {
 this._age = age;
 this._name = name;
 this._email = email;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="值类型的实例构造函数"&gt;值类型的实例构造函数&lt;/h2&gt;
&lt;p&gt;值类型的实例构造函数和引用类型的有很大不同，在值类型中不能含有无参的构造函数，如果显式指定无参的构造函数将会出现编译错误。如下面代码会出现编译错误：&lt;/p&gt;</description></item><item><title>Asp.Net中替代Eval的两种方式</title><link>https://fwhyy.com/2009/06/aspnet-instead-of-eval-in-two-ways/</link><pubDate>Fri, 26 Jun 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/06/aspnet-instead-of-eval-in-two-ways/</guid><description>&lt;p&gt;在asp.net中的数据绑定中，我们经常会用到Eval，不过大家都知道Eval绑定是通过反射来实现的， 而反射势必会对性能造成一定的影响。不过有两种替代的方式来实现绑定数据，对性能略有提高。&lt;/p&gt;
&lt;p&gt;1 当数据源为DataTable时，用下面的方式:&lt;/p&gt;
&lt;p&gt;后台代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;protected void Page_Load(object sender, EventArgs e)
{
 DataTable dt = new DataTable();
 dt.Columns.Add(&amp;#34;Name&amp;#34;, typeof(System.String));
 dt.Columns.Add(&amp;#34;Age&amp;#34;, typeof(System.Int32));
 for (int i = 0; i &amp;lt;= 20; i++)
 {
 DataRow dr = dt.NewRow();
 dr[0] = &amp;#34;oec2003_&amp;#34; + i.ToString();
 dr[1] = i + 20;
 dt.Rows.Add(dr);
 }

 rptUser.DataSource = dt;
 rptUser.DataBind();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;前台代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;asp:Repeater ID=&amp;#34;rptUser&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;ItemTemplate&amp;gt;
 姓名：&amp;lt;%# ((DataRowView)(Container.DataItem))[&amp;#34;Name&amp;#34;] %&amp;gt;
 年龄：&amp;lt;%# ((DataRowView)(Container.DataItem))[&amp;#34;Age&amp;#34;]%&amp;gt;&amp;lt;br /&amp;gt;
 &amp;lt;/ItemTemplate&amp;gt;
&amp;lt;/asp:Repeater&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 当数据源为泛型类时，用下面的方式。&lt;/p&gt;
&lt;p&gt;后台代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;protected void Page_Load(object sender, EventArgs e)
{
 List&amp;lt;User&amp;gt; user = new List&amp;lt;User&amp;gt;();
 for (int i = 0; i &amp;lt; 10; i++)
 {
 user.Add(new User(i, &amp;#34;oec2003&amp;#34;));
 }
 rptUser.DataSource = user;
 rptUser.DataBind();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;前台代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;asp:Repeater ID=&amp;#34;rptUser&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;ItemTemplate&amp;gt;
 姓名：&amp;lt;%# (Container.DataItem as User).Name %&amp;gt;
 年龄：&amp;lt;%# (Container.DataItem as User).Age%&amp;gt;&amp;lt;br /&amp;gt;
 &amp;lt;/ItemTemplate&amp;gt;
&amp;lt;/asp:Repeater&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;经过测试在10w以上数据量的时候性能差别才比较明显，而我们平时做数据绑定的时候通常都是用的分页存储过程或其他的分页方式，每页最多几十条数据，所以我认为Eval在性能上的损耗并不构成性能瓶颈。&lt;/p&gt;</description></item><item><title>CLR Via C# 学习笔记（3） 常量和字段（const readonly）</title><link>https://fwhyy.com/2009/06/clr-via-csharp-learning-notes-3-constants-and-fields/</link><pubDate>Mon, 22 Jun 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/06/clr-via-csharp-learning-notes-3-constants-and-fields/</guid><description>&lt;blockquote&gt;
&lt;p&gt;《CLR Via C#》这本书以前就粗略看过两遍，但一直都没能深入理解，而且很多内容也忘记了，现在准备重新看一遍，并将看过的部分写出来，因为写的过程也是一个加深理解的过程。本系列算是学习的一个记录吧，也可以方便以后自己查阅，如果对大家还有些帮助的话，我就很高兴了。书我是选择性的看的，所以顺序和书中的顺序可能不一样。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;常量和字段都是类型的数据成员，但是区别却是很大的。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;常量的值永远不会改变。字段有多种类型，非只读字段的值是可以改变的。&lt;/li&gt;
&lt;li&gt;常量的值必须在编译时就确定，也就是说在定义时就要赋值。编译后常量的值就保存在程序集的元数据中；字段是存储在动态内存中，在运行时才能得到字段的值。&lt;/li&gt;
&lt;li&gt;常量的定义必须用基元类型，关于基元类型可以参考(CLR Via C# 学习笔记（1） 基元类型 值类型 引用类型 )；字段的定义可以是任何类型。&lt;/li&gt;
&lt;li&gt;因为常量的值不能改变，可以将其看做是静态类型，在IL代码中可以看到常量有static修饰符，所以在调用的时候和调用静态字段一样，直接用类名.常量名；字段中的静态字段的调用才和常量一样直接用类名.字段名，调用非静态字段必须用类的实例。、&lt;/li&gt;
&lt;li&gt;C#不允许使用static修饰常量，因为常量本身就隐含是static类型；字段可以使用static，使用static定义的字段为静态字段。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="下面看个例子来理解下常量"&gt;下面看个例子来理解下常量&lt;/h2&gt;
&lt;p&gt;1 创建一个类库项目命名为Oec2003ClassLibrary ,在默认的类Class1中写如下代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;namespace Oec2003ClassLibrary
{
 public class Class1
 {
 public const double PI = 3.14;

 public static double _pi = 3.14;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 创建一个web项目，添加对Oec2003ClassLibrary类库项目的引用，新建页面ConstTest.aspx,在PageLoad中写如下代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;protected void Page_Load(object sender, EventArgs e)
{
 Response.Write(Class1.PI+&amp;#34;&amp;lt;br/&amp;gt;&amp;#34;);
 Response.Write(Class1._pi);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;3 将ConstTest设为起始页，运行，可以看到结果如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290816263.webp" alt="2010-12-29_181713" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;4 现在将Oec2003ClassLibrary 项目中的Class1的代码改写如下，然后从新编译该项目。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;namespace Oec2003ClassLibrary
{
 public class Class1
 {
 public const double PI = 3.1415926;
 public static double _pi = 3.1415926;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5 刷新刚才的页面 ，可以看到结果如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290816174.webp" alt="2010-12-29_181748" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;6 从新运行ConstTest页面可以看到如下结果&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290816233.webp" alt="2010-12-29_181824" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;从上面的例子可以看出，在应用程序不从新编译的情况下，常量的值永远不会发生改变。如果应用程序想要获得常量的新值，就必须重新编译，所以在运行时一个应用程序集想获得另一个应用程序集中的值，则不能使用常量，可以使用只读字段（readonly）。&lt;/p&gt;
&lt;p&gt;字段也是一种类型的数据成员，字段的修饰符有 static readonly volatile，没有上述修饰修饰的字段为普通的实例字段。static可以和readonly一起使用，就是静态只读字段。有关volatile将在后面的部分介绍。&lt;/p&gt;
&lt;h2 id="关于readonly要注意的地方"&gt;关于readonly要注意的地方&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;当readonly修饰的字段为值类型时，在调用的时候如果视图去改变字段的值，将会编译出错。&lt;/li&gt;
&lt;li&gt;当readonly修饰的字段为引用类型时，调用时不能改变其引用，但可以改变应用对象的值，看下面的例子。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;1 在Oec2003ClassLibrary项目的Class1.cs文件写如下代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;namespace Oec2003ClassLibrary
{
 public class Class1
 {
 public const double PI = 3.14;
 public static readonly double _pi = 3.14;

 public static readonly User user = new User(&amp;#34;oec2003&amp;#34;);
 }
 public class User
 {
 public User(string name)
 {
 Name = name;
 }
 public string Name { get; set; }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 在web项目中添加页面，命名为Readonly.aspx，PageLoad代码如下&lt;/p&gt;</description></item><item><title>CLR Via C# 学习笔记（2） 装箱和拆箱</title><link>https://fwhyy.com/2009/06/clr-via-csharp-learning-notes-2-boxing-and-unboxing/</link><pubDate>Thu, 18 Jun 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/06/clr-via-csharp-learning-notes-2-boxing-and-unboxing/</guid><description>&lt;blockquote&gt;
&lt;p&gt;CLR Via C#》这本书以前就粗略看过两遍，但一直都没能深入理解，而且很多内容也忘记了，现在准备重新看一遍，并将看过的部分写出来，因为写的过程也是一个加深理解的过程。本系列算是学习的一个记录吧，也可以方便以后自己查阅，如果对大家还有些帮助的话，我就很高兴了。书我是选择性的看的，所以顺序和书中的顺序可能不一样。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;装箱和拆箱是已经被嚼烂的两个概念了，并且在一些面试中也经常考到。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;装箱：将值类型转换为引用类型。&lt;/li&gt;
&lt;li&gt;拆箱：将引用类型转换为值类型。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;值类型是一种相对轻型的类型，不像对象那样在托管堆中分配，也不会被GC，不通过指针来引用，不过在有些时候需要获取对值类型的引用，例如在使用net1.0的集合类ArrayList的时候。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ArrayList&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ArrayList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//因Point为值类型，分配在堆栈中&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//初始化Point中的成员&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//对p进行装箱后，将引用添加到list中&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;ArrayList的Add方法是接受一个Object参数，如下&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;所以在执行Add方法时会将Point值类型转换为一个堆得托管对象，并获取到这个对象的引用，将引用地址存储在ArrayList中。&lt;/p&gt;
&lt;p&gt;在一个值类型装箱的时候内部发生的事情：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在托管堆分配好内存。分配的内存是值类型的各个字段所需内存量加上托管堆上的两个额外成员（类型对象指针和同步索引块）所需的内存量。&lt;/li&gt;
&lt;li&gt;值类型中的字段值复制到新分配的堆内存中。&lt;/li&gt;
&lt;li&gt;返回对象的引用地址。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;拆箱就是执行和装箱相反的操作，将引用类型转化为值类型。接上面的代码，获取ArrayList中的元素值用如下代码：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="p"&gt;=(&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;X:&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#34; Y:&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上面的代码中通过索引取到ArrayList中存储的各个Point的引用地址，通过Point类型转换将其对应的值从堆中复制到Point的实例point中，这个转换的过程就是拆箱的过程。&lt;/p&gt;
&lt;p&gt;在拆箱的过程中要注意以下两点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;如果对已装箱的值类型的引用的变量为null，会引发NullRefreenceException异常&lt;/li&gt;
&lt;li&gt;如果一个引用指向的对象在拆箱时不是用的装箱时所使用的类型，将会引发InvalidCastException异常。代码如下：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Int16&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//引发InvalidCastException异常&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;正确的做法是，现将其用Int32类型来拆箱，然后再强制转换为Int16&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Int16&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int16&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;下面来看两段程序来深入理解下装箱和拆箱&lt;/p&gt;
&lt;p&gt;代码一：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;123&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;, &amp;#34;&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上面的代码中有多少次装箱呢？乍一看好像就一次（Object o=x；），其实一共有三次装箱，看看IL代码就一目了然了。&lt;/p&gt;</description></item><item><title>CLR Via C# 学习笔记（1） 基元类型 值类型 引用类型</title><link>https://fwhyy.com/2009/06/clr-via-csharp-learning-notes-1-primitive-types/</link><pubDate>Wed, 17 Jun 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/06/clr-via-csharp-learning-notes-1-primitive-types/</guid><description>&lt;blockquote&gt;
&lt;p&gt;CLR Via C#》这本书以前就粗略看过两遍，但一直都没能深入理解，而且很多内容也忘记了，现在准备重新看一遍，并将看过的部分写出来，因为写的过程也是一个加深理解的过程。本系列算是学习的一个记录吧，也可以方便以后自己查阅，如果对大家还有些帮助的话，我就很高兴了。书我是选择性的看的，所以顺序和书中的顺序可能不一样。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;首先了解下什么是基元类型，基元类型是编译器直接支持的数据类型，像我们平时经常用到的int string bool 都是基元类型，基元类型是映射到FCL中的类型，像前面的三种类型对应到FCL中就是Int32 String Boolean，基元类型只是给我们的编程提供了方便，它和FCL中的类型在编译后最终生成的IL完全相同。下面给出基元类型和FCL类型的对应表&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;C#基元类型&lt;/th&gt;
					&lt;th&gt;FCL类型&lt;/th&gt;
					&lt;th&gt;CLS相容&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;sbyte&lt;/td&gt;
					&lt;td&gt;System.Sbyte&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;byte&lt;/td&gt;
					&lt;td&gt;System.Byte&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;short&lt;/td&gt;
					&lt;td&gt;System.Int16&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;ushort&lt;/td&gt;
					&lt;td&gt;System.UInt16&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;int&lt;/td&gt;
					&lt;td&gt;System.Int32&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;uint&lt;/td&gt;
					&lt;td&gt;System.Uint32&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;long&lt;/td&gt;
					&lt;td&gt;System.Int64&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;ulong&lt;/td&gt;
					&lt;td&gt;System.Uint64&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;char&lt;/td&gt;
					&lt;td&gt;System.Char&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;float&lt;/td&gt;
					&lt;td&gt;System.Single&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;double&lt;/td&gt;
					&lt;td&gt;System.Double&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;bool&lt;/td&gt;
					&lt;td&gt;System.Boolean&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;decimal&lt;/td&gt;
					&lt;td&gt;System.Decimal&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;object&lt;/td&gt;
					&lt;td&gt;System.Object&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;string&lt;/td&gt;
					&lt;td&gt;System.String&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;我们平时在写程序时通常都是使用基元类型，因为方便，但本书的作者认为应该直接使用FCL中的类型，原因如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在c#中long对应的FCL类型为System.Int64，但是在其他的语言中，如c++ 就将long视为一个Int32。这样习惯于一种编程语言的人在看另一种编程语言写的源码是就会产生错误的理解。&lt;/li&gt;
&lt;li&gt;在FCL中的许多的方法将类型名作为方法名的一部分，如System.Convert类提供ToBoolean,ToInt32,ToSingle等。这样在使用基元类型做类型转换时就感觉有点怪怪的，如：float val=Convert.ToSingle(“23”);&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="值类型和引用类型的区别"&gt;值类型和引用类型的区别&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;所有的值类型都是从System.TypeValue派生，如Struct Enum都是值类型；所有引用类型都是从System.Object派生。&lt;/li&gt;
&lt;li&gt;值类型分配在线程堆栈上，引用类型分配在托管堆上。&lt;/li&gt;
&lt;li&gt;值类型表现形式有未装箱形式和已装箱形式，而引用类型总是已装箱形式。&lt;/li&gt;
&lt;li&gt;所有的值类型都是sealed类型，所以值类型不能作为任何类型的基类型，也不能在值类型中引入虚方法。&lt;/li&gt;
&lt;li&gt;创建一个引用类型变量时，会被初始化为null，试图使用一个null的引用类型变量时，会抛出NullReferenceException异常，也就是常见的“未将对象引用设置到对象的实例”；值类型在创建时所有成员都初始化为0了，所以不会抛出该异常。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="原文例子表示值类型和引用类型的区别"&gt;原文例子表示值类型和引用类型的区别&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;class Program
{
 static void Main(string[] args)
 {
 SomeRef r1 = new SomeRef();
 SomeVal v1 = new SomeVal();
 r1.x = 5;
 v1.x = 5;
 Console.WriteLine(r1.x); //5
 Console.WriteLine(v1.x); //5
 SomeRef r2 = r1;
 SomeVal v2 = v1;
 r1.x = 8;
 v1.x = 9;
 Console.WriteLine(r1.x); //8
 Console.WriteLine(r2.x); //9
 Console.WriteLine(v1.x); //9
 Console.WriteLine(v2.x); //5
 }
}
class SomeRef
{
 public Int32 x;
}
struct SomeVal
{
 public Int32 x;
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="clr中类型字段布局的控制"&gt;CLR中类型字段布局的控制&lt;/h2&gt;
&lt;p&gt;为了提高性能，clr能按照所选择的任何方式来排列类型的字段。我们可以通过在类会是结构上使用System.Runtime.InteropServices.StructLayoutAttribute属性来改变这种排列的顺序。该属性接受一个LayoutKind的枚举值（Auto，Sequential，Explicit），默认情况下C#编译器会为类选择Atuo，为结构选择Sequential。下面来定义一个类和一个结构&lt;/p&gt;</description></item><item><title>ZedGraph在Web中的使用</title><link>https://fwhyy.com/2009/06/use-zedgraph-in-the-web/</link><pubDate>Sat, 06 Jun 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/06/use-zedgraph-in-the-web/</guid><description>&lt;p&gt;上一篇&lt;a href="http://blog.fwhyy.com/2009/06/sql-implementation-group-statistical-query/"&gt;SQL实现分组统计查询（按月、小时分组）&lt;/a&gt; 中介绍了按月和小时为单位怎样实现分组查询，在本文中会实现将上文查询的结果以图表的形式显示在页面上。在页面上显示图标有很多种解决方案，office的owc组建、自己写代码、或者是第三方的控件。本文中将使用ZedGraph控件来实现。选择ZedGraph有两个原因：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;该控件是开源的，在必要的时候可以根据自己的需要来修改；&lt;/li&gt;
&lt;li&gt;该控件所显示的图片是绘出来的，而不是生成的图片。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下载地址：&lt;a href="http://sourceforge.net/project/showfiles.php?group_id=114675"&gt;http://sourceforge.net/project/showfiles.php?group_id=114675&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;1 将控件引用到项目中，本示例使用的是5.1.5版。&lt;/p&gt;
&lt;p&gt;在工具栏下方的空白处点击右键—&amp;gt;添加选项卡,命名为ZedGraph&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290709681.webp" alt="2010-12-30_101747" loading="lazy" decoding="async"&gt;

&lt;img src="https://img.fwhyy.com/2022/202201290709929.webp" alt="2010-12-30_101836" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;在ZedGraph选项卡点右键—&amp;gt;选择项…,在弹出窗口中选择下载下来的ZedGraph.Web.dll文件。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290709682.webp" alt="https://img.fwhyy.com/14712687428710.webp" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;2 在项目中新建一aspx页面，命名为Year.aspx,将刚添加的ZedGraph控件拖到页面中，并在页面中添加一个文本框和一个按钮，文本框用来选择年份。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290710090.webp" alt="2010-12-30_102641" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 切换到代码视图，添加如下代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;namespace ZedGraphDemo
{
 public partial class Year : System.Web.UI.Page
 {
 protected void Page_Load(object sender, EventArgs e)
 {
 this.ZgwYear.RenderGraph +=
 new ZedGraphWebControlEventHandler(ZgwYear_RenderGraph);
 }

 void ZgwYear_RenderGraph(ZedGraphWeb webObject,
 System.Drawing.Graphics g, MasterPane pane)
 {
 GraphPane myPane = pane[0];

 // 标题
 myPane.Title.Text = &amp;#34;每年分析（月为单位）&amp;#34;;
 myPane.XAxis.Title.Text = &amp;#34;时间&amp;#34;;
 myPane.YAxis.Title.Text = &amp;#34;访问量&amp;#34;;

 // 坐标对集
 PointPairList list = new PointPairList();
 //PointPairList list1 = new PointPairList();
 //PointPairList list2 = new PointPairList();

 //从数据库中获取数据集
 DataTable dtYear = GetData();
 if (dtYear == null)
 return;
 for (int i = 0; i &amp;lt; dtYear.Rows.Count; i++)
 {
 list.Add(Convert.ToDouble(i), Convert.ToDouble(dtYear.Rows[i][&amp;#34;Count&amp;#34;]));
 //如果有多种类型，可以添加多个
 //list1.Add(Convert.ToDouble(i), Convert.ToDouble(dtYear.Rows[i][&amp;#34;Count1&amp;#34;]));
 //list2.Add(Convert.ToDouble(i), Convert.ToDouble(dtYear.Rows[i][&amp;#34;Count2&amp;#34;]));
 }

 BarItem myBar = myPane.AddBar(&amp;#34;页面访问&amp;#34;, list, Color.Blue);
 //BarItem myBar1 = myPane.AddBar(&amp;#34;&amp;#34;, list1, Color.Red);
 //BarItem myBar2 = myPane.AddBar(&amp;#34;&amp;#34;, list2, Color.Yellow);

 myBar.Bar.Fill = new Fill(Color.Blue, Color.White, Color.Blue);
 //myBar1.Bar.Fill = new Fill(Color.Red, Color.White, Color.Red);
 //myBar2.Bar.Fill = new Fill(Color.Yellow, Color.White, Color.Yellow);

 myPane.XAxis.MajorTic.IsBetweenLabels = true;
 // X轴Label
 string[] labels = new string[] { &amp;#34;1月&amp;#34;, &amp;#34;2月&amp;#34;, &amp;#34;3月&amp;#34;, &amp;#34;4月&amp;#34;, &amp;#34;5月&amp;#34;, &amp;#34;6月&amp;#34;,
 &amp;#34;7月&amp;#34;, &amp;#34;8月&amp;#34;, &amp;#34;9月&amp;#34;, &amp;#34;10月&amp;#34;, &amp;#34;11月&amp;#34;, &amp;#34;12月&amp;#34; };

 //设置x轴刻度
 myPane.XAxis.Scale.TextLabels = labels;
 myPane.XAxis.Type = AxisType.Text;

 // 颜色填充
 myPane.Fill = new Fill(Color.White, Color.FromArgb(200, 200, 255), 45.0f);
 myPane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45.0f);

 pane.AxisChange(g);

 myPane.YAxis.Scale.Max += myPane.YAxis.Scale.MajorStep;
 BarItem.CreateBarLabels(myPane, false, &amp;#34;f0&amp;#34;); //在柱状图上方显示统计数
 }

 protected void btnQuerys_Click(object sender, EventArgs e)
 {
 GetData();
 }

 private DataTable GetData()
 {
 SqlHelper.ConnectionString =
 ConfigurationManager.AppSettings[&amp;#34;ConnectionString&amp;#34;].ToString();
 SqlParameter[] parameters = new SqlParameter[1];

 parameters[0] = new SqlParameter(&amp;#34;@Year&amp;#34;, SqlDbType.Int, 4);
 parameters[0].Value = this.txtYear.Value.Trim().Length == 0 ? DateTime.Now.Year :
 Convert.ToInt32(txtYear.Value.Trim());
 DataSet ds = SqlHelper.ExecuteDataset(&amp;#34;Counter_CounterYear&amp;#34;, parameters);
 if (ds != null &amp;amp;&amp;amp; ds.Tables.Count &amp;gt; 0 &amp;amp;&amp;amp; ds.Tables[0].Rows.Count &amp;gt; 0)
 {
 return ds.Tables[0];
 }
 else
 {
 return null;
 }
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;4 在项目的根目录下创建一个名为ZedGraphImages的文件夹，只是作为ZedGraph绘图时的一个临时目录，并不会在该文件夹中生成图片，如果没有该文件夹会报异常。&lt;/p&gt;</description></item><item><title>SQL实现分组统计查询（按月、小时分组）</title><link>https://fwhyy.com/2009/06/sql-implementation-group-statistical-query/</link><pubDate>Thu, 04 Jun 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/06/sql-implementation-group-statistical-query/</guid><description>&lt;h2 id="首先创建数据表"&gt;首先创建数据表&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Create table Counter
(
 CounterID int identity(1,1) not null,
 IP varchar(20),
 AccessDateTime datetime,
 AccessCount int
)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;该表在这儿只是演示使用，所以只提供了最基本的字段:IP地址，访问时间和访问次数。如果每访问一次就插入一条记录，那么AccessCount可以不要，查询时使用count就可以了，这样当访问量很大的时候会对数据库造成很大压力。设置AccessCount字段可以根据需求在特定的时间范围内如果是相同IP访问就在AccessCount上累加。&lt;/p&gt;
&lt;p&gt;现在往表中插入几条记录&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;insert into Counter
select &amp;#39;127.0.0.1&amp;#39;,getdate(),1 union all
select &amp;#39;127.0.0.2&amp;#39;,getdate(),1 union all
select &amp;#39;127.0.0.3&amp;#39;,getdate(),1
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="根据年来查询以月为时间单位"&gt;根据年来查询，以月为时间单位&lt;/h2&gt;
&lt;p&gt;通常情况下一个简单的分组就能搞定&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;select
 convert(varchar(7),AccessDateTime,120) as Date,
 sum(AccessCount) as [Count]
from
 Counter
group by
 convert(varchar(7),AccessDateTime,120)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;像这样分组后没有记录的月份不会显示，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201301950583.webp" alt="2010-12-30_103754" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;这当然不是我们想要的，所以得换一种思路来实现，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;declare @Year int
set @Year=2009
select
 m as [Date],
 sum(
 case when datepart(month,AccessDateTime)=m
 then AccessCount else 0 end
 ) as [Count]
from
 Counter c,
 (
 select 1 m
 union all select 2
 union all select 3
 union all select 4
 union all select 5
 union all select 6
 union all select 7
 union all select 8
 union all select 9
 union all select 10
 union all select 11
 union all select 12
 ) aa
where
 @Year=year(AccessDateTime)
group by
 m
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查询结果如下：&lt;/p&gt;</description></item><item><title>在vs2008中设置jquery智能提示</title><link>https://fwhyy.com/2009/05/in-setting-the-jquery-vs2008-intellisense/</link><pubDate>Wed, 20 May 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/05/in-setting-the-jquery-vs2008-intellisense/</guid><description>&lt;p&gt;1 要确保您的vs2008已经打了sp1补丁，可以点击&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=27673C47-B3B5-4C67-BD99-84E525B5CE61&amp;amp;displaylang=zh-cn"&gt;这里&lt;/a&gt;下载&lt;/p&gt;
&lt;p&gt;2 下载 jQuery-vsdoc.js ，如果您安装了asp.net mvc ，可以在mvc的项目下的srcipts目下找到，或是点击&lt;a href="http://docs.jquery.com/Downloading_jQuery#Download_jQuery"&gt;这里&lt;/a&gt;下载。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300705034.webp" alt="2010-12-30_104425" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;3 下载安装一个vs2008支持 -vsdoc.js 智能提示的一个补丁 ，可以点击这里下载&lt;/p&gt;
&lt;p&gt;4 准备工作已经做完，现在就可以来试试jquery的智能提示了，用vs2008新建一个项目，在页面的head标签里添加对jquery-1.3.2-vsdoc.js的引用&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300705137.webp" alt="2010-12-30_104506" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;5 现在在js的方法中敲一个$符号，智能提示就会弹出来。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300705914.webp" alt="2010-12-30_104541" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;参考文章：&lt;a href="http://weblogs.asp.net/scottgu/archive/2008/11/21/jquery-intellisense-in-vs-2008.aspx"&gt;http://weblogs.asp.net/scottgu/archive/2008/11/21/jquery-intellisense-in-vs-2008.aspx&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Sqlserver2005附加数据库为只读的解决方法</title><link>https://fwhyy.com/2009/05/sqlserver2005-additional-database-for-read-only-solutions/</link><pubDate>Fri, 08 May 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/05/sqlserver2005-additional-database-for-read-only-solutions/</guid><description>&lt;h2 id="症状"&gt;症状：&lt;/h2&gt;
&lt;p&gt;在sqlserver2005中附加数据库时，附加的数据库会变成只读的，只能进行查询操作。&lt;/p&gt;</description></item><item><title>Asp.net中递归实现CSS菜单</title><link>https://fwhyy.com/2009/04/aspnet-recursive-implementation-of-css-menu/</link><pubDate>Sat, 18 Apr 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/04/aspnet-recursive-implementation-of-css-menu/</guid><description>&lt;p&gt;现在网络上有各种各样的非常漂亮的css菜单，不过大多都是静态的，菜单项都是在页面中写死的，这样就不是很灵活，每次要修改菜单都要去修改页面，下面就介绍一个从数据库中读取菜单项的动态css菜单的例子。&lt;/p&gt;</description></item><item><title>NHibernate入门级示例（增 删 改）</title><link>https://fwhyy.com/2009/01/an-introduction-to-the-sample-to-nhibernate/</link><pubDate>Tue, 20 Jan 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/01/an-introduction-to-the-sample-to-nhibernate/</guid><description>&lt;p&gt;NHibernate相信大家都已非常熟悉，园子里有很多高手写了相关的系列文章，不过我还是NHibernate的一名初学者，在此将一个晚上学习成果分享一下，一个很简单的利用NHibernate实现增删改的例子。&lt;/p&gt;</description></item><item><title>Asp.net 2.0的Eval方法详解</title><link>https://fwhyy.com/2009/01/aspnet-2-0-the-eval-method-of-explanation/</link><pubDate>Wed, 14 Jan 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/01/aspnet-2-0-the-eval-method-of-explanation/</guid><description>&lt;p&gt;实际上Eval方法是TemplateControl的，而System.Web.UI.Page和System.Web.UI.UserControl都继承于TemplateControl，所以我们可以在Page和UserControl上直接调用个方法。
Page.Eval方法可以帮助我们更好的撰写数据绑定表达式，在ASP.NET 1.x时代，数据绑定表达式的一般形式是：&lt;/p&gt;</description></item><item><title>Asp.Net 连接Access数据库</title><link>https://fwhyy.com/2009/01/aspnet-access-database-connection/</link><pubDate>Sat, 10 Jan 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/01/aspnet-access-database-connection/</guid><description>&lt;p&gt;自学程序以来，一直使用的都是sqlserver数据库，最近帮一朋友做一个access的demo，发现在数据库的连接方面就存在很大差异，在web.config中配置好连接字符串，然后在后台取，在此我的做法是存两个值，将Provider和assess数据库文件的路径分开存，如下：&lt;/p&gt;</description></item><item><title>消除window.close()的提示窗口</title><link>https://fwhyy.com/2009/01/eliminate-the-prompt-window/</link><pubDate>Thu, 08 Jan 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/01/eliminate-the-prompt-window/</guid><description>&lt;p&gt;Window.close()这句脚本是用来关闭当前窗口，如果是在window.open的窗口中执行Window.close()，将会很顺利地将窗口关闭，但如果是在一非window.open打开的窗口中执行Window.close()，将会弹出一个提示窗口，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201300636671.webp" alt="2010-12-30_124855" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;要在程序中消除这个提示框也很简单，不过在IE6和IE7稍有不同&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;IE6&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;html xmlns=&amp;#34;http://www.w3.org/1999/xhtml&amp;#34; &amp;gt;
&amp;lt;head id=&amp;#34;Head1&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;title&amp;gt;IE6Close&amp;lt;/title&amp;gt;
 &amp;lt;script type=&amp;#34;text/javascript&amp;#34;&amp;gt;
 function closeWin()
 {
 window.opener=null;
 window.close();
 }
 &amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
 &amp;lt;form id=&amp;#34;form2&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;div&amp;gt;
 &amp;lt;input id=&amp;#34;btnClose&amp;#34; type=&amp;#34;button&amp;#34; value=&amp;#34;close&amp;#34; onclick=&amp;#34;closeWin()&amp;#34;/&amp;gt;
 &amp;lt;/div&amp;gt;
 &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2.IE7&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;html xmlns=&amp;#34;http://www.w3.org/1999/xhtml&amp;#34; &amp;gt;
&amp;lt;head id=&amp;#34;Head1&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;title&amp;gt;IE7Colse&amp;lt;/title&amp;gt;
 &amp;lt;script type=&amp;#34;text/javascript&amp;#34;&amp;gt;
 function closeWin()
 {
 window.open(&amp;#39;&amp;#39;,&amp;#39;_self&amp;#39;,&amp;#39;&amp;#39;);
 window.close();
 }
 &amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
 &amp;lt;form id=&amp;#34;form2&amp;#34; runat=&amp;#34;server&amp;#34;&amp;gt;
 &amp;lt;div&amp;gt;
 &amp;lt;input id=&amp;#34;btnClose&amp;#34; type=&amp;#34;button&amp;#34; value=&amp;#34;close&amp;#34; onclick=&amp;#34;closeWin()&amp;#34;/&amp;gt;
 &amp;lt;/div&amp;gt;
 &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Response.Redirect在新窗口打开 &amp;&amp; 3.0扩展方法</title><link>https://fwhyy.com/2009/01/response-redirect-in-a-new-window-open-3-0-extension-methods/</link><pubDate>Wed, 07 Jan 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/01/response-redirect-in-a-new-window-open-3-0-extension-methods/</guid><description>&lt;p&gt;Response.Rederect在默认情况下是在本页跳转，所以除了在js中用window.open 或是给A标签添加target属性之外，在后台似乎不能来打开新的页面，其实不然，通过设置form的target属性同样可以让Response.Rederect所指向的url在新的窗口打开。下面用三种方法来实现。&lt;/p&gt;</description></item><item><title>MasterPage 小谈</title><link>https://fwhyy.com/2008/12/masterpage-introduction/</link><pubDate>Sat, 06 Dec 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/12/masterpage-introduction/</guid><description>&lt;h2 id="设置title"&gt;设置Title&lt;/h2&gt;
&lt;p&gt;1 如果想所有使用了masterpage的页面都是用一个title ，可以在masterpage页中设置title，并将内容页中的title去掉，否则内容页中的title会将masterpage中的title覆盖。&lt;/p&gt;</description></item><item><title>利用HttpModule实现防sql注入</title><link>https://fwhyy.com/2008/11/using-httpmodule-prevent-sql-injection/</link><pubDate>Sun, 23 Nov 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/11/using-httpmodule-prevent-sql-injection/</guid><description>&lt;p&gt;sql注入是被谈的很多的一个话题，有很多的方法能够实现sql的防注入，在这里就简单说一下如果使用HttpModule来实现sql的防注入。&lt;/p&gt;</description></item><item><title>CheckBox全选终极方案</title><link>https://fwhyy.com/2008/10/the-ultimate-solution-checkbox-selection/</link><pubDate>Thu, 23 Oct 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/10/the-ultimate-solution-checkbox-selection/</guid><description>&lt;p&gt;在我们的程序开发中经常会要用到CheckBox的全选，通常情况下是在一些数据绑定控件中如Gridview等&lt;/p&gt;</description></item><item><title>My97 使用的一点技巧</title><link>https://fwhyy.com/2008/10/some-tips-of-my97/</link><pubDate>Wed, 15 Oct 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/10/some-tips-of-my97/</guid><description>&lt;h2 id="需求"&gt;需求：&lt;/h2&gt;
&lt;p&gt;1.两个时间文本框，一个开始时间和一个结束时间，两个时间都是今天起以后的时间，并且开始时间不能大于结束时间。&lt;/p&gt;
&lt;p&gt;这样的需求在很多地方都会应用到，比如有些网站提供一些服务的购买，用户需要选择要购买服务的时间域等等。&lt;/p&gt;
&lt;p&gt;在My97的官网中有自定义时间的例子，我只是根据需要稍加了修改，代码如下:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;
&amp;lt;script type=&amp;#34;text/javascript&amp;#34; src=&amp;#34;WdatePicker.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;input id=&amp;#34;txtB&amp;#34; type=&amp;#34;text&amp;#34;
onclick=&amp;#34;WdatePicker({minDate:&amp;#39;%y-%M-#{%d}&amp;#39;,maxDate:&amp;#39;#F{$dp.$D(\&amp;#39;txtE\&amp;#39;,{d:-1})}&amp;#39;})&amp;#34;/&amp;gt;
&amp;lt;input id=&amp;#34;txtE&amp;#34; type=&amp;#34;text&amp;#34;
onFocus=&amp;#34;WdatePicker({minDate:&amp;#39;#F{$dp.$D(\&amp;#39;txtB\&amp;#39;,{d:1})||\&amp;#39;%y-%M-#{%d+2}\&amp;#39;}&amp;#39;})&amp;#34;/&amp;gt;

&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>SQL 计算一個字符串在另一个字符串中出現的次数</title><link>https://fwhyy.com/2008/08/sql-to-calculate-a-string-in-the-number-of-occurrences-of-another-string/</link><pubDate>Wed, 06 Aug 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/08/sql-to-calculate-a-string-in-the-number-of-occurrences-of-another-string/</guid><description>&lt;p&gt;在sqlserver中來計算一個字符串在另一個字符串中出現的次數，通常會去用循環來匹配，然後計算出出現的次數，這樣的效能不是很高。現在講一種比較簡單的方法也能實現同樣的功能，思路如下：&lt;/p&gt;</description></item><item><title>开发总结—数据库篇</title><link>https://fwhyy.com/2008/08/summary-the-database-development/</link><pubDate>Wed, 06 Aug 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/08/summary-the-database-development/</guid><description>&lt;p&gt;本文是我在平时工作中所遇到的数据库方面的一些知识总结&lt;/p&gt;</description></item><item><title>清除上传控件 File 的值</title><link>https://fwhyy.com/2008/07/remove-the-file-upload-control-values/</link><pubDate>Fri, 04 Jul 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/07/remove-the-file-upload-control-values/</guid><description>&lt;p&gt;因为File控件的value值是只读的，所以用document.getElementById(“File1″).value=”” 并不能清楚file控件的值。&lt;/p&gt;</description></item><item><title>解決“无法解决 equal to 操作的排序规则冲突 ”问题</title><link>https://fwhyy.com/2008/07/to-solve-the-unable-to-solve-the-equal-to-operation-collation-conflict-problem/</link><pubDate>Thu, 03 Jul 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/07/to-solve-the-unable-to-solve-the-equal-to-operation-collation-conflict-problem/</guid><description>&lt;h2 id="问题"&gt;问题：&lt;/h2&gt;
&lt;p&gt;在创建存储过程时 出现 “无法解决 equal to 操作的排序规则冲突 ”&lt;/p&gt;
&lt;h2 id="解决方法"&gt;解决方法：&lt;/h2&gt;
&lt;p&gt;1 WHERE 列名 collate Chinese_PRC_CI_AS(强制指定排序规则)，如：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;select
 *
from
 test
where
 name collate chinese_prc_ci_as in
 (select name1 chinese_prc_ci_as from test1)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 如果涉及到多表查询，则在on后面加上collate Chinese_PRC_CI_AS(强制指定排序规则) 如：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;select
 *
from
 test1 1
join
 test2 2
on
 1.id=2.id collate Chinese_PRC_CI_AS
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>将服务器控件在后台生成html</title><link>https://fwhyy.com/2008/05/generate-html-server-controls-in-the-background/</link><pubDate>Wed, 28 May 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/05/generate-html-server-controls-in-the-background/</guid><description>&lt;p&gt;这个方法很有用，在做一些Ajax应用的时候，可以在后台将gridview 生成hmtl后回传到客户端，可以实现分页的功能。&lt;/p&gt;</description></item><item><title>开发总结—Javascript篇</title><link>https://fwhyy.com/2008/05/development-summary-javascript/</link><pubDate>Sun, 25 May 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/05/development-summary-javascript/</guid><description>&lt;p&gt;本文是我在平时工作中所遇到的javascript方面的一些知识总结，主要针对在asp.net中使用脚本。&lt;/p&gt;</description></item><item><title>Sybase.PowerDesiner12.0 下载 破解 汉化</title><link>https://fwhyy.com/2008/05/sybase-powerdesiner12-0-download/</link><pubDate>Sun, 11 May 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/05/sybase-powerdesiner12-0-download/</guid><description>&lt;h2 id="powerdesiner12-下载"&gt;PowerDesiner12 下载：&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.namipan.com/d/2687db90a67c150079bc1375ca2bb97a3f154e4add52000b"&gt;http://www.namipan.com/d/2687db90a67c150079bc1375ca2bb97a3f154e4add52000b&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="汉化补丁下载"&gt;汉化补丁下载：&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://download.csdn.net/source/298116"&gt;http://download.csdn.net/source/298116&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.namipan.com/d/SYBASE%20PowerDesigner%2012%20%e6%b1%89%e5%8c%96%e8%a1%a5%e4%b8%81%20.exe/20e073a65b965e5ac125f806da04da8bccc4623498d20600"&gt;http://www.namipan.com/d/SYBASE%20PowerDesigner%2012%20%e6%b1%89%e5%8c%96%e8%a1%a5%e4%b8%81%20.exe/20e073a65b965e5ac125f806da04da8bccc4623498d20600&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="破解下載"&gt;破解下載：&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.namipan.com/d/powerdesigner12.0%e7%89%88%e7%a0%b4%e8%a7%a3%e6%96%b9%e6%b3%95.txt/d4426b20c60d5e81439e5716f8239e6fbf2e43218c000000"&gt;http://www.namipan.com/d/powerdesigner12.0%e7%89%88%e7%a0%b4%e8%a7%a3%e6%96%b9%e6%b3%95.txt/d4426b20c60d5e81439e5716f8239e6fbf2e43218c000000&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Asp.Net中 %= 与%# 的区别</title><link>https://fwhyy.com/2008/04/the-difference-between-the-and-aspnet/</link><pubDate>Thu, 03 Apr 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/04/the-difference-between-the-and-aspnet/</guid><description>&lt;p&gt;&amp;lt;%= “oec2003” % &amp;gt; 相当于：Response.Write(“oec2003”);
&amp;lt;%# “oec2003” % &amp;gt; 相当于给变量赋值了oec2003&lt;/p&gt;
&lt;p&gt;在gridview中将一个绑定列转换成模板列时会看到有如下代码：&lt;/p&gt;</description></item><item><title>Sql中分隔字串–&gt;查询–&gt;组合字串</title><link>https://fwhyy.com/2008/03/separate-strings-in-sql/</link><pubDate>Tue, 18 Mar 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/03/separate-strings-in-sql/</guid><description>&lt;p&gt;最近在工作遇到一个数据库查询的问题，大概如下:表Table1中有字段No和Title，每一个No对应一个Title，表Table2中有NoAll字段，NoAll字段的value是No的组合，以逗号隔开，如”111,222,333″，现在要查询Table2，根据NoAll将其中的每一个No所对应的Title查询出来也以逗号分隔显示，如：”oec2003,oec2004,oec2004″。表定义如下：&lt;/p&gt;</description></item><item><title>C#3.0学习(3)—匿名类型</title><link>https://fwhyy.com/2008/03/learning-csharp-3-0-3-anonymous-types/</link><pubDate>Sun, 09 Mar 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/03/learning-csharp-3-0-3-anonymous-types/</guid><description>&lt;p&gt;匿名类型是在初始化的时候根据初始化列表自动产生类型的一种机制，利用对象初始化器来创建匿名对象的对象。如:&lt;/p&gt;</description></item><item><title>window.print()实现局部打印</title><link>https://fwhyy.com/2008/03/window-print-implementation-local-print/</link><pubDate>Thu, 06 Mar 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/03/window-print-implementation-local-print/</guid><description>&lt;p&gt;window.print() 实际上，是浏览器打印功能菜单的一种程序调用。与点击打印功能菜单一样，不能精确分页，不能设置纸型，套打的问题更加无从谈起，只不过，可以让用户不用去点菜单，直接点击网页中的一个按钮，或一个链接里面调用罢了。事实上，很多用户都是采用这种方式打印，但是这种方式最致命的缺点是不能设置打印参数，比如纸型，页边距，选择打印机等等。&lt;/p&gt;</description></item><item><title>C#3.0学习(2)—对象集合初始化器</title><link>https://fwhyy.com/2008/02/learning-c-3-0-2-object-collection-initializer/</link><pubDate>Mon, 25 Feb 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/02/learning-c-3-0-2-object-collection-initializer/</guid><description>&lt;p&gt;创建一个对象时可以包含一个对象初始化器或集合初始化器，用于初始化所创建对象的成员或新创建的集合的元素。使用初始化器可以让我们的代码变得更简洁。&lt;/p&gt;</description></item><item><title>C#3.0学习(1)—隐含类型局部变量和扩展方法</title><link>https://fwhyy.com/2008/02/learning-csharp-3-0-1-implied-type-of-local-variables-and-extension-methods/</link><pubDate>Fri, 22 Feb 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/02/learning-csharp-3-0-1-implied-type-of-local-variables-and-extension-methods/</guid><description>&lt;h2 id="隐含类型局部变量"&gt;隐含类型局部变量&lt;/h2&gt;
&lt;p&gt;隐含类型的局部变量是用var关键字来声明的，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;var i = 123;
var h=123.123;
var s = “oec2003&amp;#34;;
var intArr = new[] {1,2,3,4} ;
var a = new[] { 1, 10, 100, 1000 };
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;乍一看有点像javascript中的声明方式，虽然关键字一样但是有着本质区别。&lt;/p&gt;
&lt;p&gt;在c#3.0中用var关键字声明的变量被赋值后，在编译时编译器会根据变量值的类型自动推断出变量的类型。所以仍然是强类型，这点和object不同。其实var 关键字并不是一个具体的类型，只是起到了一个占位符的作用，编译后将替换成相应的类型。要注意的一点是用var声明的变量一定要赋初始值，否则会出现编译错误，因为如果不赋值就无法根据值来推断变量的类型。&lt;/p&gt;
&lt;p&gt;var只能声明局部变量，而且可以在foreach中使用，如：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;var nums=new []{1,2,3,4,5};
foreach(var i in nums)
{

}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="扩展方法"&gt;扩展方法&lt;/h2&gt;
&lt;p&gt;这是个非常有用的特性，扩展方法允许我们在不改变源码的情况下添加现有类型中的实例方法。扩展方法所在的类必须为静态类。如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public static class oec2003Extensions
{
 public static bool IsValidEmail(this String s)
 {
 Regex regex = new Regex(@&amp;#34;^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$&amp;#34;);
 return regex.IsMatch(s);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的IsValidEmail静态方法在静态类oec2003Extensions类中，这个类可以在任何的名称空间下，在要用的地方引用名称空间就行。IsValidEmail方法的作用是用来验证电子邮件。方法中有三个参数：this String s 。this只是一个编译上的要求，作为一个提示来告诉编译器此方法有可能作为扩展方法来使用；String就是我们需要扩展的类型；s则为要验证邮件的内容。下面来看看怎样来使用此扩展方法。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;protected void Button2_Click(object sender, EventArgs e)
{
 if (this.TextBox1.Text.Trim().IsValidEmail())
 {
 Response.Write(&amp;#34;email is right&amp;#34;);
 }
 else
 {
 Response.Write(&amp;#34;email is error&amp;#34;);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;是不是很神奇，在string类型中就多了一个刚才添加的IsValidEmail方法，可以直接调用，用来实现邮件地址的验证。&lt;/p&gt;</description></item><item><title>动态添加GridView行</title><link>https://fwhyy.com/2008/02/dynamically-add-tow-to-gridview/</link><pubDate>Fri, 15 Feb 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/02/dynamically-add-tow-to-gridview/</guid><description>&lt;h2 id="c代码"&gt;C#代码:&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;span class="lnt"&gt;50
&lt;/span&gt;&lt;span class="lnt"&gt;51
&lt;/span&gt;&lt;span class="lnt"&gt;52
&lt;/span&gt;&lt;span class="lnt"&gt;53
&lt;/span&gt;&lt;span class="lnt"&gt;54
&lt;/span&gt;&lt;span class="lnt"&gt;55
&lt;/span&gt;&lt;span class="lnt"&gt;56
&lt;/span&gt;&lt;span class="lnt"&gt;57
&lt;/span&gt;&lt;span class="lnt"&gt;58
&lt;/span&gt;&lt;span class="lnt"&gt;59
&lt;/span&gt;&lt;span class="lnt"&gt;60
&lt;/span&gt;&lt;span class="lnt"&gt;61
&lt;/span&gt;&lt;span class="lnt"&gt;62
&lt;/span&gt;&lt;span class="lnt"&gt;63
&lt;/span&gt;&lt;span class="lnt"&gt;64
&lt;/span&gt;&lt;span class="lnt"&gt;65
&lt;/span&gt;&lt;span class="lnt"&gt;66
&lt;/span&gt;&lt;span class="lnt"&gt;67
&lt;/span&gt;&lt;span class="lnt"&gt;68
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c#" data-lang="c#"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Configuration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Web&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Web.Security&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Web.UI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Web.UI.WebControls&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Web.UI.WebControls.WebParts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Web.UI.HtmlControls&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Data.SqlClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_Default&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Web&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Page&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Page_Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsPostBack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;BindGrid&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;DataTable&lt;/span&gt; &lt;span class="n"&gt;ReadGridView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;DataTable&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DataTable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;DataRow&lt;/span&gt; &lt;span class="n"&gt;dr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DataColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ProductID&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DataColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ProductName&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DataColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;CategoryID&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GridView1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dr&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewRow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GridView1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Cells&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GridView1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Cells&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GridView1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Cells&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Button1_Click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;DataTable&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ReadGridView&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;//this.GridView1.DataSource = dt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;//this.GridView1.DataBind();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;DataRow&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewRow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ItemArray&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oec2003&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oec2003&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oec2003&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InsertAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AcceptChanges&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GridView1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataSource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GridView1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataBind&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;BindGrid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConfigurationManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConnectionStrings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;NorthwindConnectionString&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SqlConnection&lt;/span&gt; &lt;span class="n"&gt;con&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;SqlConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SqlCommand&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;SqlCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;SELECT top 1 [ProductID], [ProductName], [CategoryID] FROM [Products]&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;con&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SqlDataAdapter&lt;/span&gt; &lt;span class="n"&gt;sda&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;SqlDataAdapter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;DataSet&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DataSet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GridView1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataSource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tables&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;DefaultView&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GridView1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataBind&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="html代码"&gt;Html代码&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%@ Page Language=&amp;#34;C#&amp;#34; AutoEventWireup=&amp;#34;true&amp;#34; CodeFile=&amp;#34;Default.aspx.cs&amp;#34; Inherits=&amp;#34;_Default&amp;#34; %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html PUBLIC &amp;#34;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;#34; 、
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt; &amp;#34;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;#34;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http://www.w3.org/1999/xhtml&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Head1&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;runat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;server&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;无标题页&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;form2&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;runat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;server&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;asp:Button&lt;/span&gt; &lt;span class="na"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Button1&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;runat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;server&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;OnClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Button1_Click&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Button&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;asp:GridView&lt;/span&gt; &lt;span class="na"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;GridView2&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;runat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;server&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;AutoGenerateColumns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;DataKeyNames&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ProductID&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;asp:BoundField&lt;/span&gt; &lt;span class="na"&gt;DataField&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ProductID&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;HeaderText&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ProductID&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;InsertVisible&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;False&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;ReadOnly&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;True&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;SortExpression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ProductID&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;asp:BoundField&lt;/span&gt; &lt;span class="na"&gt;DataField&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ProductName&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;HeaderText&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ProductName&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;SortExpression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ProductName&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;asp:BoundField&lt;/span&gt; &lt;span class="na"&gt;DataField&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;CategoryID&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;HeaderText&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;CategoryID&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;SortExpression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;CategoryID&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;asp:GridView&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="数据库连接字串"&gt;数据库连接字串&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;connectionStrings&amp;gt;
 &amp;lt;add name=&amp;#34;NorthwindConnectionString&amp;#34;
 connectionString=&amp;#34;Data Source=FENGWEI;Initial Catalog=Northwind;User ID=sa;Password=1234&amp;#34;
 providerName=&amp;#34;System.Data.SqlClient&amp;#34;/&amp;gt;
&amp;lt;/connectionStrings&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://files.cnblogs.com/oec2003/AddRow.rar"&gt;AddRow.rar&lt;/a&gt;&lt;/p&gt;</description></item><item><title>解决AJAX中使用UpdatePanel后再用Response.Write();无法弹出对话框问题</title><link>https://fwhyy.com/2008/01/updatepanel-issues/</link><pubDate>Sat, 19 Jan 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/01/updatepanel-issues/</guid><description>&lt;p&gt;在AJAX支持的网站中使用想使用Response.Wrie(‘’); 或 Page. RegisterStartupScript (); 弹出一些提示对话框，没有效果。有如下三种解决方法：&lt;/p&gt;</description></item><item><title>Html细线表格的实现</title><link>https://fwhyy.com/2008/01/the-realization-of-the-html-form-thin-lines/</link><pubDate>Thu, 10 Jan 2008 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2008/01/the-realization-of-the-html-form-thin-lines/</guid><description>&lt;p&gt;在网页制作中，我们常常会使用到表格，表格使得需要表达的信息更清楚，明了。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;table border=&amp;#34;1&amp;#34; cellspacing=&amp;#34;0&amp;#34; bordercolor=&amp;#34;#000000&amp;#34; width = &amp;#34;80%&amp;#34;&amp;gt;
 &amp;lt;tr&amp;gt;
 &amp;lt;td&amp;gt;1.1&amp;lt;/td&amp;gt;
 &amp;lt;td&amp;gt;1.2&amp;lt;/td&amp;gt;
 &amp;lt;/tr&amp;gt;
 &amp;lt;tr&amp;gt;
 &amp;lt;td&amp;gt;2.1&amp;lt;/td&amp;gt;
 &amp;lt;td&amp;gt;2.2&amp;lt;/td&amp;gt;
 &amp;lt;/tr&amp;gt;
&amp;lt;table&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这段代码定义了border = 1pix的表格，但实际上表格的实际边框宽度为2pix, 这是因为表格边框由：表格外边框和单元格边框两部分构成。那么如何定义一个细线表格(实际边宽为1pix) 呢？&lt;/p&gt;
&lt;h3 id="使用-cellspacing和背景色技术"&gt;使用 cellspacing和背景色技术:&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;table border=&amp;#34;0&amp;#34; cellspacing=&amp;#34;1&amp;#34; bgcolor=&amp;#34;#000000&amp;#34; width = &amp;#34;80%&amp;#34;&amp;gt;
 &amp;lt;tr bgcolor=&amp;#34;#ffffff&amp;#34;&amp;gt;
 &amp;lt;td&amp;gt;1.1&amp;lt;/td&amp;gt;
 &amp;lt;td&amp;gt;1.2&amp;lt;/td&amp;gt;
 &amp;lt;/tr&amp;gt;
 &amp;lt;tr bgcolor=&amp;#34;#ffffff&amp;#34;&amp;gt;
 &amp;lt;td&amp;gt;2.1&amp;lt;/td&amp;gt;
 &amp;lt;td&amp;gt;2.2&amp;lt;/td&amp;gt;
 &amp;lt;/tr&amp;gt;
&amp;lt;table&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="使用border-collapse属性"&gt;使用border-collapse属性:&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;table border=&amp;#34;1&amp;#34; cellspacing=&amp;#34;0&amp;#34; bordercolor=&amp;#34;#000000&amp;#34; width = &amp;#34;80%&amp;#34;
 style=&amp;#34;border-collapse:collapse;&amp;#34;&amp;gt;
 &amp;lt;tr&amp;gt;
 &amp;lt;td&amp;gt;1.1&amp;lt;/td&amp;gt;
 &amp;lt;td&amp;gt;1.2&amp;lt;/td&amp;gt;
 &amp;lt;/tr&amp;gt;
 &amp;lt;tr&amp;gt;
 &amp;lt;td&amp;gt;2.1&amp;lt;/td&amp;gt;
 &amp;lt;td&amp;gt;2.2&amp;lt;/td&amp;gt;
 &amp;lt;/tr&amp;gt;
&amp;lt;table&amp;gt;
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>类型“GridView”的控件 必须放在具有 runat=server 的窗体标记内 错误的解决方法</title><link>https://fwhyy.com/2007/12/type-of-the-gridview-controls-within-the-form-tag-must-be-placed-with-runat-equal-server-error-solution/</link><pubDate>Sun, 16 Dec 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/12/type-of-the-gridview-controls-within-the-form-tag-must-be-placed-with-runat-equal-server-error-solution/</guid><description>&lt;h2 id="错误提示"&gt;错误提示:&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;类型“GridView”的控件 必须放在具有 runat=server 的窗体标记内&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="解决方法"&gt;解决方法:&lt;/h2&gt;
&lt;p&gt;在后台文件中重载VerifyRenderingInServerForm方法,如:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public override void VerifyRenderingInServerForm(Control control)
{
 //base.VerifyRenderingInServerForm(control);
}
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>在visual studio中删除最近打开的项目和文件记录的方法</title><link>https://fwhyy.com/2007/12/delete-recently-opened-in-visual-studio-project-and-file-records/</link><pubDate>Wed, 05 Dec 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/12/delete-recently-opened-in-visual-studio-project-and-file-records/</guid><description>&lt;p&gt;在打开visual studio时有一个最近打开的项目列表，但是当我们将某个项目在本地磁盘上删除后，那个项目列表依然存在，下面的方法可以让删除的项目在列表中不出现。&lt;/p&gt;</description></item><item><title>解决sqlserver2005数据库sa登录问题</title><link>https://fwhyy.com/2007/12/solve-the-problem-of-sqlserver2005-database-sa-login/</link><pubDate>Sun, 02 Dec 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/12/solve-the-problem-of-sqlserver2005-database-sa-login/</guid><description>&lt;p&gt;如果安装sql server 2005的时候，设置的身份验证模式为”windows”(默认), 安装完成后, 再设置为”sql server和windows”的身份验证模式, 则sa用户是被禁用的。必须启用它。&lt;/p&gt;</description></item><item><title>几个不同类型无刷新联动例子</title><link>https://fwhyy.com/2007/11/several-different-types-without-refresh-linkage-example/</link><pubDate>Fri, 30 Nov 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/11/several-different-types-without-refresh-linkage-example/</guid><description>&lt;h2 id="iframe实现无刷新联动"&gt;Iframe实现无刷新联动&lt;/h2&gt;
&lt;p&gt;iframe的无刷新其实是局部刷新，状态栏的滚动条还是会滚动，只是页面不会闪烁，这是一种比较老的技术了，在处理的数据两大的时候会比较慢，在本例中需要两个页面：oec2003index.aspx和oec2003frame.asapx,oec2003index.aspx用来显示界面，其中有一个iframe标记，指向oec2003frame.aspx页用来显示结果&lt;/p&gt;</description></item><item><title>“无法在web服务器上启动调试,不具备调试此程序的权限” 问题解决</title><link>https://fwhyy.com/2007/11/unable-to-start-debugging-on-the-web-server-do-not-have-permission-to-debug-the-program-problem-solving/</link><pubDate>Wed, 28 Nov 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/11/unable-to-start-debugging-on-the-web-server-do-not-have-permission-to-debug-the-program-problem-solving/</guid><description>&lt;p&gt;最近维护以前用03做的一个项目,又重新将03装上了，很久都没有用03了,装上后打开项目没有问题,但按F5运行却出现下面错误&lt;/p&gt;</description></item><item><title>C#和Javascript交互</title><link>https://fwhyy.com/2007/11/csharp-and-javascript-interaction/</link><pubDate>Fri, 23 Nov 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/11/csharp-and-javascript-interaction/</guid><description>&lt;p&gt;在asp.net开发中，经常会用到后台和前台的交互，就此总结了一点c#和javascript相互操作的方法。&lt;/p&gt;</description></item><item><title>GridView中实现CheckBox的全选</title><link>https://fwhyy.com/2007/11/to-realize-the-checkbox-selection-in-the-gridview/</link><pubDate>Fri, 09 Nov 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/11/to-realize-the-checkbox-selection-in-the-gridview/</guid><description>&lt;h2 id="用服务器端的方法"&gt;用服务器端的方法&lt;/h2&gt;
&lt;p&gt;在页面上放一个gridview控件，配置好数据源，编辑列，添加一个模版列，再编辑模版，放入一个checkbox控件。代码如下：&lt;/p&gt;</description></item><item><title>Asp.Net Ajax—Calendar控件使用</title><link>https://fwhyy.com/2007/11/aspnet-ajax-calendar-control/</link><pubDate>Mon, 05 Nov 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/11/aspnet-ajax-calendar-control/</guid><description>&lt;h2 id="简介"&gt;简介&lt;/h2&gt;
&lt;p&gt;Calendar控件是一个很简单的控件，主要用来在页面中提供日历的选择，其实现在已经有很多用javascript写的&lt;a href="http://blog.csdn.net/21aspnet/archive/2007/05/14/1607712.aspx"&gt;日历控件&lt;/a&gt;，但是Canlendar日历控件能够让我们更快速地来实现这种效果，只需要进行一些简单的设置即可。&lt;/p&gt;</description></item><item><title>存储过程生成流水号</title><link>https://fwhyy.com/2007/10/stored-procedure-to-generate-a-serial-number/</link><pubDate>Wed, 31 Oct 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/10/stored-procedure-to-generate-a-serial-number/</guid><description>&lt;h2 id="首先在数据库中创建一个存放流水号的表"&gt;首先在数据库中创建一个存放流水号的表&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;CREATE TABLE [dbo].[NumSeq] (
 [Cate] [varchar] (2) NOT NULL ,
 [DateNo] [varchar] (4) NOT NULL ,
 [Seq] [int] NULL ,
 [CrTime] [datetime] NOT NULL
)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码中，Cate 字段为流水号的头，可以在下面的存储过程中用参数的方式传入，我的定义是2个字符，这个可以根据具体需要更改&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DateNo 字段为获取日期信息&lt;/li&gt;
&lt;li&gt;Seq 字段为流水号，但最终生成的流水号是这三个字段的相加&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="创建存储过程"&gt;创建存储过程&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;CREATE PROC dpPMT_SGetMaintainSeq
@MaintainCate VARCHAR(2)

AS
--***********************累加编号*************************************************
DECLARE @MaintainNo VARCHAR(12)
IF NOT EXISTS(SELECT
 *
 FROM
 NumSeq
 WHERE
 Cate=@MaintainCate AND DATEDIFF(DAY,CrTime,GETDATE())=0)
 BEGIN
 INSERT INTO
 NumSeq(Cate,DateNo,Seq)
 values(@MaintainCate,RIGHT(CONVERT(VARCHAR(4),YEAR(GETDATE())),2)+
 REPLICATE(&amp;#39;0&amp;#39;,2-LEN(MONTH(GETDATE())))+CONVERT(VARCHAR(2),MONTH(GETDATE())),0)

 END
ELSE
 BEGIN
 UPDATE
 NumSeq
 SET
 Seq=Seq+1
 WHERE
 Cate=@MaintainCate AND DateNo=RIGHT(CONVERT(VARCHAR(4),YEAR(GETDATE())),2)+
 REPLICATE(&amp;#39;0&amp;#39;,2-LEN(MONTH(GETDATE())))+CONVERT(VARCHAR(2),MONTH(GETDATE()))
 END

--************************组合编号***************************************************************
SELECT
 @MaintainNo=Cate+DateNo+REPLICATE(&amp;#39;0&amp;#39;,6-LEN(Seq))+CONVERT(VARCHAR(6),Seq)
FROM
 NumSeq
WHERE
 Cate=@MaintainCate AND DateNo=RIGHT(CONVERT(VARCHAR(4),YEAR(GETDATE())),2)+
 REPLICATE(&amp;#39;0&amp;#39;,2-LEN(MONTH(GETDATE())))+CONVERT(VARCHAR(2),MONTH(GETDATE()))

SELECT @MaintainNo
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这个存储过程最终输出的结果如：AA071031000001 前面两位是传入的参数，中间四位是年份的后两位和月，最后的六位为6位数字的流水号。您也可以修改上面的存储过程来生成符合您要求的流水号&lt;/p&gt;</description></item><item><title>Asp.Net Ajax-PopupControl控件使用</title><link>https://fwhyy.com/2007/09/asp-net-ajax-popupcontrol/</link><pubDate>Wed, 19 Sep 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/09/asp-net-ajax-popupcontrol/</guid><description>&lt;h2 id="简介"&gt;简介&lt;/h2&gt;
&lt;p&gt;Popupcontrol可以弹出任意类型的控件，不管是在服务器控件还是html控件。就是在某控件获取焦点时弹出另外一个控件，进行一些操作后，隐藏弹出的控件。&lt;/p&gt;</description></item><item><title>对设计模式的一点理解</title><link>https://fwhyy.com/2007/09/a-little-understanding-of-design-patterns/</link><pubDate>Sat, 08 Sep 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/09/a-little-understanding-of-design-patterns/</guid><description>&lt;p&gt;说起设计模式，不得不提的是GoF23种设计模式，这些设计模式是在历史性的一本经典著作《设计模式：可复用面向对象软件的基础》被描述的，这本书的四位作者并称为Gang of Four(GoF) 。由于这本书极具影响力，所以我们通常所说的设计模式就隐含地表示为“面向对象设计模式”，但这并不意味着“设计模式”就等同于“面向对象设计模式”。&lt;/p&gt;</description></item><item><title>Asp.Net Ajax-HoverMenu控件使用</title><link>https://fwhyy.com/2007/09/asp-net-ajax-hovermenu/</link><pubDate>Thu, 06 Sep 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/09/asp-net-ajax-hovermenu/</guid><description>&lt;h2 id="简介"&gt;简介&lt;/h2&gt;
&lt;p&gt;通过名字我们可以看出这是一个菜单控件，当鼠标移动到指定的位置时，在不影响其他的元素的情况下出现一个菜单，并允许用户进行一些操作。&lt;/p&gt;</description></item><item><title>Asp.Net Ajax—ValidatorCallout控件使用</title><link>https://fwhyy.com/2007/09/asp-net-ajax-validatorcallout/</link><pubDate>Thu, 06 Sep 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/09/asp-net-ajax-validatorcallout/</guid><description>&lt;h2 id="简介"&gt;简介&lt;/h2&gt;
&lt;p&gt;ValidatorCallout控件是一个用来绑定验证控件的提示控件,让验证的信息的显示可以更加地直观. 如下&lt;/p&gt;</description></item><item><title>Asp.Net Ajax-Passwordstrength控件使用</title><link>https://fwhyy.com/2007/08/asp-net-ajax-passwordstrength/</link><pubDate>Sat, 25 Aug 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/08/asp-net-ajax-passwordstrength/</guid><description>&lt;h2 id="简介"&gt;简介&lt;/h2&gt;
&lt;p&gt;PasswordStrength控件是用来提示用户输入密码的情况,用户在密码框中输入密码时,在文本框的后面会有一个提示,显示密码的强度,这种提示有两种方式:文本和进度条,提示信息的位置也可以由我们来自己设置,样式可以写CSS来定义。当密码框失去焦点时提示信息会自动消失。下面就来看看该控件的重要属性吧。&lt;/p&gt;</description></item><item><title>Asp.Net Ajax—TextBoxWateramrk</title><link>https://fwhyy.com/2007/08/asp-net-ajax-textboxwateramrk/</link><pubDate>Thu, 23 Aug 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/08/asp-net-ajax-textboxwateramrk/</guid><description>&lt;h2 id="简介"&gt;简介&lt;/h2&gt;
&lt;p&gt;TextBoxWatermark控件是一个用于TextBox的水印控件,就是在文本框输入文字之前,文本框中有一些提示性的文字,并可以自定义css控制它的样式,实际用处我感觉不是很大,但给用户带来了操作上的方便,也有很好的视觉效果.&lt;/p&gt;</description></item><item><title>Asp.Net Ajax—FilteredTextBox控件使用</title><link>https://fwhyy.com/2007/08/asp-net-ajax-filteredtextbox/</link><pubDate>Tue, 21 Aug 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/08/asp-net-ajax-filteredtextbox/</guid><description>&lt;h2 id="简介"&gt;简介&lt;/h2&gt;
&lt;p&gt;FilterTextBox控件是一种文本框的过滤控件，可以阻止用户进行不准确的输入，相比较vs里提供的验证控件显得更为严格，验证控件是在用户输入了不准确的输入后，给出相应的提示，而现在要介绍的FilterTextBox都不给用户输入错误数据的机会。&lt;/p&gt;</description></item><item><title>Asp.Net Ajax —AutoComplete控件使用</title><link>https://fwhyy.com/2007/08/asp-net-ajax-autocomplete/</link><pubDate>Sat, 18 Aug 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/08/asp-net-ajax-autocomplete/</guid><description>&lt;p&gt;以前见到google和迅雷等网站在搜索文本框中输入文字后能自动提示,感觉这种功能很炫也很实用.现在在学习asp.net ajax 发现AjaxControlToolKit工具包中的AutoComplete控件就能实现这种功能,而且非常简单.&lt;/p&gt;</description></item><item><title>DotNet 3.0 框架介绍</title><link>https://fwhyy.com/2007/08/dotnet-3-0-framework-introduce/</link><pubDate>Fri, 10 Aug 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/08/dotnet-3-0-framework-introduce/</guid><description>&lt;p&gt;微软.NET的最新版本，.NET Framework 3.0，为开发下一代业务解决方案软件系统开启了新的可能。它的设计目标是：提高生产力，降低基础设施复杂性，提供一个一致的元系统，让企业级服务、工作流解决方案和用户体验软件系统的开发更容易。&lt;/p&gt;</description></item><item><title>AjaxControlToolkit安装&amp;下载</title><link>https://fwhyy.com/2007/08/ajaxcontroltoolkit-installing/</link><pubDate>Fri, 03 Aug 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/08/ajaxcontroltoolkit-installing/</guid><description>&lt;p&gt;以下是收集关于AjaxControlToolkit安装的一篇文章，感谢原作者&lt;/p&gt;</description></item><item><title>解决Asp.Net Ajax UpdatePanel 乱码问题</title><link>https://fwhyy.com/2007/07/solve-the-problem-of-the-aspnet-ajax-updatepanel-garbled/</link><pubDate>Wed, 25 Jul 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/07/solve-the-problem-of-the-aspnet-ajax-updatepanel-garbled/</guid><description>&lt;p&gt;UpdatePanel中当ContentComplate里面存在TextBox的时候会出现中文乱码&lt;/p&gt;
&lt;p&gt;一般存在这样两个解决方案：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在web.config里面增加下面代码。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;globalization fileEncoding=&amp;#34;utf-8&amp;#34; requestEncoding=&amp;#34;utf-8&amp;#34;
 responseEncoding=&amp;#34;utf-8&amp;#34; culture=&amp;#34;zh-CN&amp;#34;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Ajax,其实并不难</title><link>https://fwhyy.com/2007/07/ajax-actually-not-difficult/</link><pubDate>Mon, 23 Jul 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/07/ajax-actually-not-difficult/</guid><description>&lt;p&gt;Ajax是一种应用技术的缩写，全称为&lt;code&gt;Asynchronous Javascript And XML &lt;/code&gt;,这种技术的使用可以更好地提高用户的体验。组成这种技术的主要因素有：&lt;code&gt;javascript&lt;/code&gt;语言，&lt;code&gt;css&lt;/code&gt;样式表，&lt;code&gt;XMLHttpRequest&lt;/code&gt;数据交换对象和&lt;code&gt;Dom&lt;/code&gt;对象。&lt;/p&gt;</description></item><item><title>.Net泛型编程简介</title><link>https://fwhyy.com/2007/05/net-generic-programming/</link><pubDate>Tue, 22 May 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/05/net-generic-programming/</guid><description>&lt;p&gt;.NET泛型编程已经离我们不远了，在微软最近随SQL Server Yukon Beta1发行的.NET Framework 1.2中就已经有了泛型的影子。虽然现在它还是问题多多，但是相信随着新版.NET Framework的正式发行（正式发行时的版本号会是2.0），这些问题会得到解决。因此我们也该为.NET泛型编程做些准备了。&lt;/p&gt;</description></item><item><title>常用的一些正则表达式</title><link>https://fwhyy.com/2007/05/commonly-used-some-regular-expressions/</link><pubDate>Tue, 08 May 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/05/commonly-used-some-regular-expressions/</guid><description>&lt;p&gt;正则表达式用于字符串处理、表单验证等场合，实用高效。但用到时总是不太把握，以致往往要查证一番。现将一些常用的表达式收集于此，以备不时之需。&lt;/p&gt;</description></item><item><title>实现鼠标悬停高亮显示—分别在gridview和datagrid中</title><link>https://fwhyy.com/2007/05/implement-mouseover-highlight-respectively-in-the-gridview-and-the-datagrid/</link><pubDate>Mon, 07 May 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/05/implement-mouseover-highlight-respectively-in-the-gridview-and-the-datagrid/</guid><description>&lt;p&gt;在datagrid中的ItemDataBound事件中写如下代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;private void DataGrid1_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
{
 if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
 {
 e.Item.Attributes.Add(&amp;#34;onmouseover&amp;#34;, &amp;#34;c=this.style.backgroundColor;this.style.backgroundColor=&amp;#39;#66CCFF&amp;#39;&amp;#34;);
 e.Item.Attributes.Add(&amp;#34;onmouseout&amp;#34;, &amp;#34;this.style.backgroundColor=c&amp;#34;);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在girdview中的RowDataBound事件中写下如下代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
 if (e.Row.RowType == DataControlRowType.DataRow)
 {
 e.Row.Attributes.Add(&amp;#34;onmouseover&amp;#34;, &amp;#34;currentcolor=this.style.backgroundColor;this.style.backgroundColor=&amp;#39;#6699ff&amp;#39;;&amp;#34;);
 e.Row.Attributes.Add(&amp;#34;onmouseout&amp;#34;, &amp;#34;this.style.backgroundColor=currentcolor;&amp;#34;);
 }
}
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Asp.Net中水晶报表的简单使用</title><link>https://fwhyy.com/2007/01/simple-to-use-aspnet-in-crystal-reports/</link><pubDate>Thu, 11 Jan 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/01/simple-to-use-aspnet-in-crystal-reports/</guid><description>&lt;p&gt;Crystal Reports是具有强大内容创建和集成功能的高效的报表技术，是第三方开发的报表工具，使用水晶报表我们可以更好地向用户展示数据。以前可以通过编程的方式将数据集中的数据进行处理后在windows应用程序或web应用程序中输出显示，但如果要做超出了基本格式化的一些工作如：求和、平均、多极汇总、制作图标等就会显得比较复杂，而水晶报表正好弥补了其中的不足。&lt;/p&gt;</description></item><item><title>Asp.Net中列表数据绑定控件浅析</title><link>https://fwhyy.com/2007/01/asp-net-lists-data-bound-controls/</link><pubDate>Wed, 03 Jan 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/01/asp-net-lists-data-bound-controls/</guid><description>&lt;p&gt;在Asp.Net中用来显示列表数据的控件有&lt;code&gt;Repeater&lt;/code&gt;，&lt;code&gt;DataList&lt;/code&gt;,&lt;code&gt;DataGrid&lt;/code&gt;三种.&lt;/p&gt;
&lt;p&gt;DataGrid的灵活性很强，内置了丰富的事件，提供分页，编辑，排序等一些特性，对表格的操作也是非常方便的，而且还有很多种的风格可选，由于自带了很多的功能和特性，所以开发速度很快，容易部署。但它的性能不是很高，每次的操作都会返回到服务器。主要用在对有排序、分页、编辑和多列的显示，而且对性能的要求不是很高，一般情况下数据源是一个DateSet。&lt;/p&gt;</description></item><item><title>Asp.Net中的一个小的性能测试</title><link>https://fwhyy.com/2007/01/a-small-performance-test-of-asp-net/</link><pubDate>Wed, 03 Jan 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/01/a-small-performance-test-of-asp-net/</guid><description>&lt;p&gt;大家都知道使用缓存可用大大提高asp.net应用程序的性能,那么究竟能提高多少性能呢?我做了一个小小的测试.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在vs2003中新建一个web应用程序,在页面上添加一个DataGrid控件，让DataGrid里显示NorthWind数据库中employees表的内容。我的做法是在vs2003的服务器资源管理器中建立一个连接到NorthWind数据库的连接，然后将其中的employees&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Asp.Net的性能问题</title><link>https://fwhyy.com/2006/12/asp-net-performance-issues/</link><pubDate>Sat, 23 Dec 2006 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2006/12/asp-net-performance-issues/</guid><description>&lt;p&gt;性能对于一个应用程序来说是一个很重要的问题，在web的开发中也是一样，相信没有人愿意在电脑屏幕前花8秒钟来等待一个也面的打开，这就是常说的在web上的8秒钟原则。对于一个应用程序的性能我们应该把它当作是应用程序的一项功能，在设计的时候就应该处理好性能的问题，而不应该在整个程序开发完了以后再来进行优化，因为这样会付出更多的代价。&lt;/p&gt;</description></item></channel></rss>