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 :

function<T>() & passage de type


Sujet :

C#

  1. #1
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Juillet 2007
    Messages
    467
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2007
    Messages : 467
    Points : 647
    Points
    647
    Par défaut function<T>() & passage de type
    Bonjour,

    Je suis sur un problème assez épineux.

    Je voudrais passer un type (au format : Type monType) à une fonction ayant une signature comme cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    List<T> MaFonction<T>(params) { ... }
    En fait, l'idée générale est de charger une liste d'objet dans une propriété d'un objet. Via un attribut, je définis que telle propriété, s'associe à tel type :

    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
     
    class Marque 
    {
    public int Identifiant { get; set; }
    public string Nom { get; set; }
    }
     
    class Utilisateur 
    {
    public string Nom { get; set; }
     
    [MonAttributType(typeof(Marque))]
    public IEnumerable<Marque> Marques { get; set; }
     
    }

    Et de manière générique, allez charger par utilisateur, sa liste de marque, en utilisant la fonction utilisé plus haut. Et c'est là que je n'arrive pas à relayer l'information à ma fonction pour lui dire que je veux une liste d'un certain type connu... Un peu 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
     
    foreach(Property p in Utilisateur.GetProperties()) 
    {
       if(p.GetAttributes<MonAttributType>() != null)
    {
    Type monType = p.GetAttributes<MonAttributType>().First().MonType;
     
    // là je dois appeler ma fonction citée plus haut, en lui passant le type définit par l'attribut de propriété avec ce genre d'appel, mais non supporté
    var monResultat = MaFonction<monType.GetType()>(mesDonnees);
     
     
    }
     
    }
    En gros, c'est du mapping DB <-> Classe objet, et jusqu'à maintenant, je gérais seulement les objets "plats". Je souhaite maintenant gérer les objets complexes...

    Merci à vous d'avance

  2. #2
    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
    Je ne sais pas ce que tu cherches à faire précisément mais j'ai l'impression que tu complexifie ça.

    tu peux simplement faire ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Utilisateur<T>
    	{
    		public string Nom { get; set; }
     
    		public IEnumerable<T> Marques { get; set; }
     
    	}
    Tu déclare ton type quand tu initialises ta classe Utilisateur.

  3. #3
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Juillet 2007
    Messages
    467
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2007
    Messages : 467
    Points : 647
    Points
    647
    Par défaut
    Pour être plus précis :

    J'ai un "Mapper" qui se charge de lire les attributs d'une classe C# et des ses propriétés, et qui est capable d'associer les champs de base de données à des objets.

    Un exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    IEnumerable<MonObjet> values = MonMapper.Select<MonObjet>();
    Dans cet exemple, le mapper s'occupe alors, de récupérer les données, conformément au paramétrage fait sur la classe et de construire une liste d'objet en associant les champs de données aux propriétés

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    [DBTable("MaTable" ...)]
    class MonObjet 
    {
    [DBField("MonChampDeDonneePour_UneProp")]
    public string UneProp { get; set; }
    [DBField("MonChampDeDonneePour_Identifiant")]
    public int Identifiant { get; set; }
     
    }
    Là où je souhaite faire évoluer mon Mapper, c'est que je souhaite récupérer, les données des types complexes dans une propriété de mon objet, en admettant bien entendu que les données de base de données que je vais passer à ma fonction seront présentes pour que le mapper extrait les objets correspondants.

    En fait, la question est :

    Comment je passe un "Type" comme type générique "T" à une fonction ayant cette signature :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    public T MaFonction<T>(mesParams) { ... }
    Et de l'autre côté
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Type monType; // je récupère le type de classe cible & je m'en sert ensuite comme type générique pour consommer "MaFonction"
    Ta solution pourrait être envisageable, mais je veux pouvoir récupérer, si besoin, plusieurs types d'objets différents, sachant que j'ai ce point d'entrée dans mon Mapper :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    T Get<T>(string commandName, DBArgument[] dbArguments, params Type[] args) où je mettrai tous les types dépendants de "T" que je souhaite charger en parallèle du type de base "T" dans les paramètres variables de cette fonction.
    Bien entendu, le résultat de la requête SQL exécutée contient toutes les données nécessaires à la construction de mon objet et de ses dépendances.

  4. #4
    Membre chevronné
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Points : 2 209
    Points
    2 209
    Par défaut
    un bon lien vaut mieux qu'un long discours
    Nous sommes tous plus ou moins geek : ce qui est inutile nous est parfaitement indispensable ( © Celira )
    À quelle heure dormez-vous ?
    Censément, quelqu'un de sensé est censé s'exprimer sensément.

  5. #5
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Juillet 2007
    Messages
    467
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2007
    Messages : 467
    Points : 647
    Points
    647
    Par défaut
    Je n'ai malheureusement aucun lien, étant donné que ce code, c'est le mien

    Mais voilà le morceau de code qui me casse la tête:

    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
     
     
    public static T Get<T>(string command, List<AdapterParameter> parameters = null, params Type[] args)
            {
                DBObjectWrapping mapping = WrapObject<T>();
                T entity = default(T);
                IEnumerable<DbDataReader> results = OleDbDataAdapter.ExecuteQuery(command, parameters);
                foreach (DbDataReader line in results)
                {
                    entity = (T)Activator.CreateInstance<T>();
                    foreach (DBFieldMapping map in mapping.Mappings.Where(x => x.IsCollection == false))
                        map.PropertyInformation.SetValue(entity, WrapValue(map.PropertyInformation.PropertyType, line.GetValue(line.GetOrdinal(map.DBFieldName))));
     
                    break;
                }
     
                if (args != null)
                {
                    foreach (Type typ in args)
                    {
                        DBFieldMapping map = null;
                        if ((map = mapping.Mappings.Where(x => x.IsCollection && x.TypeCollection == typ).FirstOrDefault()) != null) 
                            map.PropertyInformation.SetValue(entity, FetchList<typ.GetType()>(results));
     
                    }
                }
                return entity;
            }
    Et basiquement, je voudrais indiquer à ma fonction "FetchList<T>()" que le type "T" provient de la variable "typ"

  6. #6
    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
    Tu peux récupérer le type de ton générique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public Type FunctionGetType<T>()
    		{
    			return typeof(T);
    		}
    Mais je crois savoir ce que tu cherches à faire il faut pouvoir récupérer chaque sous objet de ta classe.

    Et donc tu veux traiter différemment un objet qui n'est pas un type simple (du genre string, int ...), dans ce cas là le dataattribute n'est pas une mauvaise solution: https://msdn.microsoft.com/en-us/library/z919e8tw.aspx

    L'idée c'est que comme tu fais surement actuellement tu examines chaque propriété sauf que si la propriété à l'attribut class par exemple tu rappel ta fonction pour cette propriété ( une fonction récursive peut être pas mal dans ce là) mais attention à bien gérer les liste et autres pour pas faire 50 000 appel à ta bdd. Le mieux c'est de tout scanner et une fois fait, de faire une seule requête en BDD qui te ramène tout.

    Dans un but purement de recherche et d'apprentissage c'est une bonne chose mais si c'est destiné à être utilisé dans un logiciel d'entreprise c'est pas une bonne idée, il y a de bons ORM comme Entity qui permettent de pas trop se faire chier.

  7. #7
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Juillet 2007
    Messages
    467
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2007
    Messages : 467
    Points : 647
    Points
    647
    Par défaut
    [HS]
    Je me demandais quand est ce que cette question allait être soulevée ...

    Je ne compte pas utiliser d'ORM tout prêt, notamment Entity. Et à vrai dire, le débat "vaut il mieux utiliser un ORM tout prêt, ou faire évoluer ce qui existe déjà" n'est pas à l'ordre du jour
    Donc effectivement, Entity pourrait correspondre, mais non... Lourd, lent, contraignant ...
    [/HS]

    Dans mon approche, je ne code pas les objets de base, ni les proc' stock de base...

    Je veux juste m'affranchir des fonctions à répétitions pour assigner manuellement des données à des objets.

    Et je peux aussi te confirmer que je ne fais qu'un seul appel à ma BDD pour récupérer un objet et ses dépendances.

Discussions similaires

  1. Passage de types hérités en WCF
    Par thelpi dans le forum C#
    Réponses: 0
    Dernier message: 27/07/2009, 10h40
  2. [SOAP] Passage des types imposés en paramètres
    Par Guybrush113 dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 08/10/2007, 09h34
  3. [Syntaxe] problème de passage de type en argument
    Par coyotte507 dans le forum C++
    Réponses: 2
    Dernier message: 25/05/2007, 15h50
  4. No function matches the given name and argument types.
    Par Davboc dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 03/05/2007, 11h25
  5. Passage du type integer vers varchar sur clé primaire
    Par GMI dans le forum Bases de données
    Réponses: 2
    Dernier message: 07/01/2005, 09h09

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