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 :

Unable to cast object of type parent to child


Sujet :

C#

  1. #1
    Membre averti
    Avatar de Sparky95
    Homme Profil pro
    Full Stack (web) developer
    Inscrit en
    Décembre 2016
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Full Stack (web) developer
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2016
    Messages : 379
    Points : 358
    Points
    358
    Par défaut Unable to cast object of type parent to child
    Bonjour,

    Je cherche à changer le type d'un parent en type enfant.
    Voici la tentative la plus explicite je pense.
    Class parent
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public class ParentClass
    {
        public int Id { get; set; }
        public ParentClassDto ToDto() => new() { Id = Id }; 
    }
    
    public class ParentClassDto { public int Id { get; set; } }

    Class enfant
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class ChildClass : ParentClass
    {
        public string name { get; set; }
        public new ChildDto ToDto()
        {
            var element = (ChildDto)base.ToDto();
            // element.name = name;
    return element;
        }
    }
    
    public class ChildClassDto: ParentClassDto { public string name { get; set; } }

    J'ai suivi le fait que pour faire cela il fallait que l'objet soit créé de type enfant avant d'être interprété en temps que parent.

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Parent p = new Child();
    Child c = (Child)p;

    Seulement ici, je ne sais pas le créer de type enfant étant donné que c'est le parent directement qui crée l'objet

    une idée de comment je pourrais mettre cela en place?
    Merci d'avance

  2. #2
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 667
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 667
    Points : 5 235
    Points
    5 235
    Par défaut
    Déjà la classe ChildDto n'existe pas.
    Tu voulais sûrement écrire public new ChildClassDto ToDto().

    Ensuite, puisque ChildClassDto hérite de ParentClassDto, il n'y a pas besoin de passer par la création d'un parent.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public class ChildClass : ParentClass
    {
        public string name { get; set; }
        public new ChildClassDto ToDto()
        {
            return new ChildClassDto { Id = Id, name = name };
        }
    }

  3. #3
    Membre averti
    Avatar de Sparky95
    Homme Profil pro
    Full Stack (web) developer
    Inscrit en
    Décembre 2016
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Full Stack (web) developer
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2016
    Messages : 379
    Points : 358
    Points
    358
    Par défaut
    Bonjour,

    Effectivement c'est une faute de frappe.

    Concernant la 2e partie, je cherchais à faire en sort de ne pas devoir justement assigner les attributs, créés dans le parent, dans l'enfant.

    Mon but étant justement que l'id soit assigné dans le parent et le name dans l'enfant.

    Pour le moment j'ai fais un "fix" de cette manière

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     public new ChildDto ToDto()
    {
    
        var parent = base.ToDto();
        var child = new ChildDto();
    
        // Copy parent Attribute Values to Child
        parent.GetType().GetProperties().ToList().ForEach(property => property.SetValue(child, property.GetValue(parent)));
        child.Name = Name;
    
        return Child;
    }
    

  4. #4
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 667
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 667
    Points : 5 235
    Points
    5 235
    Par défaut
    Citation Envoyé par Sparky95 Voir le message
    Mon but étant justement que l'id soit assigné dans le parent et le name dans l'enfant.
    Ton objet Child hérite de Parent, donc l'Id que tu lui affecte provient de ce parent.
    C'est le principe même l'héritage.

    Ton "mix" fait exactement ce que je fais mais de manière plus compliqué et de manière moins efficace du fait de la création d'un objet qui ne sert à rien mais surtout à cause de la réflexion.

  5. #5
    Membre averti
    Avatar de Sparky95
    Homme Profil pro
    Full Stack (web) developer
    Inscrit en
    Décembre 2016
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Full Stack (web) developer
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2016
    Messages : 379
    Points : 358
    Points
    358
    Par défaut
    Le problème avec ce que tu fais est justement qu'il faut répéter les attributs parents dans tout les ToDto enfants.
    Je cherchais à faire en sort que la base method fasses son job et qu'en cascade l'objet soit remplis.
    Je cherche à éviter de devoir manuellement écrire tout les attributs des parents dans les enfants pour la creation d'un ChildDto SubChildDto,...

    Pourquoi?
    1 car j'ai beaucoup d'attributs dans les parents et que je n'ai pas envie de m'amuser en cascade à recopier une ligne lorsque à chaque fois que j'ajouterai un attribut en plus dans un parent
    2 car certains attributs doivent rester public mais n'ont rien à faire dans les Dto.
    le fait de ne pas les mettre dans le Dto parent, me permets d'éviter de devoir me rappeler ou d'aller à chaque fois regarder dans le Dto parent si ces attributs devaient y être.
    3 Cela permets une réflexion plus rapide lorsqu'on travail en group et que l'on crée de nouveaux enfants.
    On crée une class avec son héritage et je fais la methode ToDto avec ses attributs courant sans ce soucier de attributs de la class parente.


    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    using System;
     
     
    public class ParentDto { public int Id { get; set; } }
    public class Parent
    {
        public int Id { get; set; }
        public ParentDto ToDto() => new() { Id = Id }; 
    }
    public class ChildDto : ParentDto
    {
        public string Name { get; set; }
    }
    public class Child : Parent
    {
        public string Name { get; set; }
        public new ChildDto ToDto() => new() {
            // je ne veux pas devoir répeter Id = Id,...
            Name = Name
        };
        /*
        l'idée eu été pouvoir faire quelque chose comme ça
        public new ChildDto ToDto() => Base.ToDto() { Name = Name };
        */    
    }
     
     
    public class Program
    {
        public static void Main()
        {
            var child = new Child(){ Id = 1, Name = "Hello World!" };
            Console.WriteLine(child.ToDto().Id); // 0
        }
    }

  6. #6
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 667
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 667
    Points : 5 235
    Points
    5 235
    Par défaut
    Citation Envoyé par Sparky95 Voir le message
    /*
    l'idée eu été pouvoir faire quelque chose comme ça
    public new ChildDto ToDto() => Base.ToDto() { Name = Name };
    */
    }
    Ce que tu cherches à faire est un non sens.
    Un camion est un véhicule mais tous les véhicule ne sont pas des camions.
    Tu ne peux créer un Parent et lui renseigner la propriété Name qui fait partie de Child.
    Pour Parent la propriété Name n'existe pas.


    Citation Envoyé par Sparky95 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public class Program
    {
        public static void Main()
        {
            var child = new Child(){ Id = 1, Name = "Hello World!" };
            Console.WriteLine(child.ToDto().Id); // 0
        }
    }
    Faux, en tout cas pas avec ma méthode, moi j'obtiens 1.
    Et cela ne devrait pas non plus se produire avec ton code basé sur Reflection.
    Au passage, tu auras le même problème avec la reflexion, sauf que tu auras un code compliqué qui sera répété sus chaque objet hérité.

  7. #7
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 667
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 667
    Points : 5 235
    Points
    5 235
    Par défaut
    Tu ne pourras pas te dispenser d'un appel pour affecter les propriété des parents avec ce montage.
    Mais peut-être qu'en étant malin...

    Ceci semble fonctionner chez moi, mais je n'ai qu'un seul niveau dhéritage.
    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
    var child = new ChildClass() { Id = 1, Name = "Hello World!" };
    Console.WriteLine(child.ToDto().Id); // 0
     
     
    public class ParentClass
    {
        public int Id { get; set; }
        public ParentClassDto ToDto() => new() { Id = Id };
     
        public void Assign(ParentClassDto child, Type parentType)
        {
            var properties = parentType.GetProperties().ToList();
            foreach (var property in properties)
            {
                var value = property.GetValue(this);
                child.GetType().GetProperty(property.Name).SetValue(child, value);
            }
        }
    }
     
    public class ParentClassDto { public int Id { get; set; } }
     
    public class ChildClass : ParentClass
    {
        public string Name { get; set; }
        public new ChildClassDto ToDto()
        {
            ChildClassDto dto = new ChildClassDto() { Name = Name };
            Assign(dto, typeof(ParentClass));
     
            return dto;
        }
    }
     
     
    public class ChildClassDto : ParentClassDto
    { 
        public string Name { get; set; } 
    }

  8. #8
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 667
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 667
    Points : 5 235
    Points
    5 235
    Par défaut
    Je viens de faire le test, ça fonctionne pour toute la hierarchie à partir du moment où on renseigne la bonne classe ancêtre dans l'appel à Assign.

    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
    public class SubChildClass : ChildClass
    {
        public string Test { get; set; }
        public new SubChildClassDto ToDto()
        {
            SubChildClassDto dto = new SubChildClassDto() { Test = Test };
            Assign(dto, typeof(ChildClass));
     
            return dto;
        }
    }
     
    public class SubChildClassDto : ChildClassDto
    {
        public string Test { get; set; }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    var child = new SubChildClass() { Id = 1, Name = "Hello World!", Test = "Yeeehah" };
    Console.WriteLine(child.ToDto().Id); // 1
    Console.WriteLine(child.ToDto().Name); 
    Console.WriteLine(child.ToDto().Test);
    1
    Hello World!
    Yeeehah

  9. #9
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Tu peux également passer par le constructeur.

    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
    public class ParentDto {
       public ParentDto (int id)
    {
      Id = id ;
    }
     public int Id { get; set; } }
    public class Parent
    {
        public int Id { get; set; }
        public ParentDto ToDto() => new ParentDto(Id); 
    }
    public class ChildDto : ParentDto
    {
        public string Name { get; set; }
       public ParentDto (string name, int id) : base(id)
    {
     Name = name;
    }
    }
    public class Child : Parent
    {
        public string Name { get; set; }
        public new ChildDto ToDto() => new ChildDto(Name,ID);
     
    }
    Bon s'il y a beaucoup de paramètre ca peut devenir chiant.

    Il y a aussi les outils comme AutoMapper ou Mapster.

    Mais bon d'une manière globale, aujourd'hui il y a un regain nouveau pour les choses très explicites quitte à avoir en apparence du code redondant, et donc cela va à l'encontre de ce que tu cherches à faire ( ou d'utiliser les outils que j'ai indiqué). Demain il en sera surement autrement .

  10. #10
    Membre averti
    Avatar de Sparky95
    Homme Profil pro
    Full Stack (web) developer
    Inscrit en
    Décembre 2016
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Full Stack (web) developer
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2016
    Messages : 379
    Points : 358
    Points
    358
    Par défaut
    Citation Envoyé par popo Voir le message
    Ce que tu cherches à faire est un non sens.
    Un camion est un véhicule mais tous les véhicule ne sont pas des camions.
    Oui je sais c'est quelque chose de ce style la que j'essayais de faire mais pas ça.
    L'idée était de faire un peu comme les constructeurs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Constructeur(){
        base();
        .. suite des operations
    }
    mais avec la difficulté de création d'objet qui ensuit est retourné

    Enfin bon tant pis je vais laisser le code que je fessais pour le moment.
    Ce n'est pas le plus optimisé mais c'est le plus pratique pour l'évolution dans le temps.

    Citation Envoyé par popo Voir le message
    ...
    Oui c'est plus ou moins ce que je fais déjà. Sauf que le code d'Assign ce trouves dans Child.ToDto().

    Citation Envoyé par micka132 Voir le message
    Bon s'il y a beaucoup de paramètre ca peut devenir chiant.
    Oui c'est ce que j'essayes d'éviter

    C'est pas grave,
    Un grand merci en tout cas pour vos idées.

  11. #11
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 667
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 667
    Points : 5 235
    Points
    5 235
    Par défaut
    Citation Envoyé par Sparky95 Voir le message
    Oui c'est plus ou moins ce que je fais déjà. Sauf que le code d'Assign ce trouves dans Child.ToDto().
    La grosse différence entre ce que tu as fait et ce que je te propose est que le code qui recopies les propriété n'a pas besoin d'être répété pour chaque descendant.
    Il suffit d'appeler la méthode Assign avec type dans le second paramètre.

  12. #12
    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
    La discussion me parait bien compliquée, pour une solution relativement assez simple, basée sur l'héritage :

    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
     
    namespace ConsoleApp18
    {
        internal class Program
        {
            public class ParentClass
            {
                public int Id { get; set; }
                public ParentClassDto ToDto() => new ParentClassDto(this);
            }
     
            public class ParentClassDto 
            {
                public ParentClassDto() { }
     
                public ParentClassDto(ParentClass o)
                {
                    this.Id = o.Id;                
                }
     
                public int Id { get; set; } 
            }
     
            public class ChildClass : ParentClass
            {
                public string name { get; set; }
                public new ChildClassDto ToDto()
                {
                    var element = new ChildClassDto(this);
                    // element.name = name;
                    return element;
                }
            }
     
            public class ChildClassDto : ParentClassDto 
            {            
                public ChildClassDto(ChildClass o) : base(o)
                {
                    this.name = o.name;
                }
     
                public string name { get; set; } 
            }
     
     
     
            static void Main(string[] args)
            {
                ChildClass child = new ChildClass() { Id = 123, name = "Child" };
                ChildClassDto dto = child.ToDto();
     
                Console.WriteLine($"id = {dto.Id}");
                Console.WriteLine($"name = {dto.name}");
            }
        }
    }
    • chaque enfant est responsable de ses attributs
    • les attributs parent (ancêtre devrais-je même dire) sont gérés via l'héritage
    • pas besoin d'utiliser la réflexivité du langage
    • pas besoin de faire de casts en tout sens
    • pas besoin d'avoir des constructeurs avec une liste de paramètre à rallonge


    Cette méthode n'utilise que les bases de la programmation orientée objet, et plus particulièrement l'héritage (et même pas le polymorphisme !).

    Si je peux me permettre de donner un conseil, c'est de réviser un peu les notions d'héritage, car passer par une solution compliquée, à base de réflexion pour résoudre un problème naturellement résolu par l'utilisation de l'héritage, cela me fait dire qu'il y a peut être quelques lacunes de ce côté .
    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

  13. #13
    Membre averti
    Avatar de Sparky95
    Homme Profil pro
    Full Stack (web) developer
    Inscrit en
    Décembre 2016
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Full Stack (web) developer
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2016
    Messages : 379
    Points : 358
    Points
    358
    Par défaut
    Citation Envoyé par François DORIN Voir le message
    ...
    Voila, c'est ce que je cherchais à faire mais je n'arrivais plus à me le représenter Top merci

  14. #14
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Citation Envoyé par François DORIN Voir le message
    La discussion me parait bien compliquée, pour une solution relativement assez simple, basée sur l'héritage :
    ....[*] pas besoin d'avoir des constructeurs avec une liste de paramètre à rallonge
    Effectivement, d'autant que d'ordinaire quand on commence à avoir plein de paramètre on passe facilement par un objet. Et là pour le coup je n'ai même pas vu que cet objet c'est justement celui que l'on cherche à transformer

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 15/02/2011, 14h01
  2. Unable to cast object of type "System.Windows.Application"
    Par OminiuS dans le forum Silverlight
    Réponses: 11
    Dernier message: 15/09/2010, 16h28
  3. Réponses: 11
    Dernier message: 06/05/2009, 17h13
  4. <object> : récupérer son parent / changer son contenu
    Par benj63 dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 04/05/2006, 18h24
  5. [héritage] cast avec le type de base
    Par Lere dans le forum C++
    Réponses: 6
    Dernier message: 16/09/2004, 18h21

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