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 :

Initialisé l'objet enfant depuis l'objet parent


Sujet :

C#

  1. #1
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 065
    Points : 4 229
    Points
    4 229
    Par défaut Initialisé l'objet enfant depuis l'objet parent
    Bonjour,

    un cas que je rencontre souvent en C# mais dont je n'ai pas de solution "magique" pour le faire.

    J'ai un object B héritant de A, je voudrais crée une instance de mon Objet B à partir d'une instance d'Objet A, voici ma solution actuellement:

    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    public class A
        {
     
            [JsonProperty("id")]
            public int Id { get; set; }
     
            [JsonProperty("key")]
            public string Key { get; set; }
     
            [JsonProperty("name")]
            public string Name { get; set; }
     
            [JsonProperty("title")]
            public string Title { get; set; }
     
            public A() {
            }
     
            public A(A a)
            {
                this.Id = a.Id;
                this.Key = a.Key;
                this.Name = a.Name;
                this.Title = a.Title;
            }
        }
     
       public class B: A
        {
            public bool Discover { get; set; }
     
            public string Clue1 { get; set; }
     
            public string Clue2 { get; set; }
     
            public B() { }
     
            public B(A a):base(a)
            {
            }
        }
     
     // et donc je crée une instance de ma classé B comme ça
      B b=new B(a);
    Y'a t'il un moyen plus simple de faire ça sans me taper toutes les propriétés dans le constructeur de mes classes et sans passer par la réflexion ?

    Ou peut être que je devrais juste me crée un outil qui fait le boulot à ma place ?

  2. #2
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 184
    Points : 5 755
    Points
    5 755
    Par défaut
    Dans ton exemple nous ne savons pas ce qu'est 'a' dans 'B b=new B(a);' peut tu compléter ?

    Si je comprend :
    Tu as une class B qui hérite de A.
    Tu as instancié un objet A et tu souhaite le convertir en objet B.

    Un objet B est aussi un objet A mais le contraire n'est pas vrai.
    Un objet A n'est pas un objet B donc il faut le convertir.

    Pour l'instant ce que je dit n'avance pas à grand chose, je vais réfléchir

  3. #3
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 065
    Points : 4 229
    Points
    4 229
    Par défaut
    a est une instance de A que j'obtiens grâce à une désérialisation Json:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    A a=JsonSerializer.DeserializeJsonFromFile<A>("A.txt");
    B b=new B(a);

  4. #4
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 184
    Points : 5 755
    Points
    5 755
    Par défaut
    Je peut te proposer cela


    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
    public class A
    {
        public string stra { get; set; }
        public T ConvertTo<T>() where T : A, new()
        {
            T obj = new T();
            Type t = this.GetType();
            foreach (System.Reflection.FieldInfo fieldInf in t.GetFields())
                fieldInf.SetValue(obj, fieldInf.GetValue(this));
            foreach (System.Reflection.PropertyInfo propInf in t.GetProperties())
                propInf.SetValue(obj, propInf.GetValue(this, null), null);
            return obj;
        }
    }
     
    public class B : A
    {
        public string strb { get; set; }
    }
     
    public class C : B
    {
        public string strc { get; set; }
    }
    Ça s'utilise comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    A a = new A();
    a.stra = "A";
     
    B b = a.ConvertTo<B>();
    b.strb = "B";
     
    C c1 = a.ConvertTo<C>();
    c1.strc = "C1";
     
    C c2 = b.ConvertTo<C>();
    c1.strc = "C2";

  5. #5
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 184
    Points : 5 755
    Points
    5 755
    Par défaut
    public T ConvertTo<T>() where T : A, new()
    Le paramètre générique doit être ou doit dérivé du type A.
    Nous pourrions nous en passer mais ça évite des exceptions en cas de conversion impossible.
    L'intellissense nous prévient donc immédiatement si il y à un problème.
    Il faudrait donc adapter cette valeur à chaque implémentation de ce mécanisme dans tes class.

  6. #6
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 184
    Points : 5 755
    Points
    5 755
    Par défaut
    J'ai hésité à l'implémenter dans une conversion implicit de la class . . . une autre idée.

    EDIT : Cela ne semble pas possible avec des classes dérivées

  7. #7
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 184
    Points : 5 755
    Points
    5 755
    Par défaut
    D'autre propose de sérialiser le parent puis dé-sérialiser en type enfants, puisque tu utilise du Json.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var serializedParent = JsonConvert.SerializeObject(parentInstance); 
    Child c  = JsonConvert.DeserializeObject<Child>(serializedParent );
    D’ailleurs je ne connait pas Json qu'est ce ?
    Ça vient de la ? http://www.newtonsoft.com/json

  8. #8
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 065
    Points : 4 229
    Points
    4 229
    Par défaut
    Justement je voulais éviter la réflection (je sais qu'il existe aussi des outils comme automapper mais ça se base sur la reflection), Json c'est un format de donnée un peu comme le XML mais plus light qui convient donc parfaitement au Web moderne (tu as hiberné ces 10 dernières années ?)

    Je vais testé avec Json.

    En tout cas merci de t'être penché sur le problème.

    Ca fonctionne avec la sérialisation Json donc je pense qu'il est possible de faire ça avec la sérialisation binaire , je testerai ça, merci pour la piste (c'est pas ce qui me parait le plus propre mais c'est une solution simple et performante je pense).

  9. #9
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 184
    Points : 5 755
    Points
    5 755
    Par défaut
    J’aime pas le web

    Je ne veux pas être méchant mais JSon surement utilise aussi la réflexion.

  10. #10
    Membre régulier
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2016
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2016
    Messages : 64
    Points : 91
    Points
    91
    Par défaut
    Salut,

    sinon tu as la solution de passer par la composition, au lieu de l'héritage, enfin à voir si ça colle avec le reste de ton projet :

    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
     
    public class A // Au runtime seule une des propriétés (entre MonObjetB, MonObjectC, etc.) sera non null
    {
    ...
    ...
    ...
        public B MonObjetB 
        {
            get; set;
        }
     
        public C MonObjetC 
        {
            get; set;
        }
     
    ...
    ...
    }
     
    public class B // B n'hérite plus de A
    {
     
    }

  11. #11
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 757
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 757
    Points : 10 697
    Points
    10 697
    Billets dans le blog
    21
    Par défaut
    Si tu ne veux pas avoir à réaliser cette assignation dans le constructeur à la mano, tu as deux possibilités :
    • Utiliser la réflexion ;
    • Utiliser un générateur de code.

    Les méthodes utilisant le principe de la sérialisation/désérialisation "générique" utilisent la réflexion (pour preuve : tes propriétés de la classe A sont décorés avec des attributs !).

    Après, si le problème est un problème de performance (car l'utilisation de la réflexivité peut être relativement lourde), tu peux utiliser la réflexivité pour générer du code (voir l'espace de nom System.Reflection.Emit). Ainsi, tu n'utiliseras pas la réflexivité pour chaque initialisation d'un objet B à partir d'une instance A, mais seulement pour créer la méthode se chargeant de faire cette initialisation. C'est sans doute un peu lourd à mettre en oeuvre (il faut manipuler du IL !), mais comme ce que tu souhaites faire est assez simple, cela devrait se faire sans trop de complications .

    Après, cela reste de la génération de code. C'est juste qu'au lieu de travailler avec un fichier source, tu utilises la réflexion, et tu troques la complexité de lire le fichier source par celle d'écrire du IL. Mais l'avantage de l'utiliser ici, c'est que ton code sera langage agnostique et pourra donc être réutilisé dans d'autres langages
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  12. #12
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Points : 5 195
    Points
    5 195
    Par défaut
    Salut

    J'arrive peut-être un peu tard, mais finalement, tu veux faire un copy constructor

    Comme ça n'existe pas en C#, il y a plein de solutions proposées

    Une ici, basée sur la reflection et qui me semble simple

    https://johnsad.ventures/2006/07/03/...ctor_in_c_usi/
    The Monz, Toulouse
    Expertise dans la logistique et le développement pour
    plateforme .Net (Windows, Windows CE, Android)

  13. #13
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 065
    Points : 4 229
    Points
    4 229
    Par défaut
    Oui ça correspondrai à ça, ça serai génial qu'on puisse faire un truc dans le genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
       public MyClass( MyClass rhs )
        {
           this=rhs;
        }
    Donc pas trop le choix réflection ou génération de code comme je le pensais.

    Pour la composition ça pourrait être une solution dans l'appli sur laquelle je boss actuellement, mais d'une manière générale pas forcément, je rencontre souvent cette problématique avec l'héritage, et je cherchai une réponse pour cette problématique général.

    Je pense sinon que faire un plugin/snippet pour visualstudio qui fait ça pourrait être une solution, je verrai ce que je fait.

Discussions similaires

  1. Réponses: 2
    Dernier message: 18/09/2012, 14h58
  2. Réponses: 3
    Dernier message: 30/01/2012, 18h52
  3. Réponses: 1
    Dernier message: 24/03/2011, 14h27
  4. Réponses: 1
    Dernier message: 08/08/2009, 01h46
  5. Réponses: 15
    Dernier message: 30/04/2008, 16h50

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