【问题标题】:ASP.NET localization: Changing resources without restarting the application?ASP.NET 本地化:更改资源而不重新启动应用程序?
【发布时间】:2011-08-26 16:09:32
【问题描述】:

我要求最终用户可以更改本地化资源,并且更改应该在应用程序中可见,而无需重新启动应用程序。

更新以澄清场景:
我说的是在运行时更改本地化资源。假设我在页面的德语翻译中有错字。然后一些管理员用户应该有可能在运行时更改该错字。无需重新部署或重新启动即可将此更改反映在 UI 中。

我正在使用 ASP.NET MVC3。

我有什么选择?

我一直在考虑编写一个从数据库加载资源的custom ResourceProvider
这似乎没有太多的努力,但是到目前为止我指出了两个缺点:

  • 它不适用于在 MVC3 中用于方便验证的 DataAnnotations(DataAnnotations 与 ErrorMessageResourceType 参数一起使用,该参数仅适用于已编译的资源)
  • 我们基本上必须提供自己的工具来管理资源(如翻译等),这很遗憾,因为有很多工具可以处理 resx 文件。

还有哪些其他选择?是否可以在运行时操作已部署的 resx 文件?
但我怀疑应用程序在检测到这些更改时会自动“重新启动”:我怀疑 ASP.NET 意识到 resx 文件已更改,然后它回收应用程序池并即时编译新的 resx 文件。
它是否正确?有没有办法解决这个问题?

我还没有考虑在部署之前将资源编译到附属程序集中。这甚至是 Web 应用程序的推荐方案吗?
但即使使用已编译的附属程序集,我怀疑 ASP.NET 会在这些程序集即时更改时重新启动应用程序。这是正确的吗?

我对如何满足原始要求感兴趣? 我会对我上面提到的选项的任何 cmets 感兴趣。

【问题讨论】:

  • 你试过this answer提出的UpdatableResXResourceProvider了吗?
  • 对不起,我错过了理解,在运行时更改现有资源我认为您唯一的选择是自定义资源提供程序,但我还没有看到任何干净的解决方案来解决 DataAnnotations 问题而不诉诸自定义注释.
  • 我有办法做到这一点,但前提是你的资源密钥是固定的?

标签: asp.net asp.net-mvc-3 localization


【解决方案1】:

DataAnnotations 接受一个ErrorMessageResourceType,它告诉 ValidationAttrributes 在哪里访问资源。您可以按如下方式传递:

[Required(
    ErrorMessageResourceType = typeof(DynamicResources), 
    ErrorMessageResourceName = "ResourceKey")]
public string Username { get; set; }

通过为这个参数创建一个带有每个键的静态属性的类型,您可以创建一个从数据库或其他实现加载资源的实现。然后,您可以将其与 DRY 的动态对象结合起来,并将实现移至 TryGetMember。然后可能在编译时使用 T4 模板从您的数据库中生成静态数据,最终得到以下结果:

public class DynamicResources : DynamicObject
{
    // move these into partial and generate using T4
    public static string MyResource
    {
        get { return Singleton.MyResource; }
    }

    public static string MyOtherResource
    {
        get { return Singleton.MyOtherResource; }
    }

    // base implementation to retrieve resources
    private static dynamic singleton;

    private static dynamic Singleton
    {
        get { return singleton ?? (singleton = new DynamicResources()); }
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        // some logic here to look up resources
        result = GetResourceKeyFromDatabase(binder.Name);
        return true;
    }
}

当然,如果资源不是静态属性就完美了。

【讨论】:

  • 此解决方案不适用于问题中链接的 MSDN 中的自定义资源提供程序方法。注释期望 ErrorMessageResourceType 具有带有 ErrorMessageResourceName 的静态属性。当您实现动态资源查找时,情况并非如此。
  • 好的,有一个替代方案,依赖于固定的资源键,但是要在您的应用程序中使用资源,无论如何它们都需要预定义。
  • 谢谢!这可能是我能得到的最好的了。不过,在我采用该解决方案之前,我会研究其他验证策略......
猜你喜欢
  • 1970-01-01
  • 2015-04-01
  • 1970-01-01
  • 2013-11-06
  • 1970-01-01
  • 1970-01-01
  • 2011-04-03
  • 2011-03-08
  • 1970-01-01
相关资源
最近更新 更多