开发者

ASP.NET localization: Changing resources without restarting the application?

I have the requirement that the end-user can change localized resources and the changes should be visible in the application without the need to restart the application.

Update to clarify开发者_StackOverflow the scenario:

I am talking about changing the localized resources at runtime. Lets say I have a typo in the german translation of a page. Then some admin-user should have the possibility to change that typo at runtime. There should be no need for a redeployment or restart in order for this change to be reflected in the UI.

I am using ASP.NET MVC3.

What options do I have?

I have been looking into writing a custom ResourceProvider that loads resources from the database.

This seems not too much effort, however so far I pointed out two drawbacks:

  • It is not working with the DataAnnotations that are used for convenient validation in MVC3 (DataAnnotations work with a ErrorMessageResourceType parameter, which only works with compiled resources)
  • We basically have to provide our own tooling around managing resources (like translating etc.) which is a pity, since there are a lot of tools for this that work with resx-files.

What are the other options? Would manipulation of the deployed resx-files at runtime be an option?

But I suspect that the application is automatically "restarted" when it detects those changes: I suspect ASP.NET realizes that the resx-files have changed, it then recycles the application-pool and compiles the new resx-files on the fly.

Is this correct? Is there any way around this?

I have not yet looked into compiling the resources into satellite assemblies before deployment. Is this even a recommended scenario for web applications?

But even with compiled satellite assemblies I suspect that ASP.NET restarts the application, when those assemblies are changed on the fly. Is this correct?

I would be interested in any experience in how the original requirement can be satisfied? And I would be interested in any comments about the options I have mentioned above.


DataAnnotations accept a ErrorMessageResourceType which tells the ValidationAttrributes where to access resources. You can pass this as follows:

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

By creating a type for this parameter with static properties for each key you can create an implementation that loads resources from a database or other implementation. You could then combine this with a dynamic object for DRY and move the implementation into TryGetMember. Potentially then use T4 templates to generate the statics from your database at compile time, ending up with this:

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;
    }
}

Of course it would be perfect if resources weren't static properties.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜