Is localization using the DI framework a good idea?

I am working on a web application that I need to localize and internationalize. It occurred to me that I could do this using the dependency injection infrastructure. Let's say I declare the ILocalResources interface (using C # for this example, but this is not very important):

interface ILocalResources {
    public string OkString { get; }
    public string CancelString { get; }
    public string WrongPasswordString { get; }
    ...
}

and create implementations of this interface, one for each language that I need to support. Then I would install my DI infrastructure to create the correct implementation, statically or dynamically (e.g. based on my preferred browser of my preferred language).

Is there any reason why I should not use the DI framework for this kind of thing? The only objection I could find is that this might be a bit overkill, but if I use the DI framework in my web application anyway, would I use it for internationalization too?

+5
source share
3 answers

If you cannot use the existing resource infrastructure (for example, built into ASP.Net) and you have to create your own, I assume that at some point you will need to provide services that provide localized resources.

DI . , . ?

DI , : " CRM-, DI, DI ".

, , DI , IMO , .

+2

DI , , , IM- DI. , ILocalResources. , , , , , , . /, . , .

// ( - ), . - :

public interface ILocalResources
{
    string GetStringResource(string key);
    string GetStringResource(string key, CultureInfo culture);
}

. , , , , , , .

:

public abstract class LocalResources
{
    public string OkMessage { get { return this.GetString("OK"); } }
    public string CancelMessage { get { return this.GetString("Cancel"); } }
    ...

    protected abstract string GetStringResource(string key, 
        CultureInfo culture);

    private string GetString(string key)
    {
        Culture culture = CultureInfo.CurrentCulture;

        string resource = GetStringResource(key, culture);

        // When the resource is not found, fall back to the neutral culture.
        while (resource == null && culture != CultureInfo.InvariantCulture)
        {
            culture = culture.Parent;
            resource = this.GetStringResource(key, culture);
        }

        if (resource == null) throw new KeyNotFoundException(key);

        return resource;
    }
}

:

public sealed class SqlLocalResources : LocalResources
{
    protected override string GetStringResource(string key, 
        CultureInfo culture)
    {
        using (var db = new LocalResourcesContext())
        {
            return (
                from resource in db.StringResources
                where resource.Culture == culture.Name
                where resource.Key == key
                select resource.Value).FirstOrDefault();
        }
    }
}

, , . DI, :

container.RegisterSingleton<LocalResources>(new SqlLocalResources());

LocalResources , , , , :

public sealed class CachedLocalResources : LocalResources
{
    private readonly Dictionary<CultureInfo, Dictionary<string, string>> cache =
        new Dictionary<CultureInfo, Dictionary<string, string>>();
    private readonly LocalResources decoratee;

    public CachedLocalResources(LocalResources decoratee) { this.decoratee = decoratee; }

    protected override string GetStringResource(string key, CultureInfo culture) {
        lock (this.cache) {
            string res;
            var cultureCache = this.GetCultureCache(culture);
            if (!cultureCache.TryGetValue(key, out res)) {
                cultureCache[key] = res= this.decoratee.GetStringResource(key, culture);
            }                
            return res;
        }
    }

    private Dictionary<string, string> GetCultureCache(CultureInfo culture) {
        Dictionary<string, string> cultureCache;
        if (!this.cache.TryGetValue(culture, out cultureCache)) {
            this.cache[culture] = cultureCache = new Dictionary<string, string>();
        }
        return cultureCache;
    }
}

:

container.RegisterSingleton<LocalResources>(
    new CachedLocalResources(new SqlLocalResources()));

, , , WeakReference - - . , .

, .

+6

The only drawback that I see is that for any “resources” update you will have to recompile the assembly containing the resources. And depending on your project, this drawback may be good advice only for using the DI infrastructure to solve any ResourceService, and not for the values ​​themselves.

+2
source

All Articles