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.
精彩评论