IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

type générique désignant le type de la classe héritée.


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    maa
    maa est déconnecté
    Membre éclairé
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Par défaut type générique désignant le type de la classe héritée.
    Bonjour,

    J'ai une série de classes qui héritent les une des autres. Je voudrais que ces classes soient instanciables depuis une méthode statique, un peu à la manière d'un singleton, sauf que je stock mes instances dans un Dictionary<int, T> où la clé est un id passé en paramètre à la méthode statique et T le type de la classe. J'aimerais déclarer cette méthode static et ce dictionary seulement dans une classe ancêtre. Par exemple, j'ai :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    public abstract class MyClass1<T>  where T : new()
    {
    	protected Dictionary<int, T> _Instances = new Dictionaryint, T>();		
     
    	public static T GetInstance(int id)
    	{	
    		T result;
    		if (!_Instances.TryGetValue(id, out result))
    		{
    			result = new T();
    			_Instances.Add(id, result);
    		}
    		return result;		
    	}
    }
     
    public class MyClass2 : MyClass1<MyClass2>
    {
    }
     
     
    public class MyClass3 : MyClass2
    {
    }
    ...
     
    public class MyClassN : MyClassN-1
    {
    }
    Ce code fonctionne jusqu'à MyClass2 car on hérite de MyClass1<MyClass2> et donc T dans MyClass1<T> désigne bien MyClass2.
    Par contre dans MyClass3, qui hérite de MyClass2, le type T des membre de de MyClass1<T> est toujours MyClass2 alors que je voudrais que ça soit MyClass3.

    En clair je cherche un moyen dans ma classe de base de dire que T désigne le type de la dernière classe héritée, ceci afin d'éviter de répéter les membre _Instances et GetInstance() dans chacune des classes.

    Auriez-vous une solution/un design pattern à me proposer ?

    Merci d'avance.

  2. #2
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Par défaut
    Déjà, tel qu'il est ton code ne peut pas compiler car _Instances n'est pas static.

    Sinon, je ne vois pas de solution à ton problème en gardant tel quel, (avec la méthode GetInstance avec cette signature) car, par définition, une méthode static est ... statique, et, en clair, on ne peut pas savoir dans la méthode quelle classe héritée est l'appelante (bon, il y aurait peut être un moyen via les StackFrame et la réflection mais ce serait assez sale, en examinant d'où vient l'appel de méthode - et ne marcherait que que si le GetInstance est appelé depuis la classe elle-même ce qui n'est, bien évidemment, pas le but je suppose).

    Je te suggère plutôt de revoir le design et d'envisager de passer par un DP factory, par exemple.

    Une autre possibilité est de passer un paramètre Type à ton GetInstance, comme ça par exemple :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public static T GetInstance(Type instanceType, int id)
        {    
            T result;
            if (!_Instances.TryGetValue(id, out result))
            {
                result = (T)Activator.CreateInstance(instanceType);
                _Instances.Add(id, result);
            }
            return result;        
        }

  3. #3
    maa
    maa est déconnecté
    Membre éclairé
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Par défaut
    J'ai pas très envie de passer par le réflexion en fait.
    Par ailleurs, l'utilisation du design pattern factory m'obligera à mettre des constructeurs public pour mes classes, donc n'importe qui pourra créer des instances sans passer par la factory.
    J'ai plutôt opté pour la solution suivante (qui se rapproche assez de la factory en fait). Je délègue la création des instances à une classe static. Pour m'assurer que les instances ne sont créer que par les classes concernée, je dois fournir à la méthode GetInstance un délégué permettant de construire l'instance. Voici le code de cette classes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    internal static class InstancesProvider<T>
    {
    	private static Dictionary<string, T> _Instances = new Dictionary<string, T>();
     
    	public static T GetInstance(string id, Func<T> ctor)
    	{
    		T result;
    		if (!_Instances.TryGetValue(id, out result))
    		{
    			result = ctor();
    			_Instances.Add(id, result);
    		}
    		return result;
    	}
    }
    Puis je l'utilise comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    public Class1
    {
    	private Class1() {}
     
    	public static Class1 GetInstance(string id)
    	{
    		return InstancesProvider<Class1>.GetInstance(id, y => new Class1());
    	}
    }
     
    public Class2 : Class1
    {
    	private Class2() {}
     
    	public static Class2 GetInstance(string id)
    	{
    		return InstancesProvider<Class2>.GetInstance(id, y => new Class2());
    	}
    }
     
    ...

  4. #4
    Membre Expert Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Par défaut
    Citation Envoyé par maa Voir le message
    J'ai pas très envie de passer par le réflexion en fait.
    Par ailleurs, l'utilisation du design pattern factory m'obligera à mettre des constructeurs public pour mes classes, donc n'importe qui pourra créer des instances sans passer par la factory.
    Sauf si ton usine et ta classe sont dans la même assembly, auquel cas le mot-clé "internal" prend tout son sens

  5. #5
    maa
    maa est déconnecté
    Membre éclairé
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Par défaut
    l'utilisation du design pattern factory m'obligera à mettre des constructeurs public pour mes classes
    J'ai hésité a ajouter "ou internal" en me disant que quelqu'un allait bien me tomber dessus.
    Mais sérieusement, internal n'empêche pas la création d'instance à l'intérieur de l'assembly, donc c'est moyen je trouve... J'ai souvent l'impression que l'utilisation de constructeurs/méthodes internal est la solution de dernier recours quand on veux limiter leurs utilisation à certaines classes. On se dit : "après tout dans mon assembly, je ferais attention à ne pas faire n'importe quoi...".

Discussions similaires

  1. Appel de '.class' sur un type générique
    Par acarbenay dans le forum Langage
    Réponses: 2
    Dernier message: 18/10/2011, 15h10
  2. Récupérer la classe d'un type générique
    Par Asterius dans le forum Langage
    Réponses: 7
    Dernier message: 21/11/2008, 08h45
  3. Types génériques: Class is a raw type
    Par lexsteens dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 22/03/2008, 04h40
  4. Réponses: 12
    Dernier message: 23/09/2006, 12h12
  5. y a-t-il un support de types génériques pour python ?
    Par silverhawk.os dans le forum Général Python
    Réponses: 15
    Dernier message: 24/03/2006, 18h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo