patterncsharpMinor
ResourceManager Singleton
Viewed 0 times
singletonresourcemanagerstackoverflow
Problem
As I understand creating lots of resource managers in C# may be a bad idea so I thought that the best thing to do would be to create a singleton for this.
However, I'm not 100% if this is a good idea, or if this is a good way to implement it.
The main thing about the implementation I am unsure about is making the "Instance" private and creating number of static functions to expose the functionality. This means I can call Local.GetString instead of Local.Instance.GetString which is less clunky. I have not seen any singleton implementation which does this so I wonder if there is some problem with it.
I am also using locking but I don't see how to get around that so that is probably fine.
```
public class Locale
{
// using System.Lazy -- see http://msdn.microsoft.com/en-us/library/dd642331.aspx
static readonly Lazy lazy = new Lazy(() => new Locale(), true);
static readonly object _locker = new object();
Dictionary _managers;
public Locale()
{
_managers = new Dictionary();
}
static Locale Instance { get { return lazy.Value; } }
public static ResourceManager GetManager(Type resourceType)
{
return Instance.GetResourceManager(resourceType);
}
public static string GetString(Type resourceType, string name)
{
var manager = Instance.GetResourceManager(resourceType);
return manager.GetString(name);
}
public static string GetString(Type resourceType, string name, CultureInfo culture)
{
var manager = Instance.GetResourceManager(resourceType);
return manager.GetString(name, culture);
}
public static object GetObject(Type resourceType, string name)
{
var manager = Instance.GetResourceManager(resourceType);
return manager.GetObject(name);
}
public static object GetObject(Type resourceType, string name, CultureInfo culture)
{
var manager = Instance.GetResourceManager(resourceType);
return manager.GetObjec
However, I'm not 100% if this is a good idea, or if this is a good way to implement it.
The main thing about the implementation I am unsure about is making the "Instance" private and creating number of static functions to expose the functionality. This means I can call Local.GetString instead of Local.Instance.GetString which is less clunky. I have not seen any singleton implementation which does this so I wonder if there is some problem with it.
I am also using locking but I don't see how to get around that so that is probably fine.
```
public class Locale
{
// using System.Lazy -- see http://msdn.microsoft.com/en-us/library/dd642331.aspx
static readonly Lazy lazy = new Lazy(() => new Locale(), true);
static readonly object _locker = new object();
Dictionary _managers;
public Locale()
{
_managers = new Dictionary();
}
static Locale Instance { get { return lazy.Value; } }
public static ResourceManager GetManager(Type resourceType)
{
return Instance.GetResourceManager(resourceType);
}
public static string GetString(Type resourceType, string name)
{
var manager = Instance.GetResourceManager(resourceType);
return manager.GetString(name);
}
public static string GetString(Type resourceType, string name, CultureInfo culture)
{
var manager = Instance.GetResourceManager(resourceType);
return manager.GetString(name, culture);
}
public static object GetObject(Type resourceType, string name)
{
var manager = Instance.GetResourceManager(resourceType);
return manager.GetObject(name);
}
public static object GetObject(Type resourceType, string name, CultureInfo culture)
{
var manager = Instance.GetResourceManager(resourceType);
return manager.GetObjec
Solution
The main thing about the implementation I am unsure about is making the "Instance" private and creating number of static functions to expose the functionality. This means I can call Local.GetString instead of Local.Instance.GetString which is less clunky. I have not seen any singleton implementation which does this so I wonder if there is some problem with it.
I don't think there's a problem with that. Your static methods are only doing things which otherwise the calling code would do.
I am also using locking but I don't see how to get around that so that is probably fine.
If your code is single-threaded then you don't need locking at all.
If your code is multi-threaded, perhaps you can construct the singleton before the multi-threading starts: for example by calling a static Locale.CreateInstance method in your program's Main (or from Application_Start if your code is ASP.NET).
If your code is multi-threaded then the non-static Locale methods must also be thread-safe: including your Locale._managers dictionary accessors, and your ResourceManager methods. ResourceManager is already documented as a thread-safe class.
An alternative to the explicit
Stylistically, some people recommend auto-declaring variables types as
... or simply ...
I don't think there's a problem with that. Your static methods are only doing things which otherwise the calling code would do.
I am also using locking but I don't see how to get around that so that is probably fine.
If your code is single-threaded then you don't need locking at all.
If your code is multi-threaded, perhaps you can construct the singleton before the multi-threading starts: for example by calling a static Locale.CreateInstance method in your program's Main (or from Application_Start if your code is ASP.NET).
If your code is multi-threaded then the non-static Locale methods must also be thread-safe: including your Locale._managers dictionary accessors, and your ResourceManager methods. ResourceManager is already documented as a thread-safe class.
An alternative to the explicit
lock you implemented is to use the ConcurrentDictionary class instead of Dictionary, specifically its GetOrAdd method, something like:ResourceManager GetResourceManager(Type resourceType)
{
Func valueFactory =
resourceType => new ResourceManager(resourceType);
return managers.GetOrAdd(resourceType, valueFactory);
}Stylistically, some people recommend auto-declaring variables types as
var for example ...var valueFactory = resourceType => new ResourceManager(resourceType);... or simply ...
ResourceManager GetResourceManager(Type resourceType)
{
return managers.GetOrAdd(resourceType, resourceType => new ResourceManager(resourceType));
}Code Snippets
ResourceManager GetResourceManager(Type resourceType)
{
Func<Type, ResourceManager> valueFactory =
resourceType => new ResourceManager(resourceType);
return managers.GetOrAdd(resourceType, valueFactory);
}var valueFactory = resourceType => new ResourceManager(resourceType);ResourceManager GetResourceManager(Type resourceType)
{
return managers.GetOrAdd(resourceType, resourceType => new ResourceManager(resourceType));
}Context
StackExchange Code Review Q#39735, answer score: 3
Revisions (0)
No revisions yet.