J'ai créé une classe qui est un croisement entre une singleton (fifth version) et une fabrique (dépendance injectable). Appelez cela une "Mono-Factory"? Il fonctionne, et ressemble à ceci:Comment retarder l'initialisation statique dans une propriété
public static class Context
{
public static BaseLogger LogObject = null;
public static BaseLogger Log
{
get
{
return LogFactory.instance;
}
}
class LogFactory
{
static LogFactory() { }
internal static readonly BaseLogger instance = LogObject ?? new BaseLogger(null, null, null);
}
}
//USAGE EXAMPLE:
//Optional initialization, done once when the application launches...
Context.LogObject = new ConLogger();
//Example invocation used throughout the rest of code...
Context.Log.Write("hello", LogSeverity.Information);
L'idée est pour l'usine mono pourrait être étendu pour traiter plus d'un élément (par exemple plus d'un enregistreur). Mais j'aurais aimé avoir fait l'aspect mono-usine comme ceci:
public static class Context
{
private static BaseLogger LogObject = null;
public static BaseLogger Log
{
get
{
return LogFactory.instance;
}
set
{
LogObject = value;
}
}
class LogFactory
{
static LogFactory() { }
internal static readonly BaseLogger instance = LogObject ?? new BaseLogger(null, null, null);
}
}
Le ne fonctionne pas, parce que le moment la propriété Log est touché (par un appel setter) provoque le chemin de code lié à le getter doit être exécuté ... ce qui signifie que les données "instance" internes de LogFactory sont toujours définies sur le BaseLogger (le réglage de "LogObject" est toujours trop tard!).
Y a-t-il une décoration ou une autre astuce que j'utiliserais pour que le chemin "get" de la propriété Log soit paresseux pendant que le chemin set est invoqué?
@Ruben: J'ai supprimé ma réponse parce que je pense que c'était trompeur et/ou tout simplement faux. +1 pour votre suggestion finale, ce qui rend beaucoup plus évident ce que fait le code. – LukeH
@Ruben: Si le CLR peut choisir arbitrairement la séquence d'initialisation, comme vous le suggérez, cela signifie-t-il que la cinquième version de Jon Skeet est rompue (http://www.yoda.arachsys.com/csharp/singleton.html) ? Quoi qu'il en soit, je vais probablement modifier mon code, peut-être pour lancer une exception après le premier "set", ou je vais utiliser ce que vous avez proposé. –
Non, je pense que Jon Skeet a raison. Mais notez qu'il n'y a pas de dépendance dans son code pour tout ordre, * et * la classe Nested dans son exemple n'utilise aucune statique de la classe parente. Je pense que j'ai besoin d'ajuster quelque peu ma réponse, car je n'ai pas pris en compte certains des inconvénients de 'beforefieldinit'. – Ruben