2010-08-06 40 views
0

我有一個.NET 1.1。應用程序,它通過一個定製的翻譯系統,看起來有點像這樣提供字符串資源:取消訂閱來自長期事件源的表單組件 - 何時?

interface ITranslationProvider 
{ 
    string GetTranslation(string key); 
    event LanguageChangedEvent LanguageChanged; 
} 

即:語言可以在運行時更改和組件需要通過更新顯示字符串迴應。

單個翻譯提供程序將持續應用程序的生命週期,而使用翻譯服務的Windows Forms組件會動態創建。如果我編寫使用此表單的組件,何時是退訂LanguageChanged事件的正確時間?

例如,它似乎是壓倒一切的Disposing()應該工作:

class MyPanel : System.Windows.Forms.Panel 
{ 
    public MyPanel(ITranslationProvider translator) 
    { 
     this.translator = translator; 
     translator.LanguageChanged += new LanguageChangedEvent(SetText); 
     SetText(); 
    } 

    protected override void Dispose(bool disposing) 
    { 
     base.Dispose(disposing); 

     // is this the correct place to unregister? will Dispose() get 
     // called on this panel, even though the translator's event has 
     // a reference to it? 
     translator.LanguageChanged -= new LanguageChangedEvent(SetText); 
    } 

    private void SetText() 
    { 
     this.Text = translator.GetTranslation("my.panel.text"); 
    } 

    private ITranslationProvider translator; 
} 

...但我無法找到一個明確的答案,這是否是安全與否。有任何想法嗎?

回答

2

當您處理其父表單時,您的控制權將爲Dispose d。

如果您通過調用Show()來顯示錶單,.Net將在關閉時自動處理它。
如果您致電ShowDialog(),則需要負責處理該表格,推測可能在using區塊中。 (即使它不添加事件處理程序,也應該處理表單)

0

個人而言,我更喜歡在HandleDestroyed事件(使用OnHandleDestroyed覆蓋,因爲我不喜歡自我訂閱)中取消訂閱外部事件。這不依賴於我的組件的用戶做正確的事情 - 如果他們使用ShowDialog調用Dispose。

我也在HandleCreated事件中訂閱,因爲ShowDialog可以被多次調用(其中Show不能)。

1

是的,使用Disposing()很好。如果客戶端代碼混淆了這一點,所以它不會被調用,然後由於句柄泄漏而導致更大的問題。

請注意,這些「反向事件」是尷尬的。如果您知道事件源始終超出了消費者的範圍,那麼回調可能是更合適的解決方案。示例界面聲明:

public interface ITranslatableControl { 
    void SetText(); 
} 

public MyPanel : Panel, ITranslatableControl { 
    public MyPanel() { 
     TranslationManager.RegisterControl(this); 
    } 
    void SetText() { 
     this.Text = TranslationManager.GetText(this, "mumble"); 
    } 
} 

public static class TranslationManager { 
    private List<ITranslatableControl> controls; 
    public void RegisterControl(ITranslatableControl text) { 
     Control ctl = (Control)text; 
     ctl.Disposed += delegate { controls.Remove(text); } 
     controls.Add(text); 
     text.SetText(); // optional 
    } 
} 

注意如何偵聽Disposed事件允許管理器自動從註冊控件列表中刪除控件。客戶端控件不能再通過忘記重寫Disposing來搞砸了。在語言改變時,只需迭代列表並調用SetText()方法即可。還要注意,如果控件具有多個可轉換字符串,您現在可以爲同一個控件註冊多個回調。現在,您還可以在Register方法中爲字符串指定關鍵字,並將翻譯作爲SetText()的參數提供。等等。