Archive for the ‘.NET’ tag
Tomboy Plugin - CJKDisableSpell
平常已經習慣使用 Tomboy 來記東西,介面還算好用,隨時都可以開新 Note 或是搜尋舊的 Note。用到現在唯一不滿意的地方是 tomboy 會對文章做 spelling check,無論內容是什麼,結果就是中文的 Note 會變成滿江紅。
花了一點時間寫了這個 plugin,可以針對 CJK 的部份取消 spelling check,效果還滿不錯
使用前:
使用後:
使用方法,下載 CJKDisableSpellPlugin.cs 後自己編譯:
mcs -t:library CJKDisableSpellPlugin.cs -r:/usr/lib/tomboy/Tomboy.exe -pkg:GTK-sharp-2.0
或是直接下載編譯好的 CJKDisableSpellPlugin.dll
將 dll 放置在 ~/.tomboy/Plugins/ 後,重新啟動 Tomboy 即可。
MonoDevelop 0.10
MonoDevelop 0.10 Release 了,裡面整合了最新的 GUI Designer — Stetic
實際試用的感覺不錯,而且跟 IDE 整合在一起,是使用 auto generated code ,而不是用 .glade 檔。 很有潛力的開發環境。
Bibot3 新功能
好吧,拖了很久才寫。
自從 bibot2 從 zion 人間蒸發之後[1],就開始了用 mono 寫新的 bibot3 的計畫,但是對於到底要有什麼功能一直沒有什麼好點子。從 bibot2 的經驗來看,網址自動紀錄大概是最多人在用的功能,我從來沒想到 URL.dot 掛掉之後會有那麼多人詢問…
某天跟 chihchun 閒聊,討論到把網址丟到某個 social bookmarks 服務(像是 del.icio.us) 的可能性,既然 del.icio.us 有公開 API,那麼應該不難實做,甚至比自己刻資料庫還簡單。
於是,在某天下課後查了一下 API 研究怎麼使用,然後就誕生了 http://del.icio.us/bibot。結果比想像中的有趣,因為 del.icio.us 有 tag 的功能,所以可以根據 tag 來判斷某網址是誰、在哪個 channel 提到的,也會自動紀錄時間和更新 title。
附帶一提,tinyurl.com 也有 API 可以呼叫,所以短網址的功能也可以輕鬆完成,不用再自己 parse 網頁的 output。
[1]: 某次停電之後,位在 zion 的 lvm 上的某 vserver 整個消失,只剩下 lost+found ,至今找不到原因。
.NET - Plugin
我之前在 .NET - Load Plugins 寫過如何實做簡單的 plugin interface,最近真正在用的時候才發現問題。
Assembly.Load* 雖然可以把 .dll 檔案動態載入,可是卻找不到任何方法可以 unload.. Assembly 在被載入之後是處於鎖定的狀態,如果這時候把檔案換掉的話,Assembly.Load 便無法再重新載入,會出現 Exception
這樣就沒辦法在後端偷偷換掉 backend 了 -_-
要實做動態的 load, unload 好像是要使用 System.AppDomain 來做(時際上是用 Remoting 的技術),看似簡單,可是我試到現在還沒成功過… 還變成好像 Assembly 被 Cache 起來的情況,怎麼 load, unload 都是用到舊的 Assembly… 天阿
Short, Int, 加加減減
short x = 32767;
x = x + 2;
在 C 裡面,我們可能不小心寫出這樣的 code 而不自覺會造成 overflow,但是在 C# 則會得到
error CS0266: Cannot implicitly convert type ‘int’ to ’short’. An explicit conversion exists (are you missing a cast?)
要改成
x = (short)(x +2);
才行; 不過神奇的是,如果寫成
x += 2;
則不會有任何問題的直接 overflow… 這究竟是什麼樣的設計考量呢?
ASP.NET 2.0
今天下午心血來潮測試了一下 mono 的 ASP.NET 支援,mono 除了有 apache 用的 mod-mono 模組之外,還提供了一個 standalone 的簡單 webserver — xsp/xsp2 ,主要用來做開發測試用。
用 C# 來寫的程式都很正常,不管是 1.0 或 2.0 profile 都可以跑,可是後來想要測試 Nemerle 時卻不斷發生錯誤…
作 .NET compiler 的人應該要提供 Codedom 的 CodeCompiler,CodeGenerator 等等,供其他程式利用內部 DOM 結構動態產生程式碼,主要是用在 ASP.NET
原來 Nemerle 所實做的 Codedom 是從舊的 C# 版本移植的,後來沒有持續更新到 2.0 所以有些地方會出問題,像是沒有使用 partial class,不能把 aspx 與 codefile 分開等等,為了修正這些錯誤下午都在看 Codedom 與 System.Web.Compilation 的東西,現在已經可以正常的用 Nemerle 寫 ASP.NET 2.0
patch 在這裡。
Update: This patch has been applied.
Suffix Tree
Suffix Tree,在字串處理上有非常多的應用,尤其是字串的搜尋、定位等等,利用這個資料結構很多都可以在 O(n) 也就是 linear time 做完。
這是在這學期的 字串學(stringology) 學到的,作業就是實做 suffix tree,我用的是 Ukkonen 的演算法,可以用 on-line construction 的方法建構 suffix tree。
我是用 Nemerle 寫的(因為在練習),後來也有用 C# 改了另外的版本,但是還是 Nemerle 的版本比較完整。原本是用 System.Collections.Generic.Dictionary 來存每個 State 裡面的 transitions,可是非常的吃記憶體,用 mono –profile 可以很容易看出來一個 500kb 的檔案,在建構的時候光 Dictionary 就可以吃掉近 150mb 的記憶體;後來改用自己的 linked list 來做,節省了很多資源,2mb 的測試檔可以在 9 秒內建完樹並回報內部節點個數。
整個程式應該還有多可以改進的地方,但是目前的效率作為作業已經可以接受了,先放上來。在這裡。
System.Text.UTF8Encoding
在用 SmartIRC4Net 寫 IRC 程式的時候發現,如果把 encoding 設成 System.Text.Encoding.UTF8 會導致無法連上 IRC server。
很好奇的看了 SmartIRC4Net 的 code 結果沒什麼收穫,用的是一般的 StreamWriter 的初始化方法;如果改用 System.Text.UTF8Encoding 就可以正確連上了,而且這是 StreamWriter 預設的 encoding。
到底 Encoding.UTF8 和 UTF8Encoding 兩個有什麼不一樣呢?看了一下 mono 的實做方法,使用上這兩個都是 用 UTF8Encoding 的 instance,只是 Encoding.UTF8 是有 BOM 的,UTF8Encoding 則預設沒有。
就是因為那個多出來的 BOM 導致 IRC server 無法認出正確的指令(因為不是 vaild ascii code),在一般使用上也要注意這兩者的差別。
Nemerle - Redefining symbols
在 nemerle 裡面,可以用
def a = 123;
這樣的格式來定義一個 immutable 的變數
然而,這樣的寫法也是 vaild 的
def a = 123;
def a = "123";
雖然看起來像是給 immutable 的 a assign 了兩次不同的值,實際上兩者有完全不同的意義,所以
def (x, y) = (1, 3);
def (x, y) = (y, x);
也都是被接受的語法。
.NET - Program Glue
C 的 stdio.h 有 popen/pclose 可以用,python 有 popen/popen2… ,perl 可以把程式當作檔案代號直接開啟執行,這些都可以做到程式間黏合、互動,那 .NET 要怎麼作呢?
可以用 System.Diagnostics.Process 來做到一樣的功能:
using System;
using System.Diagnostics;
public module T {
public Main (args: array[string]) : void
{
def proc = Process ();
def proc_info = ProcessStartInfo (args[0]);
proc_info.CreateNoWindow = true;
proc_info.UseShellExecute = false;
proc_info.RedirectStandardInput = true;
proc_info.RedirectStandardOutput = true;
proc_info.RedirectStandardError = true;
proc.StartInfo = proc_info;
proc.Start ();
while (true) {
proc.StandardInput.WriteLine (Console.ReadLine ());
Console.WriteLine (proc.StandardOutput.ReadLine ());
}
}
}


