2015-10-22 22 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