<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" 
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Thinking more...-.Net</title>
<link>http://blog.roodo.com/thinkingmore/archives/cat_82805.html</link>
<description>Just thinking more...&amp;nbsp;訂閱 RSS


_uacct = &quot;UA-97150-7&quot;;
urchinTracker();

google.load(&quot;jquery&quot;, &quot;1.2&quot;);

  
  
  
  
  
  
  
  
  </description>
<language>zh-tw</language>
<generator>Roodo Blog System</generator>
<copyright>All Rights Reserved</copyright>
<atom:link href="http://blog.roodo.com/thinkingmore/archives/cat_82805.xml" rel="self" type="application/rss+xml" />
<item>
	<title>列出 log4net 設定裡所有的 repository 跟 appender</title>
	<description><![CDATA[
	Debug 用的，主要是看自己的 log4net 設定對不對。


StringBuilder sb = new StringBuilder();
ILoggerRepository[] repos = LogManager.GetAllRepositories();
foreach( ILoggerRepository repo in repos )
{
	sb.AppendLine( "=====" );
	sb.AppendLine( string.Format( "{0} - configured={1}", repo.Name, repo.Configured.ToString() );
	sb.AppendLine( "Appenders:" );
	foreach( IAppender appender in repo.GetAppenders() )
	{
		sb.AppendLine( string.Format( "\t{0}", appender.Name ) );
	}
}
sb.AppendLine( "=====" );
Console.WriteLine( sb.ToString() );


	]]>
	</description>
	<content:encoded><![CDATA[
	Debug 用的，主要是看自己的 log4net 設定對不對。

<pre name="code" class="csharp">
StringBuilder sb = new StringBuilder();
ILoggerRepository[] repos = LogManager.GetAllRepositories();
foreach( ILoggerRepository repo in repos )
{
	sb.AppendLine( "=====" );
	sb.AppendLine( string.Format( "{0} - configured={1}", repo.Name, repo.Configured.ToString() );
	sb.AppendLine( "Appenders:" );
	foreach( IAppender appender in repo.GetAppenders() )
	{
		sb.AppendLine( string.Format( "\t{0}", appender.Name ) );
	}
}
sb.AppendLine( "=====" );
Console.WriteLine( sb.ToString() );
</pre>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/7119835.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/7119835.html</guid>
	<category>.Net</category>
	<pubDate>Fri, 05 Sep 2008 16:27:20 +0800</pubDate>
</item>
<item>
	<title>debuan/ubuntu nant-0.85 的 SMP bug</title>
	<description><![CDATA[
	最近在 Ubuntu 下用 NAnt 時，有 50% 的機率會遇到類似這樣的錯誤：The current runtime framework 'mono-2.0' is not correctly configured in the NAnt configuration file.
    Function call failed.
Expression: ${path::combine(prefix, 'lib/mono/1.0')}
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        Illegal characters in path
Parameter name: path1


找了好久，都不知道原因所在，因為有時候是正常執行的。去Google試了好幾個關鍵字，都找不到解。今天用 nant "Illegal characters in path" 去找，終於找到了：#483073 - nant: race condition on SMP systems - Debian Bug report logs
裡面提供的暫時解法是利用環境變數 MONO_NO_SMP，把 SMP 關掉，再執行即可。所以只要編輯 /usr/bin/nant，在 exec 之前加上 export MONO_NO_SMP=1 即可。

	]]>
	</description>
	<content:encoded><![CDATA[
	最近在 <a href="http://www.ubuntulinux.com">Ubuntu</a> 下用 <a href="http://nant.sourceforge.net">NAnt</a> 時，有 50% 的機率會遇到類似這樣的錯誤：<pre>The current runtime framework 'mono-2.0' is not correctly configured in the NAnt configuration file.
    Function call failed.
Expression: ${path::combine(prefix, 'lib/mono/1.0')}
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        Illegal characters in path
Parameter name: path1
</pre>

找了好久，都不知道原因所在，因為有時候是正常執行的。去<a href="http://www.google.com">Google</a>試了好幾個關鍵字，都找不到解。今天用 nant "Illegal characters in path" 去找，終於找到了：<a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=483073">#483073 - nant: race condition on SMP systems - Debian Bug report logs</a><br/>
裡面提供的暫時解法是利用環境變數 MONO_NO_SMP，把 SMP 關掉，再執行即可。所以只要編輯 /usr/bin/nant，在 exec 之前加上 export MONO_NO_SMP=1 即可。
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/6978141.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/6978141.html</guid>
	<category>.Net</category>
	<pubDate>Mon, 25 Aug 2008 14:53:25 +0800</pubDate>
</item>
<item>
	<title>最近用 MySql Connector/Net 的幾個心得</title>
	<description><![CDATA[
	連線字串加上 charset=utf8，如此一來，完全不用更改 MySQL 伺服器設定，只要確定建 database/table 時有指定 utf-8 編碼即可。SQL 參數在使用 @ 時，若碰到問題，不妨改用 ? 試試。我的確碰到這問題，它卡了我兩、三天，而且改用 ? 也解決了。忘了在哪兒看到，剛好有提到這點，真的是幸好我有看到...MySQL 有提供 MySqlHelper 類別，省掉寫 Helper 的麻煩...MySQLConnector/Net下載網站上沒有給 Linux 的版本，事實上，是通用的，你可以直接拿給Mono用，不需要作任何改動。

	]]>
	</description>
	<content:encoded><![CDATA[
	<ol><li>連線字串加上 charset=utf8，如此一來，完全不用更改 <a href="http://www.mysql.com/">MySQL</a> 伺服器設定，只要確定建 database/table 時有指定 utf-8 編碼即可。</li><li>SQL 參數在使用 @ 時，若碰到問題，不妨改用 ? 試試。我的確碰到這問題，它卡了我兩、三天，而且改用 ? 也解決了。忘了在哪兒看到，剛好有提到這點，真的是幸好我有看到...</li><li><a href="http://www.mysql.com/">MySQL</a> 有提供 MySqlHelper 類別，省掉寫 Helper 的麻煩...</li><li><a href="http://www.mysql.com/">MySQL</a><a href="http://dev.mysql.com/downloads/connector/net/">Connector/Net下載網站</a>上沒有給 Linux 的版本，事實上，是通用的，你可以直接拿給<a href="http://www.go-mono.com">Mono</a>用，不需要作任何改動。</li></ol><br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/6898775.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/6898775.html</guid>
	<category>.Net</category>
	<pubDate>Fri, 22 Aug 2008 09:51:23 +0800</pubDate>
</item>
<item>
	<title>.NET framework essential Chapter 7/8-ASP.Net/Windows form</title>
	<description><![CDATA[
	各自只有一個章節，不過作者很簡明扼要地把該介紹的東西都介紹了。

ASP.Net 除了講 HtmlControl、WebControl 以外，還介紹了 Directive、Session 設定等等。
Windows form 則是簡單的介紹如何開始、Layout 的配置，以及比較容易讓人混淆的 MDI Form。

這本書真的很不錯，講的都很基本，看完對 .NET 會有一定程度的了解，不至於在茫茫大海似的類別庫裡淹死。

	]]>
	</description>
	<content:encoded><![CDATA[
	各自只有一個章節，不過作者很簡明扼要地把該介紹的東西都介紹了。<br />
<br />
ASP.Net 除了講 HtmlControl、WebControl 以外，還介紹了 Directive、Session 設定等等。<br />
Windows form 則是簡單的介紹如何開始、Layout 的配置，以及比較容易讓人混淆的 MDI Form。<br />
<br />
這本書真的很不錯，講的都很基本，看完對 .NET 會有一定程度的了解，不至於在茫茫大海似的類別庫裡淹死。<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/6705987.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/6705987.html</guid>
	<category>.Net</category>
	<pubDate>Fri, 08 Aug 2008 09:51:55 +0800</pubDate>
</item>
<item>
	<title>App_Offline.htm</title>
	<description><![CDATA[
	今天 Trace Mono System.Web.HttpRuntime 時看到的，如果在你 ASP.Net 2.0 網站目錄下放置一個 app_offline.htm 時，不管你瀏覽什麼網頁，都只會看到 app_offline.htm 的內容。

詳情可以參考 ScottGu 大 的文章：App_Offline.htm

很鳥的是，.NET Documentation 裡完全沒提到這個。

	]]>
	</description>
	<content:encoded><![CDATA[
	今天 Trace <a href="http://www.mono-project.com">Mono</a> System.Web.HttpRuntime 時看到的，如果在你 ASP.Net 2.0 網站目錄下放置一個 app_offline.htm 時，不管你瀏覽什麼網頁，都只會看到 app_offline.htm 的內容。<br />
<br />
詳情可以參考 <a href="http://weblogs.asp.net/scottgu/default.aspx">ScottGu 大</a> 的文章：<a href="http://weblogs.asp.net/scottgu/archive/2005/10/06/426755.aspx">App_Offline.htm</a><br />
<br />
很鳥的是，.NET Documentation 裡完全沒提到這個。<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/6689919.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/6689919.html</guid>
	<category>.Net</category>
	<pubDate>Thu, 07 Aug 2008 14:57:14 +0800</pubDate>
</item>
<item>
	<title>Mono 與音訊、視訊</title>
	<description><![CDATA[
	mplayer 的 -input 可以指定 file，man 裡面說明了你可以給一個 FIFO 的檔案。
藉著這個，於是就可以寫程式來控制 mplayer 來播放影片或是音樂。
你可以參考致遠管理學院資工系專題研究計畫研究成果報告計畫： Linux C# 設計 ...

你還可以使用 GStreamer#，Mono team 的人已經幫你將 gstreamer 函式庫包裝為 GStreamer#，因此使用 GStreamer# 也可以進行播放影片和音樂，最好的例子是 Banshee。
不過這只適用於 Linux。

	]]>
	</description>
	<content:encoded><![CDATA[
	<a href="http://www.mplayerhq.hu/">mplayer</a> 的 -input 可以指定 file，man 裡面說明了你可以給一個 FIFO 的檔案。<br />
藉著這個，於是就可以寫程式來控制 <a href="http://www.mplayerhq.hu/">mplayer</a> 來播放影片或是音樂。<br />
你可以參考<a href="http://mail2.dwu.edu.tw/~ezliang/Project_Unix/Projetc_report_96A.pdf">致遠管理學院資工系專題研究計畫研究成果報告計畫： Linux C# 設計 ...</a><br />
<br />
你還可以使用 <a href="http://www.mono-project.com/Gstreamer">GStreamer#</a>，<a href="http://www.mono-project.com/">Mono</a> team 的人已經幫你將 <a href="http://www.gstreamer.org/">gstreamer</a> 函式庫包裝為 <a href="http://www.mono-project.com/Gstreamer">GStreamer#</a>，因此使用 <a href="http://www.mono-project.com/Gstreamer">GStreamer#</a> 也可以進行播放影片和音樂，最好的例子是 <a href="http://www.banshee-project.com/">Banshee</a>。<br />
不過這只適用於 Linux。<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/6658157.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/6658157.html</guid>
	<category>.Net</category>
	<pubDate>Tue, 05 Aug 2008 17:49:15 +0800</pubDate>
</item>
<item>
	<title>.NET framework essential Chapter 6-Web Services</title>
	<description><![CDATA[
	最前面是一堆有點誇張的介紹，不過在當時大家真的都以為 Web Services 很棒...
這一章介紹 Web Services 的觀念與實作，由於微軟是規格制定者，所以 .NET 對 Web Services 的支援不能少，下了很多功夫。
主角是 WebService 類別與 WebMethodAttribute，方法是繼承 WebService 類別，然後在要被呼叫的方法上，標上 WebMethod attribute。

以前以為 Web Services 的底層是 SOAP，所以只能用 SOAP，沒想到也可以用 GET/POST 的方式來呼叫，所以 javascript 也能輕易地呼叫 Web Services，然後解析回傳的 XML 即可。
Security 方面，以前也以為沒有 session，現在也知道可以用了。另外還介紹了兩種層級的保護，系統層級是利用 IIS 管理介面設定權限與 SSL 來達成，Application Level，則是利用 .NET 的 web.config 來達成。
SSL 對於 Web Service 來說，是個稍嫌沈重的負擔，所以他也建議使用 authentication token 的方式，也就是提供一個架構在 SSL 上，可以取得 authentication token 的方法，取得 token 之後，後續的呼叫都要帶入這個 token，以作為識別。
這樣的方式，在目前有提供 Open API 的網站上很常見。

	]]>
	</description>
	<content:encoded><![CDATA[
	最前面是一堆有點誇張的介紹，不過在當時大家真的都以為 Web Services 很棒...<br />
這一章介紹 Web Services 的觀念與實作，由於微軟是規格制定者，所以 .NET 對 Web Services 的支援不能少，下了很多功夫。<br />
主角是 WebService 類別與 WebMethodAttribute，方法是繼承 WebService 類別，然後在要被呼叫的方法上，標上 WebMethod attribute。<br />
<br />
以前以為 Web Services 的底層是 SOAP，所以只能用 SOAP，沒想到也可以用 GET/POST 的方式來呼叫，所以 javascript 也能輕易地呼叫 Web Services，然後解析回傳的 XML 即可。<br />
Security 方面，以前也以為沒有 session，現在也知道可以用了。另外還介紹了兩種層級的保護，系統層級是利用 IIS 管理介面設定權限與 SSL 來達成，Application Level，則是利用 .NET 的 web.config 來達成。<br />
SSL 對於 Web Service 來說，是個稍嫌沈重的負擔，所以他也建議使用 authentication token 的方式，也就是提供一個架構在 SSL 上，可以取得 authentication token 的方法，取得 token 之後，後續的呼叫都要帶入這個 token，以作為識別。<br />
這樣的方式，在目前有提供 Open API 的網站上很常見。<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/6638049.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/6638049.html</guid>
	<category>.Net</category>
	<pubDate>Fri, 01 Aug 2008 13:33:47 +0800</pubDate>
</item>
<item>
	<title>MonoDevelop on Windows</title>
	<description><![CDATA[
	Cygwin 要裝些什麼可以參考這篇：CodeProject 上的文章：Building Mono on Windows: the final battle.
不過 Mono 可以直接用官方提供的，不需要自己 build。

首先進 Cygwin shell，設定 PATH 與 PKG_CONFIG_PATH，讓 Cygwin 能找到 Mono：
export PATH=/cygdrive/c/Progra~1/Mono-1.9.1/bin:$PATH
export PKG_CONFIG_PATH=/usr/lib/pkgconfig/:/usr/local/lib/pkgconfig/:/cygdrive/c/Progra~1/Mono-1.9.1/lib/pkgconfig

再把 Mono 目錄下的 pkg-config 更名，因為這個版本的 pkg-config 太舊。

接著要 build Mono-Addin-0.3.1，這簡單，很快就 build 過了。(./configure && make && make install )

再來就麻煩了，1.0 無法 build，它會要求裝 monodoc, gtksourceview-sharp-2.0.0；monodoc 其實已經有了，但卻沒有給 pkg-config 用的 .pc 檔，所以補上一個自製的 monodoc.pc。接著，gtksourceview-sharp 則需要裝 gnome-sharp、gtk-sharp 與實體的 gtk+、gnome 函式庫，所以我放棄 1.0，改用 1.9。1.9 是比較順利了，順利的原因是，MonoDevelop team 本來就有打算要出 Windows 版本，只是能不能用還在未知之數。

在 build 的過程中，發現 gmcs 無法載入 Mono.Addin.Setup assembly 的問題，這是由於 gacutil 跟 Cygwin 相處的不太好，gacutil 收的 path separator 是反斜線 '\'，但 Cygwin 只能給 '/'，所以安裝 Mono.Addin 時，並沒有依照 Makefile 的指定，將 .dll 註冊到 gac 所以在編譯(make)、安裝(make install)後，你必須要手動將 .dll 註冊到 gac 裡：cd bin;find . -name '*.dll' -exec gacutil -i {} \;

接著，MonoDevelop 就 build 成功了。不過，MonoDevelop 還是不能執行 :-( MonoDevelop.Core.Gui.Services 這邊會丟出例外。

	]]>
	</description>
	<content:encoded><![CDATA[
	<a href="http://www.cygwin.com/">Cygwin</a> 要裝些什麼可以參考這篇：<a href="http://www.codeproject.com/KB/cross-platform/mono_on_windows.aspx">CodeProject 上的文章：Building Mono on Windows: the final battle.</a><br/>
不過 <a href="http://www.mono-project.com/Main_Page">Mono</a> 可以直接用官方提供的，不需要自己 build。<br/>
<br/>
首先進 <a href="http://www.cygwin.com/">Cygwin</a> shell，設定 PATH 與 PKG_CONFIG_PATH，讓 <a href="http://www.cygwin.com/">Cygwin</a> 能找到 <a href="http://www.mono-project.com/Main_Page">Mono</a>：
<pre>export PATH=/cygdrive/c/Progra~1/Mono-1.9.1/bin:$PATH
export PKG_CONFIG_PATH=/usr/lib/pkgconfig/:/usr/local/lib/pkgconfig/:/cygdrive/c/Progra~1/Mono-1.9.1/lib/pkgconfig</pre>
<br/>
再把 <a href="http://www.mono-project.com/Main_Page">Mono</a> 目錄下的 pkg-config 更名，因為這個版本的 pkg-config 太舊。<br/>
<br/>
接著要 build Mono-Addin-0.3.1，這簡單，很快就 build 過了。(./configure && make && make install )<br/>
<br/>
再來就麻煩了，1.0 無法 build，它會要求裝 monodoc, gtksourceview-sharp-2.0.0；monodoc 其實已經有了，但卻沒有給 pkg-config 用的 .pc 檔，所以補上一個自製的 monodoc.pc。接著，gtksourceview-sharp 則需要裝 gnome-sharp、gtk-sharp 與實體的 gtk+、gnome 函式庫，所以我放棄 1.0，改用 1.9。1.9 是比較順利了，順利的原因是，<a href="http://www.monodevelop.com/Main_Page">MonoDevelop</a> team 本來就有打算要出 Windows 版本，只是能不能用還在未知之數。<br/>
<br/>
在 build 的過程中，發現 gmcs 無法載入 Mono.Addin.Setup assembly 的問題，這是由於 gacutil 跟 <a href="http://www.cygwin.com/">Cygwin</a> 相處的不太好，gacutil 收的 path separator 是反斜線 '\'，但 <a href="http://www.cygwin.com/">Cygwin</a> 只能給 '/'，所以安裝 Mono.Addin 時，並沒有依照 Makefile 的指定，將 .dll 註冊到 gac 所以在編譯(make)、安裝(make install)後，你必須要手動將 .dll 註冊到 gac 裡：<pre>cd bin;find . -name '*.dll' -exec gacutil -i {} \;</pre>
<br/>
接著，<a href="http://www.monodevelop.com/Main_Page">MonoDevelop</a> 就 build 成功了。不過，<a href="http://www.monodevelop.com/Main_Page">MonoDevelop</a> 還是不能執行 :-( MonoDevelop.Core.Gui.Services 這邊會丟出例外。<br/>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/6634735.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/6634735.html</guid>
	<category>.Net</category>
	<pubDate>Thu, 31 Jul 2008 20:06:16 +0800</pubDate>
</item>
<item>
	<title>.NET framework essential Chapter 4</title>
	<description><![CDATA[
	Chapter 3 主要是講各種語言的介紹與互相操作，大致都已經知道，沒什麼要紀錄的。
接著記 Chapter 4 的一些東西。

只要在 .config 裡面使用 bindingRedirect，就可以重新導向相依的assembly到新版本的assembly。.config 裡的 attribute：runtime / assemblyBinding / dependentAssemblyRemoting object 的程式真的出乎意料地簡單，以前從沒研究過，有機會來試試效能，看看傳一堆物件或是 Dataset 的效能如何。有一個 Attribute 的簡單範例...支援 Transaction 的要件：繼承 ServicedComponent使用正確的 Transaction attribute接著就可用 System.EnterpriseServices.ContextUtil。此外最好也指定 ApplicationName、ApplicationActivation 等組件attribute。.NET 會在編譯時自動把組件加入 COM+ Service 裡，無須自己動手註冊。這邊還有 Object pooling、Role base、Message Queuing 的例子，很淺顯易懂。這部份在 Mono 裡都沒有被實作出來，主要是因為 COM+ 在 Linux 下沒有替代品的關係。

	]]>
	</description>
	<content:encoded><![CDATA[
	Chapter 3 主要是講各種語言的介紹與互相操作，大致都已經知道，沒什麼要紀錄的。<br />
接著記 Chapter 4 的一些東西。<br />
<br />
<ul><li>只要在 .config 裡面使用 bindingRedirect，就可以重新導向相依的assembly到新版本的assembly。.config 裡的 attribute：runtime / assemblyBinding / dependentAssembly</li><li>Remoting object 的程式真的出乎意料地簡單，以前從沒研究過，有機會來試試效能，看看傳一堆物件或是 Dataset 的效能如何。</li><li>有一個 Attribute 的簡單範例...</li><li>支援 Transaction 的要件：<ol><li>繼承 ServicedComponent</li><li>使用正確的 Transaction attribute</li></ol>接著就可用 System.EnterpriseServices.ContextUtil。此外最好也指定 ApplicationName、ApplicationActivation 等組件attribute。.NET 會在編譯時自動把組件加入 COM+ Service 裡，無須自己動手註冊。這邊還有 Object pooling、Role base、Message Queuing 的例子，很淺顯易懂。這部份在 Mono 裡都沒有被實作出來，主要是因為 COM+ 在 Linux 下沒有替代品的關係。</li></ul><br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/6298417.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/6298417.html</guid>
	<category>.Net</category>
	<pubDate>Thu, 03 Jul 2008 16:55:47 +0800</pubDate>
</item>
<item>
	<title>.NET essential 第二章 CLR 筆記</title>
	<description><![CDATA[
	主要是紀錄以前不知道或是看過沒深入了解的一些東西：Managed C++ 編譯出來的執行檔無法用mono執行，可能是因為 Native code 跟 IL code 放到一起的關係。從 stack-based 的 value type 轉成 heap-based 的 reference type 的過程稱作 boxing，反之稱作 unboxing。int i=1;
object obj = i; // boxing
int j = (int)obj; // unboxing
為了要讓各種語言能在 CLR 上執行，有 Common Language Specification 的 ECMA 標準 - Standard ECMA-335。NGen 可以預先將 IL code 轉為 Native executable code，省掉 JIT compiler 的工作(pre-JITting)，因此可以加速。mono裡似乎是用 mono -O=all --aot your-assembly 來替代的樣子。

	]]>
	</description>
	<content:encoded><![CDATA[
	主要是紀錄以前不知道或是看過沒深入了解的一些東西：<ol><li>Managed C++ 編譯出來的執行檔無法用<a href="http://www.mono-project.com">mono</a>執行，可能是因為 Native code 跟 IL code 放到一起的關係。</li><li>從 stack-based 的 value type 轉成 heap-based 的 reference type 的過程稱作 boxing，反之稱作 unboxing。<pre name="code" class="csharp">int i=1;
object obj = i; // boxing
int j = (int)obj; // unboxing
</pre></li><li>為了要讓各種語言能在 CLR 上執行，有 Common Language Specification 的 ECMA 標準 - <a href="http://www.ecma-international.org/publications/standards/Ecma-335.htm">Standard ECMA-335</a>。</li><li>NGen 可以預先將 IL code 轉為 Native executable code，省掉 JIT compiler 的工作(pre-JITting)，因此可以加速。<a href="http://www.mono-project.com">mono</a>裡似乎是用 <pre>mono -O=all --aot your-assembly</pre> 來替代的樣子。</li></ol>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/6217521.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/6217521.html</guid>
	<category>.Net</category>
	<pubDate>Mon, 23 Jun 2008 11:24:43 +0800</pubDate>
</item>
<item>
	<title>ILMerge</title>
	<description><![CDATA[
	這工具可以讓你把 .Net 不同語言編譯出來的 Assembly (組件)合併在一起。

官方網址：ILMerge

安裝以後，用法很簡單：
"c:\Program Files\Microsoft\ILMerge\ILMerge.exe" /t:library /out:[輸出檔名] /lib:[Assembly搜索路徑] [要合併的 Assembly 1] [要合併的 Assembly 2] ...

只想給客戶一個可執行檔，不想給一堆其他組件的時候，這樣作也行：
"c:\Program Files\Microsoft\ILMerge\ILMerge.exe" /t:[exe或winexe] /out:[輸出檔名] /lib:[Assembly搜索路徑] [執行檔] [要合併的 Assembly 1] [要合併的 Assembly 2] ...

對，合併以後，檔案絕對變大，然後千萬不要忘記了，要測試。另外，ILMerge 文件(ILMerge.doc)裡面有些限制以及問題，甚至是用法都有詳細描述，要記得閱讀...

	]]>
	</description>
	<content:encoded><![CDATA[
	這工具可以讓你把 .Net 不同語言編譯出來的 Assembly (組件)合併在一起。<br />
<br />
官方網址：<a href="http://research.microsoft.com/~mbarnett/ILMerge.aspx">ILMerge</a><br />
<br />
安裝以後，用法很簡單：<br />
<pre>"c:\Program Files\Microsoft\ILMerge\ILMerge.exe" /t:library /out:[輸出檔名] /lib:[Assembly搜索路徑] [要合併的 Assembly 1] [要合併的 Assembly 2] ...</pre><br />
<br />
只想給客戶一個可執行檔，不想給一堆其他組件的時候，這樣作也行：<br />
<pre>"c:\Program Files\Microsoft\ILMerge\ILMerge.exe" /t:[exe或winexe] /out:[輸出檔名] /lib:[Assembly搜索路徑] [執行檔] [要合併的 Assembly 1] [要合併的 Assembly 2] ...</pre><br />
<br />
對，合併以後，檔案絕對變大，然後千萬不要忘記了，要測試。另外，ILMerge 文件(ILMerge.doc)裡面有些限制以及問題，甚至是用法都有詳細描述，要記得閱讀...<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/6027919.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/6027919.html</guid>
	<category>.Net</category>
	<pubDate>Thu, 15 May 2008 15:16:32 +0800</pubDate>
</item>
<item>
	<title>包在 Mono Windows 版裡的東西</title>
	<description><![CDATA[
	再隨手記下一些：
VisualPng.exe，可以看 png 的軟體webshot.bat，可以抓取網頁當作圖片的 console 程式，不過在 Windows 跑不起來，會丟出需要 gtkembedmoz 的錯誤訊息ipy、ipy2，是的，有把 IronPython 包進來，不過互動模式怪怪的。ikvm，這是之前就有的，詳情請參考ikvm官方網頁說明，是可以讓 Java 程式在 mono 上執行的程式(甚至是互轉)jay，類似 yacc 的 parser，是的，c# compiler 就是以此為基礎xulrunner，好像是這一版才加入的，印象中之前並沒有，用途不明...cilc，用途不明，help 是寫：Mono CIL-to-C binding generatormonop、monop2，把類別的公開介面列出來的 console 程式monolinker，可以只把需要的類別抽取出來或是把一些程式安插進去的程式。

	]]>
	</description>
	<content:encoded><![CDATA[
	再隨手記下一些：<br />
<ul><li>VisualPng.exe，可以看 png 的軟體</li><li>webshot.bat，可以抓取網頁當作圖片的 console 程式，不過在 Windows 跑不起來，會丟出需要 gtkembedmoz 的錯誤訊息</li><li>ipy、ipy2，是的，有把 IronPython 包進來，不過互動模式怪怪的。</li><li>ikvm，這是之前就有的，詳情請參考<a href="http://www.ikvm.net/">ikvm</a>官方網頁說明，是可以讓 Java 程式在 mono 上執行的程式(甚至是互轉)</li><li>jay，類似 yacc 的 parser，是的，c# compiler 就是以此為基礎</li><li>xulrunner，好像是這一版才加入的，印象中之前並沒有，用途不明...</li><li>cilc，用途不明，help 是寫：Mono CIL-to-C binding generator</li><li>monop、monop2，把類別的公開介面列出來的 console 程式</li><li>monolinker，可以只把需要的類別抽取出來或是把一些程式安插進去的程式。</li></ul><br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/5831551.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/5831551.html</guid>
	<category>.Net</category>
	<pubDate>Tue, 08 Apr 2008 16:49:33 +0800</pubDate>
</item>
<item>
	<title>pythonw 與 monow</title>
	<description><![CDATA[
	Windows 版的 Python 在安裝以後，你會發現目錄下除了 python.exe 以外，還有一個 pythonw.exe，這是做什麼的呢？
簡單的說，python.exe 是一個 console 程式，執行 Python 程式的時候，在建立捷徑的時候，你會這樣寫：python your_app.py，但是執行時會出現一個黑色的 console 視窗。
pythonw.exe 作用則在於，不出現那個黑色的 console 視窗。

好，那 monow 的作用為何，你應該也能了解了吧～

特別指出這個的原因，是因為我這幾天在看 Mono 裝了什麼東西時發現的，其實我陸續還有看到一些東西，慢慢再介紹。

	]]>
	</description>
	<content:encoded><![CDATA[
	Windows 版的 <a href="http://python.org/">Python</a> 在安裝以後，你會發現目錄下除了 python.exe 以外，還有一個 pythonw.exe，這是做什麼的呢？<br />
簡單的說，python.exe 是一個 console 程式，執行 <a href="http://python.org/">Python</a> 程式的時候，在建立捷徑的時候，你會這樣寫：python your_app.py，但是執行時會出現一個黑色的 console 視窗。<br />
pythonw.exe 作用則在於，不出現那個黑色的 console 視窗。<br />
<br />
好，那 monow 的作用為何，你應該也能了解了吧～<br />
<br />
特別指出這個的原因，是因為我這幾天在看 <a href="http://www.mono-project.com">Mono</a> 裝了什麼東西時發現的，其實我陸續還有看到一些東西，慢慢再介紹。<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/5824561.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/5824561.html</guid>
	<category>.Net</category>
	<pubDate>Mon, 07 Apr 2008 14:10:52 +0800</pubDate>
</item>
<item>
	<title>亂碼 1/2</title>
	<description><![CDATA[
	此亂碼非彼亂馬啊～
家裏 Server 的 Mono 升級到 1.9 以後，ASP.Net 網頁裡的中文突然都變成了亂碼，可是我什麼都沒改啊～
由於個人因素 (就是懶啦)，一直都沒去管，今天看開了，決定找出真兇...

首先試著直接跑 xsp2 之後，用 Browser 去看結果，正常，沒有亂碼。很好，那麼應該是 mod_mono 跟 Apache 的問題囉～
再看看有亂碼的網頁，看看送出來的網頁與 Response header 是否正確，送出來網頁的中文都變成了 ?，可是從資料庫撈出來的字卻又都沒問題，可以正常顯示，網頁的 Response header 也沒問題。很好，那真的是 mod_mono 與 Apache 的問題了。

仔細看了 mod_mono 的設定，唯一我覺得有問題的，就是 MonoSetEnv，可是我確實地已經設定了 MonoSetEnv "LANG=en_US.UTF-8"，應該不會有問題才對。
好，那麼就寫個簡單的網頁把所有環境變數列出來看看，果不其然，LANG = C，這表示LANG並沒有被設定，那麼會出現亂碼也是很正常的了。LANG 對 Linux 來說，是很重要的環境變數，沒有這個，很多應用程式將無法判斷目前所在的語系與編碼。
那麼是 mod_mono 問題囉？可是看過 source code 之後，發現沒有特別針對 MonoSetEnv 做什麼修正，再回頭看看列出來的環境變數，我發現我在設定檔裡面設定的 TEMP 環境變數有生效，那麼?!

再仔細看一次 mod_mono 的說明，原來如果你要設定多個環境變數時，要加上 ';'，所以在我改寫為 MonoSetEnv "LANG=en_US.UTF-8;TEMP=/var/tmp"，重新啟動之後，問題就解決了。

p.s. 那...為啥以前沒錯?! 我想可能是 Apache 的 apr 行為有改變吧～

	]]>
	</description>
	<content:encoded><![CDATA[
	此亂碼非彼<a href="http://zh.wikipedia.org/wiki/%E4%B9%B1%E9%A9%AC">亂馬</a>啊～<br />
家裏 Server 的 <a href="http://www.mono-project.com">Mono</a> 升級到 1.9 以後，ASP.Net 網頁裡的中文突然都變成了亂碼，可是我什麼都沒改啊～<br />
由於個人因素 (就是懶啦)，一直都沒去管，今天看開了，決定找出真兇...<br />
<br />
首先試著直接跑 xsp2 之後，用 Browser 去看結果，正常，沒有亂碼。很好，那麼應該是 mod_mono 跟 Apache 的問題囉～<br />
再看看有亂碼的網頁，看看送出來的網頁與 Response header 是否正確，送出來網頁的中文都變成了 ?，可是從資料庫撈出來的字卻又都沒問題，可以正常顯示，網頁的 Response header 也沒問題。很好，那真的是 mod_mono 與 Apache 的問題了。<br />
<br />
仔細看了 mod_mono 的設定，唯一我覺得有問題的，就是 MonoSetEnv，可是我確實地已經設定了 MonoSetEnv "LANG=en_US.UTF-8"，應該不會有問題才對。<br />
好，那麼就寫個簡單的網頁把所有環境變數列出來看看，果不其然，LANG = C，這表示LANG並沒有被設定，那麼會出現亂碼也是很正常的了。LANG 對 Linux 來說，是很重要的環境變數，沒有這個，很多應用程式將無法判斷目前所在的語系與編碼。<br />
那麼是 mod_mono 問題囉？可是看過 <a href="http://anonsvn.mono-project.com/viewcvs/trunk/mod_mono/src/">source code</a> 之後，發現沒有特別針對 MonoSetEnv 做什麼修正，再回頭看看列出來的環境變數，我發現我在設定檔裡面設定的 TEMP 環境變數有生效，那麼?!<br />
<br />
再仔細看一次 mod_mono 的說明，原來如果你要設定多個環境變數時，要加上 ';'，所以在我改寫為 MonoSetEnv "LANG=en_US.UTF-8;TEMP=/var/tmp"，重新啟動之後，問題就解決了。<br />
<br />
p.s. 那...為啥以前沒錯?! 我想可能是 <a href="http://httpd.apache.org">Apache</a> 的 apr 行為有改變吧～<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/5797269.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/5797269.html</guid>
	<category>.Net</category>
	<pubDate>Wed, 02 Apr 2008 17:05:17 +0800</pubDate>
</item>
<item>
	<title>c# Iterator</title>
	<description><![CDATA[
	這裡沒有要解說什麼，下面這段程式是從 c# specification 來的，而程式本來是不能執行的，是的，範例有問題。問題點：原本的 IEnumerator&lt;T&gt; GetEnumerator() 應該加上 IEnumerable&lt;T&gt;.，成為 IEnumerator&lt;T&gt; IEnumerable&lt;T&gt;.GetEnumerator() 少繼承了 IEnumerable 介面並實做 IEnumerable.GetEnumerator()
我查了很久，才找到問題點，另外還參考 Bertrand Le Roy 的文章，精簡了 IEnumerable.GetEnumerator() 的代碼。

Iterator 就類似 Python/Boo Generator 的概念，目前我認知到最大的好處是，不一定要讓迴圈全部跑完，就可以先傳回一個值去處理。

using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;

public class Tree&lt;T&gt;: IEnumerable&lt;T&gt;, IEnumerable
{
	T value;
	Tree&lt;T&gt; left;
	Tree&lt;T&gt; right;
	public Tree(T value, Tree&lt;T&gt; left, Tree&lt;T&gt; right) {
		this.value = value;
		this.left = left;
		this.right = right;
	}
	
	IEnumerator&lt;T&gt; IEnumerable&lt;T&gt;.GetEnumerator() {
		if (left != null) {
			foreach (T x in left) 
				yield return x;
		}
		yield return value;
		if (right != null) {
			foreach (T x in right) 
				yield return x;
		}
	}

	// Yield and generics rock! - Tales from the Evil Empire &lt;http://weblogs.asp.net/bleroy/archive/2004/08/31/223531.aspx&gt;
	IEnumerator IEnumerable.GetEnumerator() {
		return (IEnumerator)(((IEnumerable&lt;T>)this).GetEnumerator());
	}
}

public class Program
{
	static Tree&lt;T&gt; MakeTree&lt;T&gt;(T[] items, int left, int right) {
		if (left &gt; right) 
			return null;
		int i = (left + right) / 2;
		return new Tree&lt;T&gt;(items[i], 
			MakeTree(items, left, i - 1),
			MakeTree(items, i + 1, right));
	}
	static Tree&lt;T&gt; MakeTree&lt;T&gt;(params T[] items) {
		return MakeTree(items, 0, items.Length - 1);
	}
	// The output of the program is:
	// 1 2 3 4 5 6 7 8 9
	// Mon Tue Wed Thu Fri Sat Sun
	public static void Main() {
		Tree&lt;int&gt; ints = MakeTree(1, 2, 3, 4, 5, 6, 7, 8, 9);
		foreach (int i in ints) 
			Console.Write("{0} ", i);
		Console.WriteLine();
		Tree&lt;string&gt; strings = MakeTree(
			"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun");
		foreach (string s in strings) 
			Console.Write("{0} ", s);
		Console.WriteLine();
		Console.ReadLine();
	}
}


額外的收穫是，發現 mono gmcs 編譯出來的代碼比 Microsoft csc 編譯出來的代碼要多出約四百多個 bytes。

	]]>
	</description>
	<content:encoded><![CDATA[
	這裡沒有要解說什麼，下面這段程式是從 c# specification 來的，而程式本來是不能執行的，是的，範例有問題。問題點：<ol><li>原本的 IEnumerator&lt;T&gt; GetEnumerator() 應該加上 IEnumerable&lt;T&gt;.，成為 IEnumerator&lt;T&gt; IEnumerable&lt;T&gt;.GetEnumerator() <li><li>少繼承了 IEnumerable 介面並實做 IEnumerable.GetEnumerator()</li></ol><br/>
我查了很久，才找到問題點，另外還參考 <a href="http://weblogs.asp.net/bleroy/">Bertrand Le Roy</a> 的文章，精簡了 IEnumerable.GetEnumerator() 的代碼。<br/>
<br/>
Iterator 就類似 Python/Boo Generator 的概念，目前我認知到最大的好處是，不一定要讓迴圈全部跑完，就可以先傳回一個值去處理。<br/>
<br/>
<pre name="code" class="c#">using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;

public class Tree&lt;T&gt;: IEnumerable&lt;T&gt;, IEnumerable
{
	T value;
	Tree&lt;T&gt; left;
	Tree&lt;T&gt; right;
	public Tree(T value, Tree&lt;T&gt; left, Tree&lt;T&gt; right) {
		this.value = value;
		this.left = left;
		this.right = right;
	}
	
	IEnumerator&lt;T&gt; IEnumerable&lt;T&gt;.GetEnumerator() {
		if (left != null) {
			foreach (T x in left) 
				yield return x;
		}
		yield return value;
		if (right != null) {
			foreach (T x in right) 
				yield return x;
		}
	}

	// Yield and generics rock! - Tales from the Evil Empire &lt;http://weblogs.asp.net/bleroy/archive/2004/08/31/223531.aspx&gt;
	IEnumerator IEnumerable.GetEnumerator() {
		return (IEnumerator)(((IEnumerable&lt;T>)this).GetEnumerator());
	}
}

public class Program
{
	static Tree&lt;T&gt; MakeTree&lt;T&gt;(T[] items, int left, int right) {
		if (left &gt; right) 
			return null;
		int i = (left + right) / 2;
		return new Tree&lt;T&gt;(items[i], 
			MakeTree(items, left, i - 1),
			MakeTree(items, i + 1, right));
	}
	static Tree&lt;T&gt; MakeTree&lt;T&gt;(params T[] items) {
		return MakeTree(items, 0, items.Length - 1);
	}
	// The output of the program is:
	// 1 2 3 4 5 6 7 8 9
	// Mon Tue Wed Thu Fri Sat Sun
	public static void Main() {
		Tree&lt;int&gt; ints = MakeTree(1, 2, 3, 4, 5, 6, 7, 8, 9);
		foreach (int i in ints) 
			Console.Write("{0} ", i);
		Console.WriteLine();
		Tree&lt;string&gt; strings = MakeTree(
			"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun");
		foreach (string s in strings) 
			Console.Write("{0} ", s);
		Console.WriteLine();
		Console.ReadLine();
	}
}
</pre>

額外的收穫是，發現 mono gmcs 編譯出來的代碼比 Microsoft csc 編譯出來的代碼要多出約四百多個 bytes。
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/5574113.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/5574113.html</guid>
	<category>.Net</category>
	<pubDate>Thu, 21 Feb 2008 18:12:01 +0800</pubDate>
</item>
<item>
	<title>ASP.Net in Debian/Ubuntu</title>
	<description><![CDATA[
	在 Ubuntu 下架設 mono xsp 其實還蠻愉快的。
Debian/Ubuntu的mono-xsp2套件提供了 mono-xsp2-admin 指令，用這個很快就能新增/刪除你的應用程式。
用法很簡單：sudo mono-xsp2-admin add --path=your_app_path --application=/your_app_name
接著重新啟動 mono-xsp2 服務即可：sudo /etc/init.d/mono-xsp2 restart
這個方法不需要安裝 mod_mono，因為這個時候 xsp2 是以一個獨立的 Daemon 存在。如果你希望 xsp2 應用程式是作為 Apache Web server 下的一個子目錄的話，你需要安裝 mod_proxy, mod_proxy_http, mod_proxy_html：sudo apt-get install libapache2-proxy-html
sudo a2enmod proxy proxy_html

然後在你的 VirtualHost 設定裡面加上：    &lt;Proxy *&gt;
        Order deny,allow
        Allow from all
    &lt;/Proxy&gt;

    ProxyPass /your_app_name http://localhost:your_port/your_app_name
    ProxyPassReverse /your_app_name http://localhost:your_port/your_app_name

    ProxyHTMLURLMap http://localhost:your_port /your_app_name/

    &lt;Location /your_app_name&gt;
        ProxyPassReverse /
        SetOutputFilter proxy-html
        ProxyHTMLURLMap / /your_app_name/
        Order allow,deny
        Allow from all
    &lt;/Location&gt;


接著重新啟動 Apache，這時候你在瀏覽器的網址列輸入 http://localhost/your_app_name/ 應該就可以存取到你的 asp.net 應用程式了。

備註：如果你不想使用 mono-xsp2，而只想把 Apache 當作前端，IIS當後端的話，同樣也可以用 mod_proxy, mod_proxy_html, mod_proxy_http 來解。

參考資料：Using Apache with mod_proxy - Confluence 2.7 - ConfluenceRunning a Reverse Proxy with Apache:mod_proxy_html

	]]>
	</description>
	<content:encoded><![CDATA[
	在 <a href="http://www.ubuntulinux.com">Ubuntu</a> 下架設 mono xsp 其實還蠻愉快的。<br/>
<a href="http://www.debian.org">Debian</a>/<a href="http://www.ubuntulinux.com">Ubuntu</a>的mono-xsp2套件提供了 mono-xsp2-admin 指令，用這個很快就能新增/刪除你的應用程式。<br/>
用法很簡單：<pre>sudo mono-xsp2-admin add --path=your_app_path --application=/your_app_name</pre>
接著重新啟動 mono-xsp2 服務即可：<pre>sudo /etc/init.d/mono-xsp2 restart</pre>
這個方法不需要安裝 mod_mono，因為這個時候 xsp2 是以一個獨立的 Daemon 存在。如果你希望 xsp2 應用程式是作為 <a href="http://httpd.apache.org">Apache</a> Web server 下的一個子目錄的話，你需要安裝 mod_proxy, mod_proxy_http, mod_proxy_html：<pre>sudo apt-get install libapache2-proxy-html
sudo a2enmod proxy proxy_html</pre>

然後在你的 VirtualHost 設定裡面加上：<pre>    &lt;Proxy *&gt;
        Order deny,allow
        Allow from all
    &lt;/Proxy&gt;

    ProxyPass /your_app_name http://localhost:your_port/your_app_name
    ProxyPassReverse /your_app_name http://localhost:your_port/your_app_name

    ProxyHTMLURLMap http://localhost:your_port /your_app_name/

    &lt;Location /your_app_name&gt;
        ProxyPassReverse /
        SetOutputFilter proxy-html
        ProxyHTMLURLMap / /your_app_name/
        Order allow,deny
        Allow from all
    &lt;/Location&gt;
</pre>
<br/>
接著重新啟動 Apache，這時候你在瀏覽器的網址列輸入 http://localhost/your_app_name/ 應該就可以存取到你的 asp.net 應用程式了。<br/>
<br/>
備註：如果你不想使用 mono-xsp2，而只想把 Apache 當作前端，IIS當後端的話，同樣也可以用 mod_proxy, mod_proxy_html, mod_proxy_http 來解。<br/>
<br/>
參考資料：<ul><li><a href="http://confluence.atlassian.com/display/DOC/Using+Apache+with+mod_proxy">Using Apache with mod_proxy - Confluence 2.7 - Confluence</a></li><li><a href="http://www.apachetutor.org/admin/reverseproxies">Running a Reverse Proxy with Apache:</a></li><li><a href="http://apache.webthing.com/mod_proxy_html/config.html">mod_proxy_html</a></li></ul>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/5500251.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/5500251.html</guid>
	<category>.Net</category>
	<pubDate>Mon, 04 Feb 2008 17:04:52 +0800</pubDate>
</item>
<item>
	<title>String.IsNullOrEmpty</title>
	<description><![CDATA[
	長見識，原來 .Net framework 2 之後為 String 多提供了一個方便的 Method：IsNullOrEmpty

所以以後可以不用寫成這樣了：
string s;
if( s!=null && s!=String.Empty )
{
  // do something
}


補充：不過有文章(DANGER ! String.IsNullOrEmpty can lead to runtime Null exceptions !! - @ Head)指出這方法其實有可能會丟出 Null exception.

	]]>
	</description>
	<content:encoded><![CDATA[
	<a href="http://blogs.msdn.com/vijaysk/archive/2008/01/24/anatomy-of-forms-authentication-return-url.aspx" title="Anatomy of ASP.NET Forms Authentication Return URL">長見識</a>，原來 .Net framework 2 之後為 String 多提供了一個方便的 Method：<a href="http://msdn2.microsoft.com/en-us/library/system.string.isnullorempty.aspx">IsNullOrEmpty</a><br/>
<br/>
所以以後可以不用寫成這樣了：<pre name="code" class="c#">
string s;
if( s!=null && s!=String.Empty )
{
  // do something
}
</pre>
<br/>
補充：不過有文章(<a href="http://msmvps.com/blogs/bill/archive/2006/04/04/89234.aspx">DANGER ! String.IsNullOrEmpty can lead to runtime Null exceptions !! - @ Head</a>)指出這方法其實有可能會丟出 Null exception.
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/5133623.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/5133623.html</guid>
	<category>.Net</category>
	<pubDate>Fri, 25 Jan 2008 09:45:20 +0800</pubDate>
</item>
<item>
	<title>為 Mono c# 編譯器的輸出添加一點色彩</title>
	<description><![CDATA[
	Miguel 大日前為 Mono c# 編譯器加了一點小小的加強(Colorful Error Output)，只要設定MCS_COLOR環境變數，就可以讓編譯器的輸出有比較顯目的色彩：
export MCS_COLORS=errors=brightwhite,red

如果你要關閉這功能的話，只要用
export MCS_COLORS=disable
就可以關閉。

不過照文章的日期看來，這功能應該在 1.2.7 以後才會有～

	]]>
	</description>
	<content:encoded><![CDATA[
	<a href="http://tirania.org/blog/">Miguel 大</a>日前為 Mono c# 編譯器加了一點小小的加強(<a href="http://tirania.org/blog/archive/2007/Dec-21-1.html">Colorful Error Output</a>)，只要設定MCS_COLOR環境變數，就可以讓編譯器的輸出有比較顯目的色彩：<br />
<pre>export MCS_COLORS=errors=brightwhite,red</pre><br />
<br />
如果你要關閉這功能的話，只要用<br />
<pre>export MCS_COLORS=disable</pre><br />
就可以關閉。<br />
<br />
不過照<a href="http://tirania.org/blog/archive/2007/Dec-21-1.html" title="Colorful Error Output">文章</a>的日期看來，這功能應該在 1.2.7 以後才會有～<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4963207.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4963207.html</guid>
	<category>.Net</category>
	<pubDate>Fri, 11 Jan 2008 18:10:11 +0800</pubDate>
</item>
<item>
	<title>在 Monorail 裡啟動 Logging 的方法</title>
	<description><![CDATA[
	參考這篇：Enabling logging就行了。

整理如下：
在 public 下新增一個檔案 log4net.config：
&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;configuration&gt;
    &lt;log4net&gt;
        &lt;!-- Define some output appenders --&gt;
        &lt;appender name="rollingFile" type="log4net.Appender.RollingFileAppender,log4net" &gt;
            &lt;param name="File" value="log.txt" /&gt;
            &lt;param name="AppendToFile" value="true" /&gt;
            &lt;param name="RollingStyle" value="Date" /&gt;
            &lt;param name="DatePattern" value="yyyy.MM.dd" /&gt;
            &lt;param name="StaticLogFileName" value="true" /&gt;
            &lt;layout type="log4net.Layout.PatternLayout,log4net"&gt;
                &lt;param name="ConversionPattern" value="%d [%t] %-5p %c [%x] (%X{auth}) - %m%n" /&gt;
            &lt;/layout&gt;
        &lt;/appender&gt;
        &lt;root&gt;
            &lt;!-- priority value can be set to ALL|INFO|WARN|ERROR --&gt;
            &lt;priority value="INFO" /&gt;
            &lt;appender-ref ref="rollingFile" /&gt;
        &lt;/root&gt;
    &lt;/log4net&gt;
&lt;/configuration&gt;

在 public/web.config 裡面，註冊 service：
&lt;monorail&gt;
    &lt;services&gt;
        &lt;service 
            id="Custom" 
            interface="Castle.Core.Logging.ILoggerFactory, Castle.Core"
            type="Castle.Services.Logging.Log4netIntegration.Log4netFactory, Castle.Services.Logging.Log4netIntegration" /&gt;
    &lt;/services&gt;
    &lt;!--略...--&gt;


	]]>
	</description>
	<content:encoded><![CDATA[
	參考這篇：<a href="http://www.castleproject.org/monorail/documentation/v1rc2/advanced/enablinglogging.html">Enabling logging</a>就行了。<br/>
<br/>
整理如下：
<ol><li>在 public 下新增一個檔案 log4net.config：<pre name="code" class="xml">
&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;configuration&gt;
    &lt;log4net&gt;
        &lt;!-- Define some output appenders --&gt;
        &lt;appender name="rollingFile" type="log4net.Appender.RollingFileAppender,log4net" &gt;
            &lt;param name="File" value="log.txt" /&gt;
            &lt;param name="AppendToFile" value="true" /&gt;
            &lt;param name="RollingStyle" value="Date" /&gt;
            &lt;param name="DatePattern" value="yyyy.MM.dd" /&gt;
            &lt;param name="StaticLogFileName" value="true" /&gt;
            &lt;layout type="log4net.Layout.PatternLayout,log4net"&gt;
                &lt;param name="ConversionPattern" value="%d [%t] %-5p %c [%x] (%X{auth}) - %m%n" /&gt;
            &lt;/layout&gt;
        &lt;/appender&gt;
        &lt;root&gt;
            &lt;!-- priority value can be set to ALL|INFO|WARN|ERROR --&gt;
            &lt;priority value="INFO" /&gt;
            &lt;appender-ref ref="rollingFile" /&gt;
        &lt;/root&gt;
    &lt;/log4net&gt;
&lt;/configuration&gt;
</pre></li>
<li>在 public/web.config 裡面，註冊 service：<pre name="code" class="xml">
&lt;monorail&gt;
    &lt;services&gt;
        &lt;service 
            id="Custom" 
            interface="Castle.Core.Logging.ILoggerFactory, Castle.Core"
            type="Castle.Services.Logging.Log4netIntegration.Log4netFactory, Castle.Services.Logging.Log4netIntegration" /&gt;
    &lt;/services&gt;
    &lt;!--略...--&gt;
</pre></li></ol>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4784799.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4784799.html</guid>
	<category>.Net</category>
	<pubDate>Mon, 07 Jan 2008 17:10:01 +0800</pubDate>
</item>
<item>
	<title>Monorail ActiveRecord Scaffold</title>
	<description><![CDATA[
	今天看官方文件時，看到這個：ActiveRecord Scaffold
只要有 model，monorail 可以自動幫你把 controller configure 成有 scaffold 功能 (CRUD都具備) 的 controller：

[Scaffolding( typeof(Blog) )]
public class BlogsController : Controller
{
}


這真是令人驚訝...不過 rc2 預設的 Layout 有問題，所以你最好加上 [Layout] attribute，自訂 Layout 比較好...
缺點是，要作 localization 的話，依照現在 rc2 的代碼，根本不可能...

結論是，有空可以來看看這邊的代碼(ARFormHelper.cs/PresentationHelper.cs)，因為 Generator 裡面的 ScaffoldHelper 有些情況沒考慮的很仔細。

	]]>
	</description>
	<content:encoded><![CDATA[
	今天看官方文件時，看到這個：<a href="http://www.castleproject.org/monorail/documentation/v1rc2/integration/arscaffold.html">ActiveRecord Scaffold</a><br/>
只要有 model，monorail 可以自動幫你把 controller configure 成有 scaffold 功能 (CRUD都具備) 的 controller：
<pre name="code" class="c#">
[Scaffolding( typeof(Blog) )]
public class BlogsController : Controller
{
}
</pre>
<br/>
這真是令人驚訝...不過 rc2 預設的 Layout 有問題，所以你最好加上 [Layout] attribute，自訂 Layout 比較好...<br/>
缺點是，要作 localization 的話，依照現在 rc2 的代碼，根本不可能...<br/>
<br/>
結論是，有空可以來看看這邊的代碼(ARFormHelper.cs/PresentationHelper.cs)，因為 Generator 裡面的 ScaffoldHelper 有些情況沒考慮的很仔細。<br/>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4770977.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4770977.html</guid>
	<category>.Net</category>
	<pubDate>Fri, 04 Jan 2008 16:40:44 +0800</pubDate>
</item>
<item>
	<title>How to monorail by Generator tool(4)</title>
	<description><![CDATA[
	在研究過之後，我決定在 ScaffoldHelper.cs 裡面添加 GetText 這個函數，用來取得字串。

    #region Localization helpers
    public string GetText( IResource resource, string str )
    {
        if( resource==null )
            return str;
        
        object resStr = resource[ str ];
        if( resStr==null )
            return str;
        
        return resStr.ToString();
    }
    #endregion

這樣在 .vm (template)檔案裡面，就可以這麼使用，以取得本地化後的字串：

$ScaffoldHelper.GetText($textres, "Name" )

當然你還是可以用原先的方法：

$textres.Name


所以 PageBrowser() 也可以跟著修正為：

    #region Pagination helpers
    public string PageBrowser( Page page )
    {
        return PageBrowser( page, null );
    }
        
    public string PageBrowser( Page page, IResource resource )
    {
        StringWriter output = new StringWriter();
        PaginationHelper helper = new PaginationHelper();
        helper.SetController(this.Controller);
        string firstText = GetText( resource, "First" );
        string prevText = GetText( resource, "Previous" );
        string nextText = GetText( resource, "Next" );
        string lastText = GetText( resource, "Last" );
			
        if (page.HasFirst)
            output.Write(helper.CreatePageLink(1, firstText ));
        else
            output.Write( firstText );
	
        output.Write(" | ");
			
        if (page.HasPrevious)
            output.Write(helper.CreatePageLink(page.PreviousIndex, prevText ));
        else
            output.Write(prevText);
        
        output.Write(" | ");
        
        if (page.HasNext) 
            output.Write(helper.CreatePageLink(page.NextIndex, nextText ));
        else
            output.Write( nextText );
        
        output.Write(" | ");
        
        if (page.HasLast) 
            output.Write(helper.CreatePageLink(page.LastIndex, lastText ));
        else
            output.Write( lastText );
			
        return output.ToString();
    }
    #endregion


最後在資源檔裡面加上必要的字串並且修改 .vm (template)以後，就可以得到本土化後的結果。

	]]>
	</description>
	<content:encoded><![CDATA[
	在研究過之後，我決定在 ScaffoldHelper.cs 裡面添加 GetText 這個函數，用來取得字串。
<pre name="code" class="c#">
    #region Localization helpers
    public string GetText( IResource resource, string str )
    {
        if( resource==null )
            return str;
        
        object resStr = resource[ str ];
        if( resStr==null )
            return str;
        
        return resStr.ToString();
    }
    #endregion
</pre>
這樣在 .vm (template)檔案裡面，就可以這麼使用，以取得本地化後的字串：
<pre name="code" class="html">
$ScaffoldHelper.GetText($textres, "Name" )
</pre>
當然你還是可以用原先的方法：
<pre name="code" class="html">
$textres.Name
</pre>

所以 PageBrowser() 也可以跟著修正為：
<pre name="code" class="c#">
    #region Pagination helpers
    public string PageBrowser( Page page )
    {
        return PageBrowser( page, null );
    }
        
    public string PageBrowser( Page page, IResource resource )
    {
        StringWriter output = new StringWriter();
        PaginationHelper helper = new PaginationHelper();
        helper.SetController(this.Controller);
        string firstText = GetText( resource, "First" );
        string prevText = GetText( resource, "Previous" );
        string nextText = GetText( resource, "Next" );
        string lastText = GetText( resource, "Last" );
			
        if (page.HasFirst)
            output.Write(helper.CreatePageLink(1, firstText ));
        else
            output.Write( firstText );
	
        output.Write(" | ");
			
        if (page.HasPrevious)
            output.Write(helper.CreatePageLink(page.PreviousIndex, prevText ));
        else
            output.Write(prevText);
        
        output.Write(" | ");
        
        if (page.HasNext) 
            output.Write(helper.CreatePageLink(page.NextIndex, nextText ));
        else
            output.Write( nextText );
        
        output.Write(" | ");
        
        if (page.HasLast) 
            output.Write(helper.CreatePageLink(page.LastIndex, lastText ));
        else
            output.Write( lastText );
			
        return output.ToString();
    }
    #endregion
</pre>

最後在資源檔裡面加上必要的字串並且修改 .vm (template)以後，就可以得到本土化後的結果。
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4727151.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4727151.html</guid>
	<category>.Net</category>
	<pubDate>Wed, 26 Dec 2007 16:55:30 +0800</pubDate>
</item>
<item>
	<title>How to monorail by Generator tool(3)</title>
	<description><![CDATA[
	這一次要講的是 Localization，不幸的是 Generator 沒有考慮到 Localization 問題，所以由 Generator 產生出來的代碼，並不包含這部份，但這卻是一個很好的機會讓我去了解 Generator 與 monorail 底下的機制。

Castle官方網站上已經有介紹該怎麼 Localization：Resources and Localization，但不幸的是，他使用 Visual Studio.Net 作為範例，Visual Studio.Net 已經掩蓋了所有細節。
在研究官方文件與相關文件之後，以下是我的步驟。

首先，你要先在 app/controllers 加上：

	[Resource("textres", "ToDo.categories")]

這表示在 view(template) 那兒使用 $textres 就可以存取資源檔的內容。

所以在 app/views/categories/list.vm 裡，就可以把必要的字串改用$textres.字串名稱替代掉，這裡我就不列出整個 list.vm 了，只列出幾行：

	&lt;!--略--&gt;
	$HtmlHelper.LinkTo( $textres.AddNewCategory, "categories", "new")
	&lt;!--略--&gt;
	$HtmlHelper.LinkTo( $textres.View, "categories", "view", $category.Id)
	&lt;!--略--&gt;
	$HtmlHelper.LinkTo( $textres.Edit, "categories", "edit", $category.Id)
	&lt;!--略--&gt;
	$AjaxHelper.LinkToRemote( $textres.Delete, "delete.aspx", $DictHelper.CreateDict("with='id=$category.Id'", "condition=confirm('Delete?')", "onsuccess=new Effect.Fade('category$category.Id')"))
	&lt;!--略--&gt;


然後我選擇在 app/ 下建立一個 resources 目錄，用來放置資源檔：

;Filename: categories.txt
;Language: en-US
View=View
Edit=Edit
Delete=Delete
AddNewCategory=Add a new Category


;Filename: categories.zh-tw.txt
;Language: zh-tw
View=檢視
Edit=編輯
Delete=刪除
AddNewCategory=加新類別

這裡要特別注意，把文字檔的編碼存為 unicode 或是 utf-8，否則會有亂碼出現。

最後修改 default.build，以便把資源檔編譯進去，這裡我也只列出關鍵的幾行：

	&lt;!--略--&gt;
	&lt;target name="build" description="Compile all source files"&gt;
		&lt;mkdir dir="${dir.bin}" /&gt;
		&lt;copy flatten="true" todir="${dir.bin}"&gt;
			&lt;fileset&gt;
				&lt;include name="${dir.lib.castle}/**" /&gt;
				&lt;include name="${dir.lib.npgsql}/**" /&gt;
				&lt;include name="${dir.lib.mysql}/**" /&gt;
				&lt;include name="${dir.lib.migrator}/**" /&gt;
				&lt;include name="${dir.lib.nunit}/nunit.framework.dll" /&gt;
			&lt;/fileset&gt;
		&lt;/copy&gt;
		&lt;resgen todir="${dir.src.app}/resources/"&gt;
			&lt;resources&gt;
				&lt;include name="${dir.src.app}/resources/*.txt" /&gt;
			&lt;/resources&gt;
		&lt;/resgen&gt;
		&lt;csc target="library" output="${dir.bin}/${project::get-name()}.dll"&gt;
			&lt;sources&gt;
				&lt;include name="${dir.config}/Boot.cs" /&gt;
				&lt;include name="${dir.src.app}/**/*.cs" /&gt;
				&lt;include name="${dir.src.test}/**/*.cs" /&gt;
				&lt;include name="${dir.migrations}/**/*.cs" /&gt;
			&lt;/sources&gt;
			&lt;resources basedir="." prefix="ToDo"&gt;
				&lt;include name="${dir.src.app}/resources/*.resources"/&gt;
			&lt;/resources&gt;
			&lt;references basedir="${dir.bin}"&gt;
				&lt;include name="System.Web.dll" /&gt;
	&lt;!--略--&gt;

最重要的就是 resgen 這個區塊與 csc 裡面的 resources 區塊，resgen 是把文字檔轉換為 .resources 資源檔，而 csc 裡面的 resources 則是表示要把產生出來的 .resources 編譯進去。

好了，該修改的都修改了，接下來就是重新建立，輸入 nant 就會自動重新編譯。
有點美中不足的是，下面顯示頁次的部份仍然是英文，這是因為這些字串被寫死在 ScaffoldHelper.cs 裡面，我想下次再來修改這部份。

後記：csc resources 所指定的 prefix 與 [Resource("textres", "ToDo.categories")] 的第二個參數息息相關，不妨修改來試試看。網站文件有提到 LocalizationFilter 的部份，但是用了卻不行，有待繼續研究。

	]]>
	</description>
	<content:encoded><![CDATA[
	這一次要講的是 Localization，不幸的是 Generator 沒有考慮到 Localization 問題，所以由 Generator 產生出來的代碼，並不包含這部份，但這卻是一個很好的機會讓我去了解 Generator 與 monorail 底下的機制。<br/>
<br/>
<a href="http://www.castleproject.org">Castle</a>官方網站上已經有介紹該怎麼 Localization：<a href="http://www.castleproject.org/monorail/documentation/v1rc2/usersguide/res_localization.html">Resources and Localization</a>，但不幸的是，他使用 Visual Studio.Net 作為範例，Visual Studio.Net 已經掩蓋了所有細節。
在研究官方文件與相關文件之後，以下是我的步驟。<br/>
<br/>
首先，你要先在 app/controllers 加上：
<pre name="code" class="c#">
	[Resource("textres", "ToDo.categories")]
</pre>
這表示在 view(template) 那兒使用 $textres 就可以存取資源檔的內容。<br/>
<br/>
所以在 app/views/categories/list.vm 裡，就可以把必要的字串改用<b>$textres.字串名稱</b>替代掉，這裡我就不列出整個 list.vm 了，只列出幾行：
<pre name="code" class="html">
	&lt;!--略--&gt;
	$HtmlHelper.LinkTo( $textres.AddNewCategory, "categories", "new")
	&lt;!--略--&gt;
	$HtmlHelper.LinkTo( $textres.View, "categories", "view", $category.Id)
	&lt;!--略--&gt;
	$HtmlHelper.LinkTo( $textres.Edit, "categories", "edit", $category.Id)
	&lt;!--略--&gt;
	$AjaxHelper.LinkToRemote( $textres.Delete, "delete.aspx", $DictHelper.CreateDict("with='id=$category.Id'", "condition=confirm('Delete?')", "onsuccess=new Effect.Fade('category$category.Id')"))
	&lt;!--略--&gt;
</pre>

然後我選擇在 app/ 下建立一個 resources 目錄，用來放置資源檔：
<pre>
;Filename: categories.txt
;Language: en-US
View=View
Edit=Edit
Delete=Delete
AddNewCategory=Add a new Category
</pre>
<pre>
;Filename: categories.zh-tw.txt
;Language: zh-tw
View=檢視
Edit=編輯
Delete=刪除
AddNewCategory=加新類別
</pre>
這裡要特別注意，把文字檔的編碼存為 unicode 或是 utf-8，否則會有亂碼出現。<br/>
<br/>
最後修改 default.build，以便把資源檔編譯進去，這裡我也只列出關鍵的幾行：
<pre name="code" class="html">
	&lt;!--略--&gt;
	&lt;target name="build" description="Compile all source files"&gt;
		&lt;mkdir dir="${dir.bin}" /&gt;
		&lt;copy flatten="true" todir="${dir.bin}"&gt;
			&lt;fileset&gt;
				&lt;include name="${dir.lib.castle}/**" /&gt;
				&lt;include name="${dir.lib.npgsql}/**" /&gt;
				&lt;include name="${dir.lib.mysql}/**" /&gt;
				&lt;include name="${dir.lib.migrator}/**" /&gt;
				&lt;include name="${dir.lib.nunit}/nunit.framework.dll" /&gt;
			&lt;/fileset&gt;
		&lt;/copy&gt;
		&lt;resgen todir="${dir.src.app}/resources/"&gt;
			&lt;resources&gt;
				&lt;include name="${dir.src.app}/resources/*.txt" /&gt;
			&lt;/resources&gt;
		&lt;/resgen&gt;
		&lt;csc target="library" output="${dir.bin}/${project::get-name()}.dll"&gt;
			&lt;sources&gt;
				&lt;include name="${dir.config}/Boot.cs" /&gt;
				&lt;include name="${dir.src.app}/**/*.cs" /&gt;
				&lt;include name="${dir.src.test}/**/*.cs" /&gt;
				&lt;include name="${dir.migrations}/**/*.cs" /&gt;
			&lt;/sources&gt;
			&lt;resources basedir="." prefix="ToDo"&gt;
				&lt;include name="${dir.src.app}/resources/*.resources"/&gt;
			&lt;/resources&gt;
			&lt;references basedir="${dir.bin}"&gt;
				&lt;include name="System.Web.dll" /&gt;
	&lt;!--略--&gt;
</pre>
最重要的就是 resgen 這個區塊與 csc 裡面的 resources 區塊，resgen 是把文字檔轉換為 .resources 資源檔，而 csc 裡面的 resources 則是表示要把產生出來的 .resources 編譯進去。<br/>
<br/>
好了，該修改的都修改了，接下來就是重新建立，輸入 nant 就會自動重新編譯。<br/>
有點美中不足的是，下面顯示頁次的部份仍然是英文，這是因為這些字串被寫死在 ScaffoldHelper.cs 裡面，我想下次再來修改這部份。<br/>
<br/>
後記：<ul><li>csc resources 所指定的 prefix 與 [Resource("textres", "ToDo.categories")] 的第二個參數息息相關，不妨修改來試試看。</li><li>網站文件有提到 LocalizationFilter 的部份，但是用了卻不行，有待繼續研究。</li></ul>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4722367.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4722367.html</guid>
	<category>.Net</category>
	<pubDate>Tue, 25 Dec 2007 16:54:39 +0800</pubDate>
</item>
<item>
	<title>How to monorail by Generator tool(2)</title>
	<description><![CDATA[
	接下來，就參考這篇有名的 Four Days on Rails 來試試看吧～
首先呢，由於隔了這麼久才寫這篇，所以 Generator 改位置了，你得從這裡：http://svn.castleproject.org:8080/svn/castle/trunk/Experiments/Generator/ Checkout，其他大致都跟上篇一樣。

先利用 monorail ToDo，建立專案，接著依照上篇文章作必要的設定，同時我們使用 rc2，不使用最新的版本(也就是你不用更動 default.build)，設定的部份就不再贅述。建立資料庫，這邊我是用MySQL，建立的資料庫名稱是 ToDoDev，不過這只有跟修改連線字串有關係。修改資料庫的連線字串，連線字串是放在 config/databases/ 下的 ActiveRecord 設定檔裡面，你可以看到這邊有兩個設定檔，他很貼心的把開發用與測試用的資料庫分開：development.xml、test.xml，事實上，你還可以增加一個 Production (或是其他名字)的 ActiveRecord 設定檔，表示這是正式上線用的資料庫。切換的時候，可以更動 config/boot.cs 以決定使用哪個 ActiveRecord 設定檔，預設是 development。建立 Model，首先先產生"Category"，Category 的欄位如下：  id int autoincrement
  name varchar(255)
  created_on datetime
  updated_on datetime
，在專案的目錄下輸入：script\generate model Categories name created_on updated_on，這邊要注意的是，不需要特別寫 id，因為慣例至上，Generator會自動幫你增加 Id 這個欄位。Generator 會幫你作三件事情：產生 Category 這個類別、產生測試 Category 的 Unit test 類別以及建立資料表格的程式，你可以從指令的輸出結果很清楚的看到。    exists app\models
    create app\models\Categories.cs
    exists test\models
    create test\models\CategoriesTest.cs
    create db\migrations
    create db\migrations\001_AddCategoriesTable.cs
接下來，要去修改 Categories 類別的屬性型態，Generator 預設都是把型態設為字串，db\migrations 那邊則都是建立 varchar(50)。所以除了 app\models\Categories.cs 要修改型態之外，db\migrations\001_AddCategoriesTable.cs 下也要改！這邊把 Name 改為 255 個字元，created_on與updated_on 則改為 DateTime。都修改完畢之後，就可以執行 nant migrate，這個步驟會幫你去實體資料庫作必要的事情。為甚麼要這樣子作？我想是因為一般資料庫的 script 是沒有作管理的，因此，才刻意把這些要去資料庫建立表格、修改欄位等的動作都放到 db\migrations 下，以便把這些程式也都納入版本控制。執行 script\generate scaffold Category，這個步驟會一口氣幫你把 CRUD 的頁面都弄出來。那麼，就編譯吧，直接執行 nant，只是卻出現了...[csc] app\controllers\CategoriesController.cs(36,72): error CS0246: 找不到型別或命名空間名稱 'Category' (您是否遺漏 using 指示詞或組件參考?)
[csc] app\controllers\CategoriesController.cs(56,45): error CS0246: 找不到型別或命名空間名稱 'Category' (您是否遺漏 using 指示詞或組件參考?)
這個，得去修改 CategoriesController.cs，把 Category 都改為 Categories，這看來是 Generator 的問題。接著又再出現
error CS1501: 方法 'CreatePagination' 沒有任何多載使用 '2' 個引數，唉～這個錯誤訊息實在是太黯然又太銷魂...你必須再次修改 CategoriesController.cs，添加這兩行：
using System.Collections;
using System.Collections.Generic;
然後把 PropertyBag["categories"] = PaginationHelper.CreatePagination( Categories.FindAll(), 10);改為
PropertyBag["categories"] = PaginationHelper.CreatePagination( (IList)Categories.FindAll(), 10);，接下來應該就沒問題了。先試試看到目前為止的成果吧，輸入script\server，然後打開你的瀏覽器，在位址列輸入：http://localhost:8080/categories/list.aspx，就能看到結果了。

執行結果：


	]]>
	</description>
	<content:encoded><![CDATA[
	接下來，就參考這篇有名的 <a href="http://rails.homelinux.org/">Four Days on Rails</a> 來試試看吧～<br/>
首先呢，由於隔了這麼久才寫這篇，所以 Generator 改位置了，你得從這裡：<a href="http://svn.castleproject.org:8080/svn/castle/trunk/Experiments/Generator/">http://svn.castleproject.org:8080/svn/castle/trunk/Experiments/Generator/</a> Checkout，其他大致都跟上篇一樣。<br/>
<br/>
<ol><li>先利用 monorail ToDo，建立專案，接著依照上篇文章作必要的設定，同時我們使用 rc2，不使用最新的版本(也就是你不用更動 default.build)，設定的部份就不再贅述。</li><li>建立資料庫，這邊我是用<a href="http://www.mysql.com">MySQL</a>，建立的資料庫名稱是 ToDoDev，不過這只有跟修改連線字串有關係。</li><li>修改資料庫的連線字串，連線字串是放在 config/databases/ 下的 ActiveRecord 設定檔裡面，你可以看到這邊有兩個設定檔，他很貼心的把開發用與測試用的資料庫分開：development.xml、test.xml，事實上，你還可以增加一個 Production (或是其他名字)的 ActiveRecord 設定檔，表示這是正式上線用的資料庫。切換的時候，可以更動 config/boot.cs 以決定使用哪個 ActiveRecord 設定檔，預設是 development。</li><li>建立 Model，首先先產生"Category"，Category 的欄位如下：<blockquote>  id int autoincrement<br/>
  name varchar(255)<br/>
  created_on datetime<br/>
  updated_on datetime<br/>
</blockquote>，在專案的目錄下輸入：script\generate model Categories name created_on updated_on，這邊要注意的是，不需要特別寫 id，因為慣例至上，Generator會自動幫你增加 Id 這個欄位。Generator 會幫你作三件事情：產生 Category 這個類別、產生測試 Category 的 Unit test 類別以及建立資料表格的程式，你可以從指令的輸出結果很清楚的看到。<blockquote>    exists app\models<br/>
    create app\models\Categories.cs<br/>
    exists test\models<br/>
    create test\models\CategoriesTest.cs<br/>
    create db\migrations<br/>
    create db\migrations\001_AddCategoriesTable.cs<br/>
</blockquote></li><li>接下來，要去修改 Categories 類別的屬性型態，Generator 預設都是把型態設為字串，db\migrations 那邊則都是建立 varchar(50)。所以除了 app\models\Categories.cs 要修改型態之外，db\migrations\001_AddCategoriesTable.cs 下也要改！這邊把 Name 改為 255 個字元，created_on與updated_on 則改為 DateTime。</li><li>都修改完畢之後，就可以執行 nant migrate，這個步驟會幫你去實體資料庫作必要的事情。為甚麼要這樣子作？我想是因為一般資料庫的 script 是沒有作管理的，因此，才刻意把這些要去資料庫建立表格、修改欄位等的動作都放到 db\migrations 下，以便把這些程式也都納入版本控制。</li><li>執行 script\generate scaffold Category，這個步驟會一口氣幫你把 CRUD 的頁面都弄出來。</li><li>那麼，就編譯吧，直接執行 nant，只是卻出現了...<blockquote>[csc] app\controllers\CategoriesController.cs(36,72): error CS0246: 找不到型別或命名空間名稱 'Category' (您是否遺漏 using 指示詞或組件參考?)<br/>
[csc] app\controllers\CategoriesController.cs(56,45): error CS0246: 找不到型別或命名空間名稱 'Category' (您是否遺漏 using 指示詞或組件參考?)
</blockquote>這個，得去修改 CategoriesController.cs，把 Category 都改為 Categories，這看來是 Generator 的問題。接著又再出現
<blockquote>error CS1501: 方法 'CreatePagination' 沒有任何多載使用 '2' 個引數</blockquote>，唉～這個錯誤訊息實在是太黯然又太銷魂...你必須再次修改 CategoriesController.cs，添加這兩行：
<pre name="code" class="c#">using System.Collections;
using System.Collections.Generic;
</pre>然後把 <pre name="code" class="c#">PropertyBag["categories"] = PaginationHelper.CreatePagination( Categories.FindAll(), 10);</pre>改為
<pre name="code" class="c#">PropertyBag["categories"] = PaginationHelper.CreatePagination( (IList)Categories.FindAll(), 10);</pre>，接下來應該就沒問題了。</li><li>先試試看到目前為止的成果吧，輸入script\server，然後打開你的瀏覽器，在位址列輸入：http://localhost:8080/categories/list.aspx，就能看到結果了。</li></ol>
<br/>
執行結果：
<a href="http://www.flickr.com/photos/elleryq/2124463394/" title="categories_list_aspx"><img src="http://static.flickr.com/2153/2124463394_4d918e0fb1_m.jpg" title="categories_list_aspx" alt="categories_list_aspx" width="240" height="175" /></a>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4693005.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4693005.html</guid>
	<category>.Net</category>
	<pubDate>Thu, 20 Dec 2007 14:53:35 +0800</pubDate>
</item>
<item>
	<title>Gtk# UI設計隨便聊</title>
	<description><![CDATA[
	前一陣子用MonoDevelop來寫 Gtk# 應用程式玩，發現真的是很簡單。
幾乎可以跟 SharpDevelop 或 Visual Studio.Net 設計 Windows form 應用程式一樣了，同樣也是拖拉放，就可以完成。

對於初入門的人來說，最痛苦的可能還是對於 Gtk# 的物件模型不熟悉，因為不熟悉，所以也就不知道該去處理哪些屬性與事件。
好在Mono官方網站有提供入門文件：GtkSharp系列文件Beginners Guide用力唸一唸這些文件跟自己去嘗試，大致上應該是夠了。但這些文件大部分都是自己去寫 Layout code。

如果你正在使用目前版本的 MonoDevelop 在 Layout 的話，你會發現世界全然不同，因為MonoDevelop引進了 Stetic。
現在使用 MonoDevelop 拉出來的 Form，實際上都會被存放在專案目錄下的 gtk-gui 目錄下的某個 xml 檔案，在每次 build 之前，MonoDevelop 會先把 xml 轉換為一個存放於 gtk-gui 目錄下的 partial 類別(.cs)，然後 build 的時候，再 build 到一起。而在專案目錄下所看到的代碼，只會有一行 Build()。
這真的是方便很多，開發者只需要專注於如何處理程式邏輯就可以，而不需要去管 UI 代碼的生成。

在 MonoDevelop 加入 Stetic 之前，大部分的 Gtk# 應用程式還是用手動加代碼或是用 Glade# 來設計介面（詳細的 Glade# 用法，可以參考 Your First Glade# Application 的說明）。
Glade# 其實也是把整個 UI 存成一個 xml 檔案，所以你得先使用 Glade 應用程式設計出 UI，得到 .glade 檔案，然後在程式裡面：載入 .glade 檔案為控制項(Widget)加上 Attribute撰寫事件處理並繫結。
這當然是比手動寫代碼方便許多，但比起 Stetic，還是要多作事，往往用 Glade 修改 UI 後，可能會忘記加必要的 Widget 宣告，或是對應的事件繫結。

	]]>
	</description>
	<content:encoded><![CDATA[
	前一陣子用<a href="http://www.monodevelop.com">MonoDevelop</a>來寫 Gtk# 應用程式玩，發現真的是很簡單。<br />
幾乎可以跟 <a href="http://www.icsharpcode.net/OpenSource/SD/">SharpDevelop</a> 或 Visual Studio.Net 設計 Windows form 應用程式一樣了，同樣也是拖拉放，就可以完成。<br />
<br />
對於初入門的人來說，最痛苦的可能還是對於 Gtk# 的物件模型不熟悉，因為不熟悉，所以也就不知道該去處理哪些屬性與事件。<br />
好在<a href="http://www.go-mono.com">Mono</a>官方網站有提供入門文件：<ul><li><a href="http://www.mono-project.com/Category:GtkSharp">GtkSharp系列文件</a></li><li><a href="http://www.mono-project.com/GtkSharpBeginnersGuide">Beginners Guide</a></li></ul>用力唸一唸這些文件跟自己去嘗試，大致上應該是夠了。但這些文件大部分都是自己去寫 Layout code。<br />
<br />
如果你正在使用目前版本的 <a href="http://www.monodevelop.com">MonoDevelop</a> 在 Layout 的話，你會發現世界全然不同，因為<a href="http://www.monodevelop.com">MonoDevelop</a>引進了 <a href="http://www.mono-project.com/Stetic">Stetic</a>。<br />
現在使用 <a href="http://www.monodevelop.com">MonoDevelop</a> 拉出來的 Form，實際上都會被存放在專案目錄下的 gtk-gui 目錄下的某個 xml 檔案，在每次 build 之前，<a href="http://www.monodevelop.com">MonoDevelop</a> 會先把 xml 轉換為一個存放於 gtk-gui 目錄下的 partial 類別(.cs)，然後 build 的時候，再 build 到一起。而在專案目錄下所看到的代碼，只會有一行 Build()。<br />
這真的是方便很多，開發者只需要專注於如何處理程式邏輯就可以，而不需要去管 UI 代碼的生成。<br />
<br />
在 <a href="http://www.monodevelop.com">MonoDevelop</a> 加入 <a href="http://www.mono-project.com/Stetic">Stetic</a> 之前，大部分的 Gtk# 應用程式還是用手動加代碼或是用 Glade# 來設計介面（詳細的 Glade# 用法，可以參考 <a href="http://www.mono-project.com/GtkSharpBeginnersGuide#Your_First_Glade.23_Application">Your First Glade# Application</a> 的說明）。<br />
Glade# 其實也是把整個 UI 存成一個 xml 檔案，所以你得先使用 Glade 應用程式設計出 UI，得到 .glade 檔案，然後在程式裡面：<ol><li>載入 .glade 檔案</li><li>為控制項(Widget)加上 Attribute</li><li>撰寫事件處理並繫結</li></ol>。<br />
這當然是比手動寫代碼方便許多，但比起 <a href="http://www.mono-project.com/Stetic">Stetic</a>，還是要多作事，往往用 Glade 修改 UI 後，可能會忘記加必要的 Widget 宣告，或是對應的事件繫結。<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4674857.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4674857.html</guid>
	<category>.Net</category>
	<pubDate>Tue, 18 Dec 2007 16:48:51 +0800</pubDate>
</item>
<item>
	<title>Gtk.TreeView(3)</title>
	<description><![CDATA[
	在 Linux 裡面，所謂的"事件"，多半是用 Signal 來表示，所以你看到 Signal 時，可以概略地當作"事件"來看。
而這些事件跟 Windows Form 的事件命名法差異相當大。
以下這些是比較常用到的：    protected virtual void OnTreeview1RowActivated (object o, Gtk.RowActivatedArgs args)
    {
        // double click
        Console.WriteLine( String.Format("[{0}]: {1}", o.GetType().ToString(), "row activated") );
    }
    
    protected virtual void OnTreeview1RowCollapsed (object o, Gtk.RowCollapsedArgs args)
    {
        // collapse
        Console.WriteLine( String.Format("[{0}]: {1}", o.GetType().ToString(), "row collapsed") );
    }
    
    protected virtual void OnTreeview1RowExpanded (object o, Gtk.RowExpandedArgs args)
    {
        // expand
        Console.WriteLine( String.Format("[{0}]: {1}", o.GetType().ToString(), "row expanded") );
    }
    
    protected virtual void OnTreeview1CursorChanged (object sender, System.EventArgs e)
    {
        // click
        Console.WriteLine( String.Format("[{0}]: {1}", sender.GetType().ToString(), "Cursor changed") );
    }


我是怎麼查到的呢？
坦白說，我是用笨方法，看到那些 Console.WriteLine 了沒？
我先試著在可能的事件裡面放置這些 Console.WriteLine，接著執行程式，試著去 Click、Expand，然後看 Console 輸出就知道了...

	]]>
	</description>
	<content:encoded><![CDATA[
	在 Linux 裡面，所謂的"事件"，多半是用 Signal 來表示，所以你看到 Signal 時，可以概略地當作"事件"來看。<br/>
而這些事件跟 Windows Form 的事件命名法差異相當大。<br/>
以下這些是比較常用到的：<pre name="code" class="c#">    protected virtual void OnTreeview1RowActivated (object o, Gtk.RowActivatedArgs args)
    {
        // double click
        Console.WriteLine( String.Format("[{0}]: {1}", o.GetType().ToString(), "row activated") );
    }
    
    protected virtual void OnTreeview1RowCollapsed (object o, Gtk.RowCollapsedArgs args)
    {
        // collapse
        Console.WriteLine( String.Format("[{0}]: {1}", o.GetType().ToString(), "row collapsed") );
    }
    
    protected virtual void OnTreeview1RowExpanded (object o, Gtk.RowExpandedArgs args)
    {
        // expand
        Console.WriteLine( String.Format("[{0}]: {1}", o.GetType().ToString(), "row expanded") );
    }
    
    protected virtual void OnTreeview1CursorChanged (object sender, System.EventArgs e)
    {
        // click
        Console.WriteLine( String.Format("[{0}]: {1}", sender.GetType().ToString(), "Cursor changed") );
    }
</pre>
<br/>
我是怎麼查到的呢？<br/>
坦白說，我是用笨方法，看到那些 Console.WriteLine 了沒？<br/>
我先試著在可能的事件裡面放置這些 Console.WriteLine，接著執行程式，試著去 Click、Expand，然後看 Console 輸出就知道了...
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4662027.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4662027.html</guid>
	<category>.Net</category>
	<pubDate>Mon, 17 Dec 2007 10:08:34 +0800</pubDate>
</item>
<item>
	<title>Gtk.TreeView (2)</title>
	<description><![CDATA[
	根據昨天的程式，稍作改良，就可以把整個目錄樹丟進去顯示了...
下面就是利用 Recursive 來把資料塞到 TreeStore 裡面去。


	public void _buildTreeStore( TreeStore store, DirectoryInfo di, TreeIter parent )
	{
		foreach( DirectoryInfo iter in di.GetDirectories() )
		{
			TreeIter ti = store.AppendValues( parent, iter.FullName, iter.Name, "" );
			_buildTreeStore( store, iter, ti, true  );
		}
		// add files in tree
		foreach( FileInfo fi in di.GetFiles() )
			store.AppendValues( parent, fi.FullName, fi.Name, fi.Length.ToString() );
	}
	
	public TreeStore buildTreeStore( string path )
	{
		// 0: fullpath 1: name 2: filesize
		TreeStore store = new TreeStore( typeof(string), typeof(string), typeof(string) );
		DirectoryInfo di = new DirectoryInfo( path );
		TreeIter root = store.AppendValues( path, di.Name, "" );
		_buildTreeStore( store, di, root );
		return store;
	}

	public ExplorerSharp(): base(Gtk.WindowType.Toplevel)
	{
		Build();

		TreeStore store = buildTreeStore( "./" );

		// 設定資料來源  
		treeview1.Model = store;  

		// 不顯示表頭  
		treeview1.HeadersVisible = false;  

		// 設定要顯示的欄位  
		treeview1.AppendColumn("Name", new CellRendererText(), "Name", 1 );  
		treeview1.AppendColumn("Size", new CellRendererText(), "FileSize", 2 );  

		// 一次只能選定一列或一個節點  
		treeview1.Selection.Mode = Gtk.SelectionMode.Single;  
	}


	]]>
	</description>
	<content:encoded><![CDATA[
	根據昨天的程式，稍作改良，就可以把整個目錄樹丟進去顯示了...<br/>
下面就是利用 Recursive 來把資料塞到 TreeStore 裡面去。<br/>
<br/>
<pre name="code" class="c#">
	public void _buildTreeStore( TreeStore store, DirectoryInfo di, TreeIter parent )
	{
		foreach( DirectoryInfo iter in di.GetDirectories() )
		{
			TreeIter ti = store.AppendValues( parent, iter.FullName, iter.Name, "" );
			_buildTreeStore( store, iter, ti, true  );
		}
		// add files in tree
		foreach( FileInfo fi in di.GetFiles() )
			store.AppendValues( parent, fi.FullName, fi.Name, fi.Length.ToString() );
	}
	
	public TreeStore buildTreeStore( string path )
	{
		// 0: fullpath 1: name 2: filesize
		TreeStore store = new TreeStore( typeof(string), typeof(string), typeof(string) );
		DirectoryInfo di = new DirectoryInfo( path );
		TreeIter root = store.AppendValues( path, di.Name, "" );
		_buildTreeStore( store, di, root );
		return store;
	}

	public ExplorerSharp(): base(Gtk.WindowType.Toplevel)
	{
		Build();

		TreeStore store = buildTreeStore( "./" );

		// 設定資料來源  
		treeview1.Model = store;  

		// 不顯示表頭  
		treeview1.HeadersVisible = false;  

		// 設定要顯示的欄位  
		treeview1.AppendColumn("Name", new CellRendererText(), "Name", 1 );  
		treeview1.AppendColumn("Size", new CellRendererText(), "FileSize", 2 );  

		// 一次只能選定一列或一個節點  
		treeview1.Selection.Mode = Gtk.SelectionMode.Single;  
	}
</pre>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4629083.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4629083.html</guid>
	<category>.Net</category>
	<pubDate>Wed, 12 Dec 2007 17:19:18 +0800</pubDate>
</item>
<item>
	<title>Gtk.TreeView (1)</title>
	<description><![CDATA[
	使用 TreeView 的基本，首先就是添加列與設定要顯示的欄。
呈現的方式，取決於你給 TreeView.Model 屬性的資料是什麼，如果是 TreeStore，就會顯示 Tree，如果是 ListStore，就會顯示 Grid。


    // 如果你把 TreeStore 改為 ListStore，就能得到類似 Grid 的效果。
    TreeStore store = new TreeStore();
    for( int i=0; i
	]]>
	</description>
	<content:encoded><![CDATA[
	使用 TreeView 的基本，首先就是添加列與設定要顯示的欄。<br/>
呈現的方式，取決於你給 TreeView.Model 屬性的資料是什麼，如果是 TreeStore，就會顯示 Tree，如果是 ListStore，就會顯示 Grid。<br/>
<br/>
<pre name="code" class="c#">
    // 如果你把 TreeStore 改為 ListStore，就能得到類似 Grid 的效果。
    TreeStore store = new TreeStore();
    for( int i=0; i<10; i++ )
    {
        TreeIter iter = store.AppendValues( "Demo " + i.ToString(), "" );
        // 添加子節點，你可以把這兩行註解掉試試看，這樣就沒有子節點了。
        for( int j=0; j<10; j++ )
            store.AppendValues( iter, "", "Child " + j.ToString() );
    }
    
    // 設定資料來源
    treeview1.Model = store;
    
    // 不顯示表頭
    treeview1.HeadersVisible = false;
    
    // 設定要顯示的欄位
    treeview1.AppendColumn("Name", new CellRendererText(), "i", 0 );
    treeview1.AppendColumn("Size", new CellRendererText(), "j", 1 );
    
    // 一次只能選定一列或一個節點
    treeview1.Selection.Mode = Gtk.SelectionMode.Single;
</pre>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4615599.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4615599.html</guid>
	<category>.Net</category>
	<pubDate>Tue, 11 Dec 2007 15:58:08 +0800</pubDate>
</item>
<item>
	<title>Gtk.TreeView</title>
	<description><![CDATA[
	這幾天玩MonoDevelop Stetic (gtk# 的 UI designer) 的時候，發現 gtk# 裡的 TreeView Widget 是個很有趣的元件。
有趣的原因，是因為他的設計哲學整個跟 Windows form 的設計哲學截然不同，Windows form 的 TreeView 就是很單純的 TreeView，沒別的。
而 gtk# 的 TreeView Widget 則是以所謂的 MVC Pattern 去設計，所以，其實 TreeView Widget 會根據你塞進去的 Store (Model) 來決定該怎麼去顯示。也因此，它既可以當作 Grid 來用，也可以當作 TreeView 來用，也可以當作有 TreeView 的 Grid 來用。
摸索的時候，花了不少時間，但今天打算寫這篇的時候，發現Mono官方網站就有 Tutorial：GtkSharp TreeView Tutorial，真的是白白浪費了摸索的時間...

	]]>
	</description>
	<content:encoded><![CDATA[
	這幾天玩<a href="http://www.monodevelop.com">MonoDevelop</a> Stetic (gtk# 的 UI designer) 的時候，發現 gtk# 裡的 TreeView Widget 是個很有趣的元件。<br />
有趣的原因，是因為他的設計哲學整個跟 Windows form 的設計哲學截然不同，Windows form 的 TreeView 就是很單純的 TreeView，沒別的。<br />
而 gtk# 的 TreeView Widget 則是以所謂的 MVC Pattern 去設計，所以，其實 TreeView Widget 會根據你塞進去的 Store (Model) 來決定該怎麼去顯示。也因此，它既可以當作 Grid 來用，也可以當作 TreeView 來用，也可以當作有 TreeView 的 Grid 來用。<br />
摸索的時候，花了不少時間，但今天打算寫這篇的時候，發現<a href="http://www.go-mono.com">Mono</a>官方網站就有 Tutorial：<a href="http://www.mono-project.com/GtkSharp_TreeView_Tutorial">GtkSharp TreeView Tutorial</a>，真的是白白浪費了摸索的時間...<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4596589.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4596589.html</guid>
	<category>.Net</category>
	<pubDate>Sat, 08 Dec 2007 17:12:14 +0800</pubDate>
</item>
<item>
	<title>如何在 Ubuntu/Debian 下重新編譯 mono/monodevelop</title>
	<description><![CDATA[
	謝謝你，Dale E. Moore：[MonoDevelop] Can't keep monodevelop running
信內所提供的方法，真是相當簡單又快速，也讓我學到 apt-get 的另外一個用法：build-dep

sudo apt-get build-dep mono monodevelop
Download mono-1.2.5.2.tar.bz2&lt;http://go-mono.com/sources/mono/mono-1.2.5.2.tar.bz2&gt;and monodevelop-0.17.tar.bz2&lt;http://go-mono.com/sources/monodevelop/monodevelop-0.17.tar.bz2&gt;from http://go-mono.com/sources-stable/.

bunzip2 mono-1.2.5.2.tar.bz2
tar xvf mono-1.2.5.2.tar.bz2
cd mono-1.2.5.2
./configure --prefix=`pkg-config --variable=prefix mono`
make
sudo make install

bunzip2 monodevelop-0.17.tar.bz2
tar xvf monodevelop-0.17.tar
cd monodevelop-0.17
./configure --prefix=`pkg-config --variable=prefix mono`
make
sudo make install


	]]>
	</description>
	<content:encoded><![CDATA[
	謝謝你，Dale E. Moore：<a href="http://lists.ximian.com/pipermail/monodevelop-list/2007-November/006985.html">[MonoDevelop] Can't keep monodevelop running</a><br />
信內所提供的方法，真是相當簡單又快速，也讓我學到 apt-get 的另外一個用法：build-dep<br />
<blockquote><br />
sudo apt-get build-dep mono monodevelop<br />
Download mono-1.2.5.2.tar.bz2&lt;http://go-mono.com/sources/mono/mono-1.2.5.2.tar.bz2&gt;and monodevelop-0.17.tar.bz2&lt;http://go-mono.com/sources/monodevelop/monodevelop-0.17.tar.bz2&gt;from http://go-mono.com/sources-stable/.<br />
<br />
bunzip2 mono-1.2.5.2.tar.bz2<br />
tar xvf mono-1.2.5.2.tar.bz2<br />
cd mono-1.2.5.2<br />
./configure --prefix=`pkg-config --variable=prefix mono`<br />
make<br />
sudo make install<br />
<br />
bunzip2 monodevelop-0.17.tar.bz2<br />
tar xvf monodevelop-0.17.tar<br />
cd monodevelop-0.17<br />
./configure --prefix=`pkg-config --variable=prefix mono`<br />
make<br />
sudo make install<br />
</blockquote><br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4557817.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4557817.html</guid>
	<category>.Net</category>
	<pubDate>Thu, 29 Nov 2007 12:30:26 +0800</pubDate>
</item>
<item>
	<title>.Net framework 2.0 SP1/3.0 SP1/3.5 無法安裝</title>
	<description><![CDATA[
	前一陣子Microsoft釋出了Visual Studio 2008/.Net framework 3.5，前兩天想裝起來看看，只是怎麼裝都不行。
經過與Google明查暗訪的結果，都說要先移除掉先前安裝的所有 .Net frameowrk以及登錄檔(Registry)裡面的資訊，再重新安裝才行。
還好，Microsoft的Aaron Stebner寫了一個工具，可以幫你作掉這些麻煩事，也因為這個工具，我先移除了先前安裝的 .Net framework 3.0，再移除掉 .Net framework 2.0，接著依序安裝 .Net framework 2.0 SP1、.Net framework 3.0 SP1、.Net framework 3.5，就大功告成了。

關於這個工具的文章與下載網址：Aaron Stebner's WebLog : Automated cleanup tool to remove the .NET Framework 1.0, 1.1, 2.0, 3.0 and 3.5

	]]>
	</description>
	<content:encoded><![CDATA[
	前一陣子<a href="http://www.microsoft.com">Microsoft</a>釋出了Visual Studio 2008/.Net framework 3.5，前兩天想裝起來看看，只是怎麼裝都不行。<br />
經過與<a href="http://www.google.com">Google</a>明查暗訪的結果，都說要先移除掉先前安裝的所有 .Net frameowrk以及登錄檔(Registry)裡面的資訊，再重新安裝才行。<br />
還好，<a href="http://www.microsoft.com">Microsoft</a>的<a href="http://blogs.msdn.com/astebner/">Aaron Stebner</a>寫了一個<a href="http://blogs.msdn.com/astebner/archive/2006/05/30/611355.aspx" title="Aaron Stebner's WebLog : Automated cleanup tool to remove the .NET Framework 1.0, 1.1, 2.0, 3.0 and 3.5">工具</a>，可以幫你作掉這些麻煩事，也因為這個工具，我先移除了先前安裝的 .Net framework 3.0，再移除掉 .Net framework 2.0，接著依序安裝 .Net framework 2.0 SP1、.Net framework 3.0 SP1、.Net framework 3.5，就大功告成了。<br />
<br />
關於這個工具的文章與下載網址：<a href="http://blogs.msdn.com/astebner/archive/2006/05/30/611355.aspx">Aaron Stebner's WebLog : Automated cleanup tool to remove the .NET Framework 1.0, 1.1, 2.0, 3.0 and 3.5</a><br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4553349.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4553349.html</guid>
	<category>.Net</category>
	<pubDate>Wed, 28 Nov 2007 17:48:52 +0800</pubDate>
</item>
<item>
	<title>新版 mod_mono 在啟動時的警告</title>
	<description><![CDATA[
	最近在重新啟動Apache httpd時，常出現這錯誤訊息(我的環境：CentOS 4.5)：
Starting httpd: [Tue Oct 30 07:39:41 2007] [crit] The unix daemon module not initialized yet. Please make sure that your mod_mono module is loaded after the User/Group directives have been parsed. Not initializing the dashboard.


今天早上認真地向Google祈禱了一下，發現有人問過了：[Mono-list] Errors after update....:(
解決方法很簡單，就是打開你的 httpd.conf，確定User apache
Group apache
在Include conf.d/*.conf之前即可。

	]]>
	</description>
	<content:encoded><![CDATA[
	最近在重新啟動<a href="http://www.apache.org/httpd/">Apache httpd</a>時，常出現這錯誤訊息(我的環境：CentOS 4.5)：<br />
<blockquote>Starting httpd: [Tue Oct 30 07:39:41 2007] [crit] The unix daemon module not initialized yet. Please make sure that your mod_mono module is loaded after the User/Group directives have been parsed. Not initializing the dashboard.<br />
</blockquote><br />
<br />
今天早上認真地向<a href="http://www.google.com.tw">Google</a>祈禱了一下，發現有人問過了：<a href="http://lists.ximian.com/pipermail/mono-list/2007-September/thread.html#36163">[Mono-list] Errors after update....:(</a><br />
解決方法很簡單，就是打開你的 httpd.conf，確定<pre>User apache<br />
Group apache</pre><br />
在<pre>Include conf.d/*.conf</pre>之前即可。<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/4390155.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/4390155.html</guid>
	<category>.Net</category>
	<pubDate>Tue, 30 Oct 2007 07:45:03 +0800</pubDate>
</item>
<item>
	<title>How to monorail by Generator tool(1)</title>
	<description><![CDATA[
	環境：Windows 2000/XP
需求：Subversion(或TortoiseSVNNAntMono，主要是要裡面的 boo
利用Subversion(或TortoiseSVN checkout Generator 出來，網址：http://svn.castleproject.org:8080/svn/castle/trunk/Tools/Generator/。進行編譯與安裝：nant install，這個步驟會將 monorail.bat 與 generator.bat 這兩個批次檔安裝到 c:\winnt 或 c:\windows 下。切換到你的工作目錄，執行 monorail your_project，就會自動幫你產生出 your_project 這個目錄，裡面就是完整的框架。切換到 your_project 目錄下，執行 nant setup，這個步驟會自動幫你下載官方網站上的 rc2 版本下來進行設定，如果你想要使用最新的組件，可以修改 default.build 裡面的 castle.url，將他改為官方 build server 上提供的網址(每日更新)，如：&lt;property name="castle.url" value="http://builds.castleproject.org/builds/castleproject-1.1-build_456-net-2.0-debug.zip" /&gt;；或是本地端位置 &lt;property name="castle.url" value="file://c:\download\Castle-net-2.0-debug-2007-7-30 (r4074).zip" /&gt;修改 public/web.config，第18行多了 &lt;services&gt; 將這行移除或註解掉。將 Mono 目錄下的 booi.bat 複製到 your_project 目錄下，script 目錄下的批次檔都會用到，所以複製到這邊以後會比較省事。修改 script\server.bat為如下內容，如果你不修改的話，Webdev.WebServer.exe 雖然可以順利執行，但卻會出錯。@booi script\server.boo %windir%\Microsoft.NET\Framework\v2.0.50727\Webdev.WebServer.exe norestart /port:8080 /path:%CD%\public執行 script\server，右下角會有 Webdev.WebServer.exe 的 trayicon 出現，告訴你可以用了。打開瀏覽器吧，在網址列輸入 http://localhost:8080/index.html 就可以看到畫面囉～

除了以上的步驟，產生出來的專案目錄下有個 README.TXT，你也可以好好地閱讀一下。

	]]>
	</description>
	<content:encoded><![CDATA[
	環境：Windows 2000/XP<br />
需求：<ul><li><a href="http://subversion.tigris.org/">Subversion</a>(或<a href="http://tortoisesvn.tigris.org/">TortoiseSVN</a></li><li><a href="http://nant.sourceforge.net">NAnt</a></li><li><a href="http://www.go-mono.com">Mono</a>，主要是要裡面的 boo</li></ul><br />
<ol><li>利用<a href="http://subversion.tigris.org/">Subversion</a>(或<a href="http://tortoisesvn.tigris.org/">TortoiseSVN</a> checkout Generator 出來，網址：<a href="http://svn.castleproject.org:8080/svn/castle/trunk/Tools/Generator/">http://svn.castleproject.org:8080/svn/castle/trunk/Tools/Generator/</a>。</li><li>進行編譯與安裝：nant install，這個步驟會將 monorail.bat 與 generator.bat 這兩個批次檔安裝到 c:\winnt 或 c:\windows 下。</li><li>切換到你的工作目錄，執行 monorail your_project，就會自動幫你產生出 your_project 這個目錄，裡面就是完整的框架。</li><li>切換到 your_project 目錄下，執行 nant setup，這個步驟會自動幫你下載官方網站上的 rc2 版本下來進行設定，如果你想要使用最新的組件，可以修改 default.build 裡面的 castle.url，將他改為<a href="http://builds.castleproject.org/cruise/index.castle">官方 build server</a> 上提供的網址(每日更新)，如：<blockquote>&lt;property name="castle.url" value="http://builds.castleproject.org/builds/castleproject-1.1-build_456-net-2.0-debug.zip" /&gt;</blockquote>；或是本地端位置 <blockquote>&lt;property name="castle.url" value="file://c:\download\Castle-net-2.0-debug-2007-7-30 (r4074).zip" /&gt;</blockquote></li><li>修改 public/web.config，第18行多了 &lt;services&gt; 將這行移除或註解掉。</li><li>將 <a href="http://www.go-mono.com">Mono</a> 目錄下的 booi.bat 複製到 your_project 目錄下，script 目錄下的批次檔都會用到，所以複製到這邊以後會比較省事。</li><li>修改 script\server.bat為如下內容，如果你不修改的話，Webdev.WebServer.exe 雖然可以順利執行，但卻會出錯。<blockquote>@booi script\server.boo %windir%\Microsoft.NET\Framework\v2.0.50727\Webdev.WebServer.exe norestart /port:8080 /path:%CD%\public</blockquote></li><li>執行 script\server，右下角會有 Webdev.WebServer.exe 的 trayicon 出現，告訴你可以用了。打開瀏覽器吧，在網址列輸入 http://localhost:8080/index.html 就可以看到畫面囉～</li></ol><br />
<br />
除了以上的步驟，產生出來的專案目錄下有個 README.TXT，你也可以好好地閱讀一下。<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/3850251.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/3850251.html</guid>
	<category>.Net</category>
	<pubDate>Thu, 02 Aug 2007 08:00:50 +0800</pubDate>
</item>
<item>
	<title>如何使用 Mono.GetOptions？</title>
	<description><![CDATA[
	Mono.GetOptions 是做什麼的？問的好。
如果你曾經在 Linux 下開發過 console 應用程式，相信你對於getopt這個 library 應該不陌生才對。
Mono.GetOptions 就是一個類似 getopt 的組件。

這裡主要是介紹怎麼使用，下面就列出步驟：
安裝Mono。在 AssemblyInfo.cs 裡面加入：//填入簡單的用法說明，顯示 help 時會用到
[assembly: Mono.UsageComplement("[-t:param] [-o] [-h] [-v] [-u]")]
//填入關於這程式的說明，也是顯示 help 時會用到
[assembly: Mono.About("A sample about how to use Mono.GetOptions")]
//作者
[assembly: Mono.Author("your_name")]
//有錯誤時可以通報誰，可填可不填
[assembly: Mono.ReportBugsTo("your_name@your_domain.com")]
//更詳細的說明，可填可不填
[assembly: Mono.AdditionalInfo("This is a sample about how to use Mono.GetOptions.  It's only a small program.  If you want to know more about Mono.GetOptions, you can hack Mono.GetOptions source code.")]
//是屬於哪個套件，可填可不填
[assembly: Mono.IsPartOfPackage("Samples")]
然後在原來的地方應該會有這些：[assembly: AssemblyTitle("Mono.GetOptions Sample")]
[assembly: AssemblyProduct("getoptions_sample")]
[assembly: AssemblyCopyright("your_name or your_organization")]
[assembly: AssemblyVersion("1.0.*")]
請記得都填入。引用 Mono.GetOptions 組件，用SharpDevelop的話，可以很方便的選 Add mono reference。記得 using Mono.GetOptions。using Mono.GetOptions;新增一個類別，繼承 Options。using System.Collections.Generic;
class ProgramOptions : Options
{
	private string _outputFolder = "output";

	public string OutputFolder
	{
		get { return _outputFolder; }
		set { _outputFolder = value; }
	}

	private List _templateFolders;

	// 表示最多容許兩個，參數可以用 -t 或是 --template
	// 用法大致是 -t:test 或 --template:test
	[Option(2, "Template folder, default is 'default'", 't', "template")]
	public WhatToDoNext DoTemplate( string s )
	{
		//Console.WriteLine( "template={0}", s );
		_templateFolders.Add( s );
		return WhatToDoNext.GoAhead;
	}

	// 預設只容許一個，參數是 -o 或 --output
	[Option("Output folder, default is 'output'", 'o', "output")]
	public WhatToDoNext DoOutput( string s )
	{
		//Console.WriteLine( "output={0}", s );
		_outputFolder = s;
		return WhatToDoNext.GoAhead;
	}

	public ProgramOptions()
	{
		// 表示同時接受 Linux / Windows 的命令列常態用法
		this.ParsingMode = OptionsParsingMode.Both;

		_templateFolders = new List();
	}
}
在 Main 裡面使用剛剛新增的類別：ProgramOptions options = new ProgramOptions(); 
options.ProcessArgs(args);
foreach( string s in options.TemplateFolders )
	Console.WriteLine( "Template folder = {0}", s );
Console.WriteLine( "Output folder = {0}", options.OutputFolder );
就這麼簡單。Build 以後，你可以在命令列模式或是 linux 的 console 模式下試試看了～這邊我假設你編譯出來的目的檔是 your_program：#your_program -h
#your_program --help
#your_program --template:t1 --template:t2 --output:o1
#your_program -t:t1 -t:t2 -o:o1
#your_program -u
#your_program -V
#your_program --version


對getopt有興趣的話，可以參考getopt。
這是對岸同志寫的介紹，很簡短：Mono项目提供的一个控制台程序辅助包GetOptions - 自由、创新、研究、探索…… - 博客园
這篇也是 Tutorial，寫的很好：The PumaCode.org Blog :: GetOpt style command line processing in C# with Mono.GetOptions

	]]>
	</description>
	<content:encoded><![CDATA[
	Mono.GetOptions 是做什麼的？問的好。<br/>
如果你曾經在 Linux 下開發過 console 應用程式，相信你對於<a href="http://www.gnu.org/software/libc/manual/html_node/Getopt.html" title="Getopt - The GNU C Library">getopt</a>這個 library 應該不陌生才對。<br/>
Mono.GetOptions 就是一個類似 <a href="http://www.gnu.org/software/libc/manual/html_node/Getopt.html" title="Getopt - The GNU C Library">getopt</a> 的組件。<br/>
<br/>
這裡主要是介紹怎麼使用，下面就列出步驟：
<ol><li>安裝<a href="http://www.go-mono.com">Mono</a>。</li><li>在 AssemblyInfo.cs 裡面加入：<pre name="code" class="c#">//填入簡單的用法說明，顯示 help 時會用到
[assembly: Mono.UsageComplement("[-t:param] [-o] [-h] [-v] [-u]")]
//填入關於這程式的說明，也是顯示 help 時會用到
[assembly: Mono.About("A sample about how to use Mono.GetOptions")]
//作者
[assembly: Mono.Author("your_name")]
//有錯誤時可以通報誰，可填可不填
[assembly: Mono.ReportBugsTo("your_name@your_domain.com")]
//更詳細的說明，可填可不填
[assembly: Mono.AdditionalInfo("This is a sample about how to use Mono.GetOptions.  It's only a small program.  If you want to know more about Mono.GetOptions, you can hack Mono.GetOptions source code.")]
//是屬於哪個套件，可填可不填
[assembly: Mono.IsPartOfPackage("Samples")]
</pre>然後在原來的地方應該會有這些：<pre name="code" class="c#">[assembly: AssemblyTitle("Mono.GetOptions Sample")]
[assembly: AssemblyProduct("getoptions_sample")]
[assembly: AssemblyCopyright("your_name or your_organization")]
[assembly: AssemblyVersion("1.0.*")]
</pre>請記得都填入。</li><li>引用 Mono.GetOptions 組件，用<a href="http://www.icsharpcode.net/OpenSource/SD/">SharpDevelop</a>的話，可以很方便的選 Add mono reference。</li><li>記得 using Mono.GetOptions。<pre>using Mono.GetOptions;</pre></li><li>新增一個類別，繼承 Options。<pre name="code" class="c#">using System.Collections.Generic;
class ProgramOptions : Options
{
	private string _outputFolder = "output";

	public string OutputFolder
	{
		get { return _outputFolder; }
		set { _outputFolder = value; }
	}

	private List<string> _templateFolders;

	// 表示最多容許兩個，參數可以用 -t 或是 --template
	// 用法大致是 -t:test 或 --template:test
	[Option(2, "Template folder, default is 'default'", 't', "template")]
	public WhatToDoNext DoTemplate( string s )
	{
		//Console.WriteLine( "template={0}", s );
		_templateFolders.Add( s );
		return WhatToDoNext.GoAhead;
	}

	// 預設只容許一個，參數是 -o 或 --output
	[Option("Output folder, default is 'output'", 'o', "output")]
	public WhatToDoNext DoOutput( string s )
	{
		//Console.WriteLine( "output={0}", s );
		_outputFolder = s;
		return WhatToDoNext.GoAhead;
	}

	public ProgramOptions()
	{
		// 表示同時接受 Linux / Windows 的命令列常態用法
		this.ParsingMode = OptionsParsingMode.Both;

		_templateFolders = new List<string>();
	}
}
</pre></li><li>在 Main 裡面使用剛剛新增的類別：<pre name="code" class="c#">ProgramOptions options = new ProgramOptions(); 
options.ProcessArgs(args);
foreach( string s in options.TemplateFolders )
	Console.WriteLine( "Template folder = {0}", s );
Console.WriteLine( "Output folder = {0}", options.OutputFolder );
</pre>就這麼簡單。</li><li>Build 以後，你可以在命令列模式或是 linux 的 console 模式下試試看了～這邊我假設你編譯出來的目的檔是 your_program：<pre>#your_program -h
#your_program --help
#your_program --template:t1 --template:t2 --output:o1
#your_program -t:t1 -t:t2 -o:o1
#your_program -u
#your_program -V
#your_program --version
</pre></li></ol>
<br/>
對<a href="http://www.gnu.org/software/libc/manual/html_node/Getopt.html" title="Getopt - The GNU C Library">getopt</a>有興趣的話，可以參考<a href="http://www.cs.nctu.edu.tw/~yslin/library/linuxc/function/16.html">getopt</a>。<br/>
這是對岸同志寫的介紹，很簡短：<li><a href="http://www.cnblogs.com/shanyou/archive/2007/06/09/777562.html">Mono项目提供的一个控制台程序辅助包GetOptions - 自由、创新、研究、探索…… - 博客园</a></li><br/>
這篇也是 Tutorial，寫的很好：<a href="http://blog.pumacode.org/2006/07/24/csharp-getopts-mono-getoptions/">The PumaCode.org Blog :: GetOpt style command line processing in C# with Mono.GetOptions</a><br/>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/3605181.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/3605181.html</guid>
	<category>.Net</category>
	<pubDate>Fri, 06 Jul 2007 14:14:54 +0800</pubDate>
</item>
<item>
	<title>如何在 CentOS 4/4.5 裡安裝 mono</title>
	<description><![CDATA[
	這裡，我假設你用 yum 來管理你的套件。

下載 mono.repo 然後放到 /etc/yum.repos.d/ (以 root 身份)#yum update#yum install mono-complete xsp mod_mono完成啦!

很簡單，對吧～
如果你用 Fedora Core 3/4/5 或者是 RHEL 4，你可以參考Mono 下載頁面。
安裝的方法跟上面所說得非常地類似。

	]]>
	</description>
	<content:encoded><![CDATA[
	這裡，我假設你用 yum 來管理你的套件。<br />
<br />
<ol><li>下載 <a href="http://www.go-mono.com/download-stable/rhel-4-i386/mono.repo">mono.repo</a> 然後放到 /etc/yum.repos.d/ (以 root 身份)</li><li>#yum update</li><li>#yum install mono-complete xsp mod_mono</li><li>完成啦!</li></ol><br />
<br />
很簡單，對吧～<br />
如果你用 Fedora Core 3/4/5 或者是 RHEL 4，你可以參考<a href="http://www.mono-project.com/Downloads">Mono 下載頁面</a>。<br />
安裝的方法跟上面所說得非常地類似。<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/3552733.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/3552733.html</guid>
	<category>.Net</category>
	<pubDate>Fri, 29 Jun 2007 16:20:33 +0800</pubDate>
</item>
<item>
	<title>ActiveRecord 的除錯</title>
	<description><![CDATA[
	老實說，這還真令人困擾，還好官方有說明如何得到更詳細的除錯資訊：Troubleshooting :: Castle Project。
基本上，就是加上一些設定，於是NHibernate 能根據這份設定以及內部有用到的 log4net library把一些訊息丟到 log 裡面去。
靠著產出出來的 log，終於找到問題。

	]]>
	</description>
	<content:encoded><![CDATA[
	老實說，這還真令人困擾，還好官方有說明如何得到更詳細的除錯資訊：<a href="http://www.castleproject.org/activerecord/documentation/trunk/usersguide/troubleshooting.html">Troubleshooting :: Castle Project</a>。<br />
基本上，就是加上一些設定，於是<a href="http://www.hibernate.org/343.html">NHibernate</a> 能根據這份設定以及內部有用到的 <a href="http://logging.apache.org/log4net/">log4net</a> library把一些訊息丟到 log 裡面去。<br />
靠著產出出來的 log，終於找到問題。<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/3426043.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/3426043.html</guid>
	<category>.Net</category>
	<pubDate>Thu, 07 Jun 2007 13:49:56 +0800</pubDate>
</item>
<item>
	<title>樂透下期號碼預測(3)-完結</title>
	<description><![CDATA[
	為甚麼沈寂了這麼久才寫這篇，那是因為我發現，樂透是不可預測的。其實有學過統計學的我早應該知道了。
如果你還是想試試看預測，那麼可以參考這一系列排列組合的文章，應該會很有幫助：
瓶水相逢:C# - P(n, r) 排列組合問題 - 樂多日誌瓶水相逢:C# - 產生 Permutation - P(n) 排列問題 - 樂多日誌瓶水相逢:C# - 產生 Combination - C(n, r) 組合問題 - 樂多日誌瓶水相逢:C# - 產生 Power Set - 樂多日誌

	]]>
	</description>
	<content:encoded><![CDATA[
	為甚麼沈寂了這麼久才寫這篇，那是因為我發現，樂透是不可預測的。其實有學過統計學的我早應該知道了。<br />
如果你還是想試試看預測，那麼可以參考這一系列排列組合的文章，應該會很有幫助：<br />
<ul><li><a href="http://blog.roodo.com/chhuang/archives/3198511.html">瓶水相逢:C# - P(n, r) 排列組合問題 - 樂多日誌</a></li><li><a href="http://blog.roodo.com/chhuang/archives/3198231.html">瓶水相逢:C# - 產生 Permutation - P(n) 排列問題 - 樂多日誌</a></li><li><a href="http://blog.roodo.com/chhuang/archives/3198041.html">瓶水相逢:C# - 產生 Combination - C(n, r) 組合問題 - 樂多日誌</a></li><li><a href="http://blog.roodo.com/chhuang/archives/3196737.html">瓶水相逢:C# - 產生 Power Set - 樂多日誌</a></li></ul><br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/3397425.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/3397425.html</guid>
	<category>.Net</category>
	<pubDate>Mon, 04 Jun 2007 11:49:34 +0800</pubDate>
</item>
<item>
	<title>Porting guide</title>
	<description><![CDATA[
	今天看到jpobst的這篇文章：Porting Guide。
他說，他上星期在Mono wiki上寫了一篇Guide: Porting Winforms Applications，內文提到如何將NClass移植到 Linux Mono 上的過程。
整個移植的過程相當簡單，首先利用MoMA (Mono Migration Analyzer)去分析NClass，得知NClass使用了哪些類別，而這些類別(內部的method)在Mono裡面是否已經被實做、有沒有使用 P/Invoke 等技術等等，接著再去補足Mono的類別或改寫 NClass(別忘記寄patch給原作者啊)，這樣就完成整個移植的過程。
對於想把 Windows 上的 .Net 應用程式移植到 Linux 的人，這是一篇相當具有參考性的文章。

	]]>
	</description>
	<content:encoded><![CDATA[
	今天看到<a href="http://jpobst.blogspot.com/">jpobst</a>的<a href="http://jpobst.blogspot.com/2007/05/porting-guide.html">這篇文章：Porting Guide</a>。<br />
他說，他上星期在<a href="http://www.go-mono.com">Mono wiki</a>上寫了一篇<a href="http://www.mono-project.com/Guide:_Porting_Winforms_Applications">Guide: Porting Winforms Applications</a>，內文提到如何將<a href="http://nclass.sourceforge.net/">NClass</a>移植到 Linux Mono 上的過程。<br />
整個移植的過程相當簡單，首先利用<a href="http://www.mono-project.com/MoMA">MoMA (Mono Migration Analyzer)</a>去分析<a href="http://nclass.sourceforge.net/">NClass</a>，得知<a href="http://nclass.sourceforge.net/">NClass</a>使用了哪些類別，而這些類別(內部的method)在<a href="http://www.go-mono.com">Mono</a>裡面是否已經被實做、有沒有使用 P/Invoke 等技術等等，接著再去補足<a href="http://www.go-mono.com">Mono</a>的類別或改寫 NClass(別忘記寄patch給原作者啊)，這樣就完成整個移植的過程。<br />
對於想把 Windows 上的 .Net 應用程式移植到 Linux 的人，這是一篇相當具有參考性的文章。<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/3344443.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/3344443.html</guid>
	<category>.Net</category>
	<pubDate>Fri, 25 May 2007 10:33:52 +0800</pubDate>
</item>
<item>
	<title>ActiveRecord</title>
	<description><![CDATA[
	ActiveRecord是一套相當不錯的 Pattern library，主要是實做ActiveRecord pattern，底層則是NHibernate。
大致的原理主要是在 Entity class 的屬性上加上 Attribute，Pattern 再根據這些資訊與設定來作 Object-relation mapping。

官方網站提供了一份很簡潔的指引：Getting started with ActiveRecord
很簡單，也很清楚，但是如果你想要更深入了解一些的話，我建議不妨參考大陸網友Yuhen的這一系列文章：[ActiveRecord] 之一：初始化和配置 - Q.yuhen[ActiveRecord] 之二：常用方法 - Q.yuhen[ActiveRecord] 之三：SessionScope - Q.yuhen[Castle AR] 4. CRUD - Q.yuhen[Castle AR] 5. Base Relations - Q.yuhen
或是Oren Eini的系列文章：Castle Demo App: Getting Started With Active RecordCastle Demo App: Active Record RelationsCastle Demo App: Lazy Loading and ScopesCastle Demo App: Many To Many Relations
或是Hamilton Verissimo的系列文章：All you wanted to know about Castle ActiveRecord - Part IAll you wanted to know about Castle ActiveRecord - Part II

我覺得都寫的相當不錯。

原本官方有提供很不錯的工具：ActiveRecord Generator，可以幫你從建好的 Database schema 去產生 entity class，省去你手動寫 code 的痛苦。
只是現在因為人力不足的關係，暫時停止繼續開發。

如果你想試試看所謂的ORM，不妨試試看這個 Library，可以讓你少寫掉很多很多 code。

	]]>
	</description>
	<content:encoded><![CDATA[
	<a href="http://www.castleproject.org/activerecord/">ActiveRecord</a>是一套相當不錯的 Pattern library，主要是實做<a href="http://en.wikipedia.org/wiki/Active_record">ActiveRecord pattern</a>，底層則是<a href="http://www.nhibernate.org/">NHibernate</a>。<br />
大致的原理主要是在 Entity class 的屬性上加上 Attribute，Pattern 再根據這些資訊與設定來作 <a href="http://en.wikipedia.org/wiki/Object-relational_mapping">Object-relation mapping</a>。<br />
<br />
官方網站提供了一份很簡潔的指引：<a href="http://www.castleproject.org/activerecord/gettingstarted/index.html">Getting started with ActiveRecord</a><br />
很簡單，也很清楚，但是如果你想要更深入了解一些的話，我建議不妨參考<a href="http://www.rainsts.net/">大陸網友Yuhen</a>的這一系列文章：<ul><li><a href="http://www.rainsts.net/article.asp?id=237">[ActiveRecord] 之一：初始化和配置 - Q.yuhen</a></li><li><a href="http://www.rainsts.net/article.asp?id=238">[ActiveRecord] 之二：常用方法 - Q.yuhen</a></li><li><a href="http://www.rainsts.net/article.asp?id=239">[ActiveRecord] 之三：SessionScope - Q.yuhen</a></li><li><a href="http://www.rainsts.net/article.asp?id=486">[Castle AR] 4. CRUD - Q.yuhen</a></li><li><a href="http://www.rainsts.net/article.asp?id=487">[Castle AR] 5. Base Relations - Q.yuhen</a></li></ul><br />
或是<a href="http://www.ayende.com/Blog/Default.aspx">Oren Eini</a>的系列文章：<ul><li><a href="http://www.ayende.com/Blog/archive/7898.aspx">Castle Demo App: Getting Started With Active Record</a></li><li><a href="http://www.ayende.com/Blog/archive/7897.aspx">Castle Demo App: Active Record Relations</a></li><li><a href="http://www.ayende.com/Blog/archive/7896.aspx">Castle Demo App: Lazy Loading and Scopes</a></li><li><a href="http://www.ayende.com/Blog/archive/7891.aspx">Castle Demo App: Many To Many Relations</a></li></ul><br />
或是<a href="http://hammett.castleproject.org/">Hamilton Verissimo</a>的系列文章：<ul><li><a href="http://geekswithblogs.net/hammett/articles/76697.aspx">All you wanted to know about Castle ActiveRecord - Part I</a></li><li><a href="http://geekswithblogs.net/hammett/articles/76809.aspx">All you wanted to know about Castle ActiveRecord - Part II</a></li></ul><br />
<br />
我覺得都寫的相當不錯。<br />
<br />
原本官方有提供很不錯的工具：<a href="http://wiki.castleproject.org/index.php/ActiveRecord_Generator">ActiveRecord Generator</a>，可以幫你從建好的 Database schema 去產生 entity class，省去你手動寫 code 的痛苦。<br />
只是現在因為人力不足的關係，暫時停止繼續開發。<br />
<br />
如果你想試試看所謂的<a href="http://en.wikipedia.org/wiki/Object-relational_mapping">ORM</a>，不妨試試看這個 Library，可以讓你少寫掉很多很多 code。<br />
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/3338939.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/3338939.html</guid>
	<category>.Net</category>
	<pubDate>Thu, 24 May 2007 17:03:43 +0800</pubDate>
</item>
<item>
	<title>tf4mono</title>
	<description><![CDATA[
	原來早已經有非微軟官方釋出的 Team Foundation Server 的 client 端工具了～
這樣子不管是在 Linux 下或是在不想使用微軟官方 client 的情況下，都可以方便的去存取 CodePlex 的 Repository 了。

網址在這裡：tf4mono

目前只有提供 Console mode 的指令，作者希望未來可以提供 MonoDevelop 的 Add-In...

消息來源：Rope on Fire: tf4mono version 0.4.4Team Foundation for Mono - Mono Project News
	]]>
	</description>
	<content:encoded><![CDATA[
	原來早已經有非微軟官方釋出的 Team Foundation Server 的 client 端工具了～<br />
這樣子不管是在 Linux 下或是在不想使用微軟官方 client 的情況下，都可以方便的去存取 <a href="http://codeplex.com">CodePlex</a> 的 Repository 了。<br />
<br />
網址在這裡：<a href="http://code.google.com/p/tf4mono/">tf4mono</a><br />
<br />
目前只有提供 Console mode 的指令，作者希望未來可以提供 <a href="http://monodevelop.org/">MonoDevelop</a> 的 Add-In...<br />
<br />
消息來源：<ul><li><a href="http://ropeonfire.blogspot.com/2007/05/tf4mono-version-044.html">Rope on Fire: tf4mono version 0.4.4</a></li><li><a href="http://www.mono-project.com/news/archive/2007/May-21.html">Team Foundation for Mono - Mono Project News</a></li></ul>		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/3282655.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/3282655.html</guid>
	<category>.Net</category>
	<pubDate>Mon, 21 May 2007 11:23:58 +0800</pubDate>
</item>
<item>
	<title>Visual WebGui (VWG)</title>
	<description><![CDATA[
	今天在 Mono-dev 群組上看到有人詢問是否有類似 GWT 的軟體，可以快速開發 .Net 上的 ajax 程式。
Miguel 大大回答到有這麼一套：Visual WebGui (VWG) 

有空的話，來試試看好不好用。
	]]>
	</description>
	<content:encoded><![CDATA[
	今天在 Mono-dev 群組上看到有人詢問是否有類似 GWT 的軟體，可以快速開發 .Net 上的 ajax 程式。<br />
<a href="http://tirania.org/blog/">Miguel 大大</a>回答到有這麼一套：<a href="http://www.codeplex.com/visualwebgui">Visual WebGui (VWG) </a><br />
<br />
有空的話，來試試看好不好用。		]]>
	</content:encoded>
	<link>http://blog.roodo.com/thinkingmore/archives/3282643.html</link>
	<guid>http://blog.roodo.com/thinkingmore/archives/3282643.html</guid>
	<category>.Net</category>
	<pubDate>Sun, 20 May 2007 11:19:49 +0800</pubDate>
</item>
<item>
	<title>利用 Gmail SMTP server 來寄信</title>
	<description><![CDATA[
	詳情可以參考這篇：Send E-Mail from your .NET application using your GMail Account，內文提供了 .Net 1.1/2.0 的方法。

我自己用 .Net 2，試的結果，發現有這個錯誤訊息出現："Must issue a STARTTLS command first"
Google 大神告訴我，有蠻多人詢問這個問題。
仔細研讀之後，發現是我自己忘了幫 SmtpClient 設置 EnableSsl 屬性為 true。

加上之後，又丟出 "The requested feature is not implemented."。
咦？沒實做，難道我用的Mono 1.2.3.1還沒實做這部份？
用Reflector反組譯出來看之後，果然...真的還沒實做 SSL 傳輸的部份。
希望下一版會加進去...這樣就可以在 Linux 下使用了。
以下是程式碼，它是一個命令列的程式，讓你可以指定必要的欄位後寄送郵件。
打 MailSharp -h 可以得到使用說明。
/**
 * MailSharp
 *
 * Reference:
 * 	Send E-Mail from your .NET application using your GMail Account - The Code Project - C# Programming &lt;http://www.codeproject.com/useritems/SendMailUsingGmailAccount.asp&gt;
 */
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.Threading;
using System.ComponentModel;

namespace MailSharp {
public class MailSharpConsole {
    public static string showUsage() {
        StringBuilder sb = new StringBuilder();

        sb.AppendLine( "Usage: MailSharp [options] ToAddress" );
        sb.AppendLine( "\t-a File to attach." );
        sb.AppendLine( "\t-f From address" );
        sb.AppendLine( "\t-b Body message" );
        sb.AppendLine( "\t-s Subject");
        sb.AppendLine( "\t-S SMTP server host" );
        sb.AppendLine( "\t-U Username for SMTP server authentication" );
        sb.AppendLine( "\t-p Password for SMTP server authentication" );
        sb.AppendLine( "\t-l Use SSL" );
        sb.AppendLine( "\t-h Help/Usage");
        sb.AppendLine();
        sb.AppendLine( "Example:" );
        sb.AppendLine( "\tFor GMail" );
        sb.AppendLine( "\tMailSharp -f your_name@gmail.com -b Test -s Test -S smtp.gmail.com -P 587 -l -U your_gmail -p your_gmail_password someone@somewhere.com" );

        return sb.ToString();
    }

    public static void Main(string[] args) {
        MailAddress from = null;
        MailAddress to = null;
        MailMessage message = new MailMessage();
        SmtpClient client = new SmtpClient();
        NetworkCredential myCred = new NetworkCredential();
        bool bShowUsage=false;

        try {
            if ( args.Length &gt; 0 ) {
                for ( int i=0; i&lt;args.Length; i++ ) {
                    switch ( args[i] ) {
                    case "-S": // server host
                        i++;
                        if ( i&lt;args.Length ) {
                            client.Host = args[i];
                        } else
                            throw new Exception( "-S was specified, but no value." );
                        break;
                    case "-P": // server port
                        i++;
                        if ( i&lt;args.Length ) {
                            client.Port=Convert.ToInt32( args[i] );
                        } else
                            throw new Exception( "-P was specified, but no value." );
                        break;
                    case "-T": // timeout
                        i++;
                        if ( i&lt;args.Length ) {
                            client.Timeout = Convert.ToInt32( args[i] );
                        } else
                            throw new Exception( "-T was specified, but no value." );
                        break;
                    case "-U": // username for smtp server authentication
                        i++;
                        if ( i&lt;args.Length )
                            myCred.UserName = args[i];
                        else
                            throw new Exception( "-U was specified, but no value." );
                        break;
                    case "-p": // password for smtp server authentication
                        i++;
                        if ( i&lt;args.Length )
                            myCred.Password = args[i];
                        else
                            throw new Exception( "-p was specified, but no value." );
                        break;
                    case "-l": // use SSL
                        client.EnableSsl = true;
                        break;
                    case "-s": // subject
                        i++;	// next one is subject.
                        if ( i&lt;args.Length ) {
                            message.Subject = args[i];
                            message.SubjectEncoding = System.Text.Encoding.UTF8;
                        } else
                            throw new Exception( "-s was specified, but no value." );
                        break;
                    case "-a":	// attachment
                        i++;	// next one is attachment filename.
                        if ( i&lt;args.Length ) {
                            // Add attachment.
                            Attachment data = new Attachment( args[i], MediaTypeNames.Application.Octet);
                            message.Attachments.Add(data);
                        } else
                            throw new Exception( "-a was specified, but no value." );
                        break;
                    case "-b":	// body message.
                        i++;	// next one is body message
                        if ( i&lt;args.Length ) {
                            message.Body = args[i];
                            message.BodyEncoding =  System.Text.Encoding.UTF8;
                        } else
                            throw new Exception( "-b was specified, but no value." );
                        break;
                    case "-f":	// from address
                        i++;
                        if ( i&lt;args.Length ) {
                            // Specify the e-mail sender.
                            // Create a mailing address that includes a UTF8 character
                            // in the display name.
                            // from = new MailAddress( "someone@gmail.com", "someo