Hm, vous pouvez vérifier this sur.
En bref, ce que vous voulez faire est, injecter une source "culture" dans votre objet de contenu localisé. Considérons l'exemple suivant,
// your public global settings singleton, no big surprises here
// except possibly thread safe locking [shrug] if you are singlethreaded
// you can simplify this model further
public class GlobalSettings
{
// singleton synchronization and instance reference
private static readonly object _instanceSyncRoot = new object();
private static readonly GlobalSettings _instance = null;
// instance-based synchronization and values
private readonly object _syncRoot = new object();
private string _cultureName = string.Empty;
// gets public static instance
public static GlobalSettings Current
{
get
{
lock (_instanceSyncRoot)
{
if (_instance == null)
{
_instance = new GlobalSettings();
}
}
return _instance;
}
}
// gets public culture name
public string CultureName
{
get { lock (_syncRoot) { return _cultureName; } }
set { lock (_syncRoot) { _cultureName = value; } }
}
// private constructor to re-inforce singleton semantics
private GlobalSettings() { }
}
Ainsi, un certain nombre de choses. Typiquement singletons comme celui-ci sont mal vu - ils sont très pratiques! mais comme vous le faites remarquer, conduire à un couplage étroit entre les composants fonctionnels et la configuration.
Si vous souhaitez déplacer loin de ce couplage étroit, tout en préservant ce qui existe, vous avez quelques options, la plus facile étant
// define a general-purpose settings interface, i do not much
// care for refactor tools, but you may use re-sharper or built in
// refactor components to "extract" those properties from global
// settings that you need. here we pull out culture name only,
public interface ISettings
{
// gets culture name from underlying settings implementation
string CultureName { get; }
}
public class LocalizedContent
{
public string CultureName { get; set; }
public LocalizedContent (ISettings settings)
{
CultureName = settings.CultureName;
}
}
Si vous êtes en mesure de modifier GlobalSettings
singleton,
// public singleton is now an implementation of a "loosely coupled
// component" called ISettings
public class GlobalSettings : ISettings { ... }
// elsewhere in code
public LocalizedContent GetLocalizedContent()
{
LocalizedContent content = new LocalizedContent (GlobalSettings.Instance);
return content;
}
Si vous n'êtes pas en mesure de modifier GlobalSettings
singleton,
// wrapper class for global settings singleton
public class Settings : ISettings
{
public string CultureName
{
get { return GlobalSettings.Instance.CultureName; }
}
}
// elsewhere in code
public LocalizedContent GetLocalizedContent()
{
LocalizedContent content = new LocalizedContent (new Settings());
return content;
}
Maintenant, LocalizedContent
n'est plus étroitement couplé à GlobalSettings
singleton. En fait, toute implémentation de ISettings
satisfera sa dépendance de constructeur.
Si vos dépendances sont aussi simples comme une chaîne ou deux, cela peut être exagéré.Cependant, si vous avez d'autres composants complexes dépendant de ce singleton global, cette approche peut être pour vous :)
Essayez-vous d'éviter le couplage à 'GlobalSettings.Current' (c'est-à-dire au fait que GlobalSettings dans l'implémentation actuelle, cette classe est un singleton etc.) ou à GlobalSettings? – mjv
Seule la propriété GlobalSettings.Current. Je ne suis pas capable de se moquer des GlobalSettings "Current" statiques dans mes méthodes de test unitaires. –
si vous essayez de tester un singleton unitaire puis vérifiez cela http://stackoverflow.com/questions/1601073/nunit-mocking-not-working-for-singleton-method/1601438#1601438. Je résume dans ma réponse ci-dessous. –