2010-04-26 7 views
2

Je veux écrire un singleton générique avec un constructeur externe. En d'autres termes, le constructeur peut être modifié. J'ai 2 designs dans mon esprit mais je ne sais pas s'ils sont pratiques ou non.Générique Singleton abstrait avec un constructeur personnalisé en C#

  • La première est d'appliquer la classe dérivée constructeur d'être non-public, mais je ne sais pas s'il y a un moyen de celui-ci?

  • Deuxième est d'utiliser un délégué et l'appeler dans le constructeur?

Il ne s'agit pas nécessairement d'un constructeur. La raison pour laquelle j'ai choisi le constructeur personnalisé est de faire des initialisations personnalisées.

Aucune suggestion ne serait appréciée :)

+0

Vous voulez dire, le constructeur peut être modifié pour travailler contre différents types? –

+3

Ma suggestion serait d'essayer de rester loin de Singletons. Ils ont tendance à devenir un pita majeur lorsque vous commencez à tester votre code. Jetez un oeil ici pour certains hors des pièges lorsque vous travaillez avec Singletons. http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/ –

+0

@this. __curious_geek Oui exactement :) – Heka

Répondre

-1

Ok, voici ma solution. J'ai utilisé la réflexion pour vérifier les constructeurs publics. S'il vous plaît commenter s'il me manque quelque chose.

 public abstract class Singleton<T> where T: class 
     { 

     private static volatile T _instance; 

     private static object _lock = new object(); 

     protected Singleton() 
     { 
      ConstructorInfo[] constructorPublic = typeof(T).GetConstructors(BindingFlags.Public | BindingFlags.Instance); 
      if (constructorPublic.Length > 0) 
      { 
      throw new Exception(String.Format("{0} has one or more public constructors so the property cannot be enforced.", 
               typeof(T).FullName)); 
      } 
     } 

     public static T Instance 
     { 
      get 
      { 
      if (_instance == null) 
      { 
       lock (_lock) 
       { 
       if (_instance == null) 
       { 
        ConstructorInfo constructorNonPublic = null; 

        try 
        { 
        constructorNonPublic = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, 
                  new Type[0], null); 
        } 
        catch (Exception e) 
        { 
        throw e; 
        } 

        if (constructorNonPublic == null || constructorNonPublic.IsAssembly) 
        { 
        throw new Exception(String.Format("A private or protected constructor is missing for {0}", 
                 typeof (T).Name)); 
        } 

        _instance = constructorNonPublic.Invoke(null) as T; 
       } 
       } 
      } 

      return _instance; 
      } 
     } 
     } 
2

Cela ne sonne pas bien. Je me demande si la configuration par IoC va être plus simple et plus facile à supporter. La plupart des conteneurs IoC prendront en charge la réutilisation des objets de type singeton et l'initialisation configurable en. Sans l'effet de bord rendant votre objet tout moche.

Singleton est agréable, mais est largement surutilisé. Bien sûr, je suis aussi coupable que le prochain geek ...

+0

Je ne suis pas très familier avec IoC. Pouvez-vous donner un exemple? – Heka

+1

@Heka - regardez l'exemple de "logger" ici: http://www.pnpguidance.net/News/StructureMapTutorialDependencyInjectionIoCNET.aspx –

+2

Les singletons sont comme la restauration rapide; rapide et pratique, mais décidément malsain à long terme. –

2

Voici une façon de le faire, Si jamais je pouvais vous aider.

public abstract class MySingletonBase<T> 
    where T : class 
{ 
    protected MySingletonBase() 
    { 
    } 

    // All other functions that will be inherited. 
} 

public class MySingleton<T> : MySingletonBase<T> 
    where T : class 
{ 
    private static MySingleton<T> instance; 
    protected MySingleton() 
    { 
    } 

    public static MySingleton<T> GetInstance() 
    { 
     if (instance == null) 
     { 
      instance = new MySingleton<T>(); 
     } 
     return instance; 
    } 
} 
+0

Oui c'est une bonne solution mais je préfère quelque chose de plus simple à utiliser. Et je pense que j'ai trouvé quelque chose :) Laissez-moi poster le code. – Heka

0

Vous pouvez essayer d'utiliser un motif d'usine pour créer une fabrique singleton, qui produira les singletons concrets.

2

Ceci est mon point, en utilisant .NET 4

public class Singleton<T> where T : class, new() 
    { 
     Singleton(){} 

     private static readonly Lazy<T> instance = new Lazy<T>(()=> new T()); 

     public static T Instance { get { return instance.Value; } } 
    }