patterns - singleton template c#
¿Cómo implementar un singleton en C#? (14)
El singleton estático es más o menos un patrón anti si quieres un diseño ligeramente acoplado. Evitar si es posible, y a menos que este sea un sistema muy simple, recomendaría echar un vistazo a uno de los muchos marcos de inyección de dependencia disponibles, como http://ninject.org/ o http://code.google.com/p / autofac / .
Para registrar / consumir un tipo configurado como singleton en autofac, debería hacer algo como lo siguiente:
var builder = new ContainerBuilder()
builder.Register(typeof(Dependency)).SingletonScoped()
builder.Register(c => new RequiresDependency(c.Resolve<Dependency>()))
var container = builder.Build();
var configured = container.Resolve<RequiresDependency>();
La respuesta aceptada es una solución terrible, por cierto, al menos verifique a los chats que realmente implementaron el patrón.
¿Cómo implemento el patrón singleton en C #? Quiero poner mis constantes y algunas funciones básicas en él, ya que las utilizo en todas partes de mi proyecto. Quiero que sean ''globales'' y no es necesario vincularlos manualmente a cada objeto que creo.
Ignorando la cuestión de si debe o no usar el patrón de Singleton, que se ha discutido en otro lugar, implementaría un singleton como este:
/// <summary>
/// Thread-safe singleton implementation
/// </summary>
public sealed class MySingleton {
private static volatile MySingleton instance = null;
private static object syncRoot = new object();
/// <summary>
/// The instance of the singleton
/// safe for multithreading
/// </summary>
public static MySingleton Instance {
get {
// only create a new instance if one doesn''t already exist.
if (instance == null) {
// use this lock to ensure that only one thread can access
// this block of code at once.
lock (syncRoot) {
if (instance == null) {
instance = new MySingleton();
}
}
}
// return instance where it was just created or already existed.
return instance;
}
}
/// <summary>
/// This constructor must be kept private
/// only access the singleton through the static Instance property
/// </summary>
private MySingleton() {
}
}
Lo que estás describiendo son meramente funciones estáticas y constantes, no un singleton. El patrón de diseño singleton (que rara vez se necesita) describe una clase que se crea una instancia, pero solo una vez, automáticamente, cuando se utiliza por primera vez.
Combina la inicialización diferida con una comprobación para evitar la creación de instancias múltiples. Solo es realmente útil para las clases que envuelven algún concepto que es físicamente singular, como un envoltorio alrededor de un dispositivo de hardware.
Las constantes estáticas y las funciones son solo eso: código que no necesita una instancia en absoluto.
Pregúntese esto: "¿Se romperá esta clase si hay más de una instancia de la misma?" Si la respuesta es no, no necesita un singleton.
Realmente puede simplificar una implementación singleton, esto es lo que uso:
internal FooService() { }
static FooService() { }
private static readonly FooService _instance = new FooService();
public static FooService Instance
{
get { return _instance; }
}
Si solo está almacenando algunos valores globales y tiene algunos métodos que no necesitan estado, no necesita un código único. Simplemente haga que la clase y sus propiedades / métodos estén estáticos.
public static class GlobalSomething
{
public static int NumberOfSomething { get; set; }
public static string MangleString( string someValue )
{
}
}
Singleton es más útil cuando tienes una clase normal con estado, pero solo quieres una de ellas. Los enlaces que otros han proporcionado deberían ser útiles para explorar el patrón de Singleton.
hmmm ... Pocas constantes con funciones relacionadas ... ¿no sería mejor lograrlo a través de enums? Sé que puede crear una enumeración personalizada en Java con métodos y todo, lo mismo debe ser posible en C #, si no se admite directamente, entonces se puede hacer con singleton de clase simple con constructor privado.
Si sus constantes están semánticamente relacionadas, debe considerar las enumeraciones (o concepto equivalente) obtendrá todas las ventajas de las variables estáticas const + podrá utilizar para su ventaja la comprobación de tipos del compilador.
Mi 2 centavo
Singleton != Global
. Parece que está buscando la palabra clave static
.
Al ocultar el constructor público, agregar un campo estático privado para contener esta única instancia y agregar un método de fábrica estático (con inicializador lento) para devolver esa instancia única
public class MySingleton
{
private static MySingleton sngltn;
private static object locker;
private MySingleton() {} // Hides parameterless ctor, inhibits use of new()
public static MySingleton GetMySingleton()
{
lock(locker)
return sngltn?? new MySingleton();
}
}
Hmm, todo esto parece un poco complejo.
¿Por qué necesita un marco de inyección de dependencia para obtener un singleton? Usar un contenedor IOC está bien para una aplicación empresarial, (siempre y cuando no se use en exceso, por supuesto), pero, ah, el chico solo quiere saber más acerca de cómo implementar el patrón.
¿Por qué no siempre entusiastamente crear instancias, luego proporcionar un método que devuelve la estática, la mayoría del código escrito arriba y luego desaparece. Sigue el viejo adagio C2: DoTheSimplestThingThatPodiblyPortiblyWork ...
Personalmente, optaría por un marco de inyección de dependencias, como Unity, todos ellos pueden configurar elementos únicos en el contenedor y mejorarían el acoplamiento pasando de una dependencia de clase a una dependencia de interfaz.
public class Globals
{
private string setting1;
private string setting2;
#region Singleton Pattern Implementation
private class SingletonCreator
{
internal static readonly Globals uniqueInstance = new Globals();
static SingletonCreator()
{
}
}
/// <summary>Private Constructor for Singleton Pattern Implementaion</summary>
/// <remarks>can be used for initializing member variables</remarks>
private Globals()
{
}
/// <summary>Returns a reference to the unique instance of Globals class</summary>
/// <remarks>used for getting a reference of Globals class</remarks>
public static Globals GetInstance
{
get { return SingletonCreator.uniqueInstance; }
}
#endregion
public string Setting1
{
get { return this.setting1; }
set { this.setting1 = value; }
}
public string Setting2
{
get { return this.setting2; }
set { this.setting2 = value; }
}
public static int Constant1
{
get { reutrn 100; }
}
public static int Constat2
{
get { return 200; }
}
public static DateTime SqlMinDate
{
get { return new DateTime(1900, 1, 1, 0, 0, 0); }
}
}
Me gusta este patrón, aunque no impide que alguien cree una instancia no única. A veces puede ser mejor educar a los desarrolladores en su equipo sobre el uso de la metodología correcta en lugar de ir a longitudes heroicas para evitar que algunos nudillos utilicen su código de la manera incorrecta ...
public class GenericSingleton<T> where T : new()
{
private static T ms_StaticInstance = new T();
public T Build()
{
return ms_StaticInstance;
}
}
...
GenericSingleton<SimpleType> builder1 = new GenericSingleton<SimpleType>();
SimpleType simple = builder1.Build();
Esto le dará una única instancia (instanciado de la manera correcta) y será efectivamente flojo, porque el constructor estático no se llama hasta que se llame a Build ().
Le recomendaría que lea el artículo Explorando el patrón de diseño Singleton disponible en MSDN. Detalla las características del marco que hacen que el patrón sea simple de implementar.
Como un aparte, verificaría la lectura relacionada en SO con respecto a Singletons .
Los singleton solo tienen sentido si ambas condiciones son verdaderas:
- El objeto debe ser global
- Solo debe existir una sola instancia del objeto
Tenga en cuenta que el # 2 no significa que le gustaría que el objeto solo tenga una sola instancia; si ese es el caso, simplemente ejecútelo solo una vez, significa que debe (como en, es peligroso que esto no sea cierto) solo ser una sola instancia
Si quieres global, solo crea una instancia global de algún objeto (no un objeto) (o hazlo estático o lo que sea). Si solo quieres una instancia, de nuevo, static es tu amigo. Además, simplemente crea una instancia de un solo objeto.
Esa es mi opinión de todos modos.