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 :

Stocker des objets de type différents dans un dictionnaire générique


Sujet :

C#

  1. #1
    Membre actif
    Inscrit en
    Avril 2006
    Messages
    346
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 346
    Points : 252
    Points
    252
    Par défaut Stocker des objets de type différents dans un dictionnaire générique
    Bonjour,

    je souhaite développer une classe intitulée CommunicationFactory comprenant une méthode GetChannel retournant un type générique:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public class CommunicationFactory
    {
            public T GetChannel<T>(string configName)
            {
     
            }        
    }

    J'aimerais que cette méthode récupère dans un dictionnaire l'objet correspondant au paramètre configName ou le créé et l'ajoute au dico si celui-ci n'existe pas.
    Ainsi, j'ai besoin d'un dictionnaire dont la clé est de type string et la valeur est de type générique.

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    private Dictionary<string, T> m_DicoChannel;

    Or il n'est pas possible de typer le dictionnaire ainsi puisque la classe CommunicationFactory n'est elle-même pas générique.
    Est-ce que selon vous l'utilisation du type dynamique est adapté dans ce cas ? Cela donnerait:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    private Dictionary<string, dynamic> m_DicoChannel;

    Sinon, comment puis-je créer un dictionnaire dont les valeurs sont de types différents ?

    Pour info, je développe en C#4 sous VS2010.

    Merci d'avance,
    Zoax

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 754
    Points
    39 754
    Par défaut
    Utilise un Dictionary<string, object>, et cast le résultat vers T :

    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
    public class CommunicationFactory
    {
        private readonly Dictionary<string, object> m_DicoChannel = new Dictionary<string, object>();
        public T GetChannel<T>(string configName)
        {
            object channel;
            if (!m_DicoChannel.TryGetValue(configName, out channel))
            {
                channel = CreateChannel<T>();
                m_DicoChannel[configName] = channel;
            }
            return (T)channel;
        }        
     
        private T CreateChannel<T>()
        {
            // Création du channel
            ...
        }
    }

  3. #3
    Membre actif
    Inscrit en
    Avril 2006
    Messages
    346
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 346
    Points : 252
    Points
    252
    Par défaut
    Bonjour,

    merci pour la réponse.
    Citation Envoyé par tomlev
    Utilise un Dictionary<string, object>, et cast le résultat vers T :
    Tout simplement.

    Pour comprendre, quel était l'inconvénient d'utiliser dynamic ?

    Merci d'avance,
    Zoax

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 754
    Points
    39 754
    Par défaut
    Citation Envoyé par zoaax Voir le message
    Pour comprendre, quel était l'inconvénient d'utiliser dynamic ?
    Ca dépend de ce que tu fais avec... Si tu remplaces object par dynamic dans le code que je t'ai donné, ça ne changera strictement rien, parce que ce code n'accède pas aux membres de l'objet, il se contente de le caster en T. Et en réalité, du point de vue du CLR, un dynamic est juste un object (dynamic n'est pas un "vrai" type en fait).

    Par contre, si tu commences à accéder à des membres d'un objet via une variable dynamic, ça peut poser des problèmes de performance et de fiabilité, parce que ça introduit du "late binding", c'est à dire que les membres (méthodes, propriétés etc) auxquels tu accèdes sont résolus lors de l'exécution plutôt que lors de la compilation. Autrement dit, si tu accèdes à une propriété qui n'existe pas sur une variable dynamic, ça compilera sans problème, mais ça fera une erreur lors de l'exécution. Bien sûr dans certains cas c'est très pratique, mais en l'occurrence ça n'apporte rien...

  5. #5
    Membre expert
    Avatar de GuruuMeditation
    Homme Profil pro
    .Net Architect
    Inscrit en
    Octobre 2010
    Messages
    1 705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Belgique

    Informations professionnelles :
    Activité : .Net Architect
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2010
    Messages : 1 705
    Points : 3 568
    Points
    3 568
    Par défaut
    Ca me rappelle le bon (?) vieux temps .NET 1.1 avant les génériques!

  6. #6
    Membre actif
    Inscrit en
    Avril 2006
    Messages
    346
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 346
    Points : 252
    Points
    252
    Par défaut
    Bonjour,

    merci pour les réponses.
    Je veux faire une méthode de fermeture des channel. J'ai donc besoin d'accéder aux membres des objets stockés dans le dictionnaire. Ceux-ci sont en réalité de type CommunicationObject<T>. Or vu que l'objet Valeur du dictionnaire est de type object, je ne peux pas accéder à ses membres.

    Voici la définition de l'objet CommunicationObject<T>:

    Code c# : 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
    internal class CommunicationObject<T>
        {
            /// <summary>
            /// Obtient ou définit le ChannelFactory utilisé pour la communication avec le service WCF
            /// </summary>
            internal ChannelFactory<T> ChannelFactory { get; private set; }
            /// <summary>
            /// Obtient ou définit le canal utilisé pour envoyer les messages au service WCF
            /// </summary>
            internal T Channel { get; private set; }
     
            internal CommunicationObject(ChannelFactory<T> channelFactory)
            {
                this.ChannelFactory = channelFactory;
                this.Channel = channelFactory.CreateChannel();
            }
        }

    Pour résoudre ceci, j'ai 2 possibilités. La première est de finalement utiliser un dico employant un type "dynamique".

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    private Dictionary<string, dynamic> m_DicoCommunication = null;

    Ce qui donnerait:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /// <summary>
            /// Fermeture des cannaux de communication
            /// </summary>
            internal void CloseChannels()
            {
                foreach (var comObj in m_DicoCommunication.Values)
                {
                    var channelFactory = comObj.ChannelFactory;
                    if ((channelFactory != null) && (channelFactory.State == CommunicationState.Opened))
                    {
                        if (channelFactory.State != CommunicationState.Faulted)
                            channelFactory.Close();
                    }
                }
            }

    L'autre possibilité, selon moi, serait de faire à l'ancienne en héritant la classe CommunicationObject<T> par sa version non générique CommunicationObject.

    Qu'est-ce qu'il serait le mieux d'après vous ?

    Zoax

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 754
    Points
    39 754
    Par défaut
    Le mieux serait de définir une interface avec les méthodes communes (dont Close), et d'utiliser cette interface à la place de object dans le dictionnaire. Comme ça tout reste fortement typé et tu n'as pas besoin de dynamic

Discussions similaires

  1. itération sur des objets de types différents ?
    Par jc63 dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 07/09/2007, 08h19
  2. Réponses: 4
    Dernier message: 05/05/2007, 19h12
  3. Réponses: 3
    Dernier message: 16/10/2006, 11h06
  4. Réponses: 7
    Dernier message: 13/03/2006, 08h56
  5. stocker des valeurs de type différent
    Par jakouz dans le forum Langage
    Réponses: 3
    Dernier message: 28/11/2005, 09h36

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