2015-10-22 25 views
1

是否有任何方便的方法來序列化存儲在Resources.resx文件中(以多種語言)存儲的字符串的引用。我想稍後訪問它(應用程序可能已重新啓動後)並以當前活動的語言顯示它。序列化可本地化的字符串

另一個用例是將「資源項」傳遞給某種方法,例如,顯示錯誤消息(使用當前活動的語言),同時用英語記錄消息(以便我們可以對其進行調試)。

需要牢記的一點是,我們不只有一個Resource.resx文件(在這種情況下,我們可以簡單地存儲密鑰並使用ResourceManager實例),但是其中大量的應用。

有多種用例:一個目的是避免不必要的代碼重複。這是更方便寫類似ShowMessage(messageKey)(其中顯示消息並記錄它),而不是寫

ShowMessage(Resources.ResourceManager.GetString("Key", CultureInfo.CurrentCulture)); 
Log(Resources.ResourceManager.GetString("Key", CultureInfo.InvariantCulture)); 

這也將有一定的局部異常(有用的,這樣的組件不必須知道什麼關於ShowMessage方法)。在我的情況下,我有一些可序列化的CNC宏,我想要一些本地化的消息步驟(用戶在繼續之前必須做一些手動操作)。配置宏和執行時,語言可能會有所不同。

+0

真的有這個需求嗎?這些資源應該用作靜態資源,動態使用它們看起來像是一種代碼異味。你可以勾畫使用情況嗎? – Santhos

+0

因此......如果你的掛斷是每次寫出這兩行的時間過多,爲什麼不把它解壓到一個單獨的方法呢? – DrewJordan

+0

問題是應用程序是模塊化的。我們有大約100個裝配 - 所以我們必須在每個裝配中重新定義這種方法... – LionAM

回答

1

你可以考慮Observer Pattern的一些變化,比如Third-party Connect,它使用事件來顯示和記錄消息。它涉及到提取以下到您的所有組件中使用一個低級別的共享DLL:

public class UIMessageEventArgs : EventArgs 
{ 
    public string Key { get; private set; } 
    public Func<CultureInfo, string> GetString { get; private set; } 

    public UIMessageEventArgs(string key, Func<CultureInfo, string> getString) 
    { 
     if (key == null || getString == null) 
      throw new ArgumentNullException(); 
     this.Key = key; 
     this.GetString = getString; 
    } 
} 

public interface IUIMessageService 
{ 
    event EventHandler<UIMessageEventArgs> OnMessage; 

    void ShowMessage(object sender, string key, Func<CultureInfo, string> getString); 
} 

public sealed class UIMessageService : IUIMessageService 
{ 
    static UIMessageService() { instance = new UIMessageService(); } 

    static UIMessageService instance; 

    public static UIMessageService Instance { get { return instance; } } 

    UIMessageService() { } 

    #region IUIMessageService Members 

    public event EventHandler<UIMessageEventArgs> OnMessage; 

    public void ShowMessage(object sender, string key, Func<CultureInfo, string> getString) 
    { 
     if (getString == null) 
      throw new ArgumentNullException("getString"); 
     if (key == null) 
      throw new ArgumentNullException("key"); 
     var onMessage = OnMessage; 
     if (onMessage != null) 
      onMessage(sender, new UIMessageEventArgs(key, getString)); 
    } 

    #endregion 
} 

public static class UIMessageExtensions 
{ 
    public static void ShowMessage(this ResourceManager resourceManager, string key) 
    { 
     if (resourceManager == null) 
      throw new ArgumentNullException("resourceManager"); 
     if (key == null) 
      throw new ArgumentNullException("key"); 
     UIMessageService.Instance.ShowMessage(resourceManager, key, c => resourceManager.GetString(key, c)); 
    } 
} 

我發的消息服務單身,因爲我懷疑你所有的聽衆都會是單身。

然後在你的數控代碼,你只需撥打:

Resources.ResourceManager.ShowMessage("Key"); 

另外在C#6.0,你應該能夠使用nameof,而不是硬編碼的屬性名稱字符串:

Resources.ResourceManager.ShowMessage(nameof(Resources.Key)); 

通過如果您正在實現CAD/CAM相關的宏功能,您可以考慮記錄密鑰字符串而不是不變信息 - 然後將該不變信息作爲註釋添加到宏中。這樣,即使在不變的語言中,宏也不會因爲對消息文本的修改(拼寫修正)而意外失效。

如果在某些時候您需要能夠將用戶的響應錄製到可選(根據宏作者的需要)用於交互式響應的宏中,則可以擴展UIMessageService模型以允許委託人返回通過消息鍵進行的用戶響應被注入。

+0

這真是一個有趣的答案。我特別喜歡運算符的名稱(沒有注意到它已經存在 - 但是現在我們仍然堅持使用C#5.0)。 – LionAM