2012年1月19日

[.Net] 介面可以繼承介面,但結果卻不是我想的那樣


事情是這樣發生的,
有一天我們決定讓 Spring.Net 進入我們的生活,
於是衝擊到了 GridView + ObjectDataSource 的美好時光,
是的, Spring.Net 讓我們的 Business Object 都虛化了(ㄜ我想說的是IoC),
而 ObjectDataSource 預設是用這種方式產生BusinessObject的執行個體:
e.ObjectInstance = Activator.CreateInstance(method.Type)
想當然,還沒透過 Spring.Net Injection 進來,一執行就賞你一個:
並未將物件參考設定為物件的執行個體
這很正常,而我們也在他發生前就預料到,並加以處理,處理的方式很簡單,
就如同 Creating an ObjectDataSource Control Source Object 中提到的,
You can control how the source object is created by handling the ObjectCreating event of the ObjectDataSource control. You can create an instance of the source object, and then set the ObjectInstance property of the ObjectDataSourceEventArgs class to that instance. The ObjectDataSource control will use the instance that is created in the ObjectCreating event instead of creating an instance on its own.
一切看起來是那麼的美好,但現實往往都比想象中來得殘酷,
因為我們的 Business Object 希望可以方便被客製,
於是我們讓他看起來像這樣:

問題來了,看似正常,但一執行就被賞了一個 ObjectDataSource 找不到參數的非泛型方法,
雖然所有介面都定義在 Core.Business.IFooServices 裡,
但 Business.IFooServices 明明就有繼承 Core.BUsiness.IFooServices,
為什麼操作 Business.IFooServices 就告訴我找不到方法,
追查的結果發現,在 ObjectDataSource 裡是用 Reflection 的手法GetMethod並Invoke,


Dim methods As MethodInfo() = type.GetMethods((BindingFlags.FlattenHierarchy Or (BindingFlags.Public Or (BindingFlags.Static Or BindingFlags.Instance))))

而偏偏 type.GetMethods 遇到 Interface 就不管他老子是誰了!
即使有告訴他要 BindingFlags.FlattenHierarchy 也沒用,
於是就拜請 Google 大神,這才發現,
原來
介面是可以繼承介面,但結果卻不是我想的那樣。
詳細的內容,下面的參考資料裡,每位大大都寫的很清楚,就不多談了,

直接下結論
介面繼承介面時,衍生的介面不需要實作父介面(這看起來很像繼承),而介面可以繼承 0 - 多個介面(哇,多重繼承?其實他也不過是介面而已),實作衍生介面時,需要實作衍生介面及其父介面(下面這段Code故意用 VB.Net的寫法,很驚人(至少嚇到我了)的 Inherits 可以寫不只一次)。

Interface a

    Sub a1method()
End Interface

Interface b

    Inherits a
    Sub b1method()
End Interface

Interface c

    Inherits a
    Inherits b
    Sub c1method()
End Interface
Class ca
    Implements c
    Public Sub a1method() Implements a.a1method
    End Sub

    Public Sub b1method() Implements b.b1method
    End Sub

    Public Sub c1method() Implements c.c1method
    End Sub
End Class
而介面繼承的目的,只是告訴實作,在實作介面時,要連同其繼承的介面一併實作僅此而已,
對介面而言,只紀錄其繼承的介面是誰,不會把父介面的宣告抄一分給自己,
所以,以上例而言,class ca實作的對象雖然是 c ,
但自動產生出來的程式,卻是各個 Interface(見上面程式粗體字的地方),
如果是C#,使用明確實作就不能實作c.b1method 及 c.a1method,因為c根本就沒有他們。

--
參考資料

  1. .Net Interfaces Are Not Classes
  2. Reflection Pop Quiz - Does interface inheritance exist?
  3. Interface “inheritance” in C#
  4. Type.GetMethods Method (BindingFlags)
  5. 13.1.2 Base interfaces
  6. Interface Design

2011年12月14日

[Mac] 停止 mail 收件人更新通訊錄

繼上一篇 "設定 Mac 通訊錄讀取 Zimbra 全域聯絡人" 之後,
發現,只要 mail 一收到信,收件人就會自動更新到通訊錄中,
這立意是不錯,但困擾的是,姓和名的欄位根本就不對,
被更新過的通訊錄,姓氏和名字的欄位竟然會重複,一整個很無奈,
找了很久,終於在網路上找到解決的方式了,有需要的人請享用:


defaults write com.apple.mail SuppressAddressHistory -bool true

在 terminal 中執行上面這行指令,關閉 mail 後,重新開啟就會生效了。
有一點小小的副作用:即使收件人是不存在通訊錄中的,他也不會自動加到通訊錄中,
連收件人紀錄也不會寫,不過這點到是對我沒有影響,
因為我喜歡手動加到通訊錄,勝過讓他自動幫我加。

2011年11月28日

[Mac] 讓 Mac 認識 Windows 的電腦名稱

要從 Mac 上用電腦名稱連進 Windows 的網路芳鄰,常讓人一個頭兩個大,
這裡提供的作法是把 IP 和 電腦名稱的對應,放到 /etc/hosts 檔案裡,
只要記憶過一次,下次就不用更做這樣的動作,
畢竟,大部份的人,常用的電腦就那幾台而已。

其實這篇是( Lion 下批次更新 hosts 檔的 shell script )的延伸
將前述的 shell script 包裝起來變成 app


服用前請注意,

1. 不能修改此 app 的檔名(若改名可能會造成 hosts遺失)
2. 使用前一定要先備分 /etc/hosts
3. hosts 若不慎遺失請不要怪我

下載位置:

找主機IP.app.zip


[Mac] 設定 Mac 通訊錄讀取 Zimbra 全域聯絡人

自從公司把 Exchange Server 換成了 Zimbra 後,很多作業都不順,
尤其是在非 Microsoft 的作業系統上,很多設定都要自力自強,
在 Mac 上Mail 和 Calendar 都不是太大的問題,
但 Contacts 就麻煩了,
因為他的設定太無腦了,直接就抓該帳號的聯絡人,
在介面上還沒有地方可以設定,改抓全域聯絡人,
下面來介紹一下,可以調整這個設定的方式,

以下設定先決條件是,Zimbra Server 上有設 galsync account

首先,打開通訊錄,然後加入一個 CardDav 帳號(通訊錄 -> 偏好設定)

設定完成後,將通訊錄關閉
打開 Finder,按 Command + Shift + G
在跳出的 TextBox 中輸入 ~/Library/Application Support/AddressBook/Sources 並前往該路徑

在該路徑下可以看到如下圖的目錄,但目錄名稱是第一個步驟動態產生的,所以會因人而異
在該目錄下會有一個 Configuration.plist,用文字編輯器將此檔案開起(如果有XCode的話也可以用XCode提供的編輯器編輯)。


打開聯絡資訊 -> 偏號設定 -> 帳號
在伺服器設定裡將紅框處的文字複製出來。
在 Configuration.plist 中尋找剛剛複製出來的文字,
如下圖標示紅框處,調整為 Zimbra Server 上設定的 galsync account 的名字


接下來再重新開啟通訊錄,便會開始同步 GAL 的聯絡人囉。

2011年10月26日

[Mac] bbedit 真好用

BBedit 就他像的 slogan

It doesn’t suck.®

但他不止不糟,而且還非常的優秀。
最棒的是還提供了 command line 的指令
bbedit、bbfind、bbdiff

bbedit 的用法,網路上有一堆文章在介紹,也就不多提了,
來看一下 bbfind ,
在換到 Mac Book Air 上工作後,
另一個(前一個)困擾我的問題是,
在 Windows 上有個非常好用的 grepWin ,
可以讓我在追程式問題的時候,快速的找到相關關鍵字的程式,
但 Mac 下一直找不到好用的替代品,
其實我要的功能不多,只要可以整合 finder,
簡單的輸入關鍵字,就會在指定的目錄下搜尋所有文字檔,
且不同編碼的文字檔也要可以搜尋。
像這樣:



2011年10月4日

[Javascript] console object 如何 cross-browser

前面有提到 console 物件 的內容及使用,
緊接著會遇到的問題就是,不是所有的瀏覽器都有這玩意,
以下是利用 ExtJS  applyIf 的方式,解決 cross-browser 的問題。

    function applyIf(object, config) {
        var property;
    
        if (object) {
            for (property in config) {
                if (object[property] === undefined) {
                    object[property] = config[property];
                }
            }
        }
    
        return object;
    }
    function PageLoad() {
        
        window.console = window.console || {};
        
        applyIf(window.console, {
            log: function(message) { alert(message); } ,
            info: function(message) { alert(message); } ,
            error: function(message) { throw message; }
        });
        
        console.log("log");
        console.info("info");
        console.error("error");
    }