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 :

Ajouter des éléments à une liste par reflection


Sujet :

C#

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 114
    Points : 122
    Points
    122
    Par défaut Ajouter des éléments à une liste par reflection
    Bonjour,

    j'essai d'initialiser une instance de classe à l'aide de la reflection.
    Pour cela j'ai pris soin de nommer et typer les propriété de la classe du même noms et types que les colonnes de la table.

    Cela fonctionne parfaitement pour les types simples. Par contre j'ai du mal à populer les listes.

    voici mon code:
    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
     
        public class Calendar : Root
        {
            protected string _CalendarName;
     
            // Properties
            public string CalendarName { get { return _CalendarName; } }
            public List<string> SubCal { get; set; }
            public List<DateTime> Holidays { get; set; }
     
            // Constructor
            public Calendar(string name) 
            {
                Dictionary<string, Object> keys = new Dictionary<string, Object>();
                keys.Add("CalendarName", name);
                loadFromDB("subcalendar", keys);
                loadFromDB("calendarview", keys);
            }
        }
    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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
     
        public class Root
        {
            private string _connectionString;
     
            public Root()
            {
                string bdd = ConfigurationManager.AppSettings["BDD"];
                _connectionString = ConfigurationManager.ConnectionStrings[bdd].ConnectionString;
            }
     
            private string buildClause(KeyValuePair<string, Object> kvp)
            {
                PropertyInfo prop = this.GetType().GetProperty(kvp.Key);
                string clause = "";
                string typeName = this.GetType().GetProperty(kvp.Key).PropertyType.Name;
     
                switch (typeName)
                {
                    case "String":
                        clause = kvp.Key + " = '" + Convert.ToString(kvp.Value) + "'";
                        break;
                    case "Boolean":
                        clause = kvp.Key + " = " + (Convert.ToBoolean(kvp.Value) ? "true" : "false");
                        break;
                    case "DateTime":
                        clause = kvp.Key + " = '" + Convert.ToDateTime(kvp.Value).ToString("yyyy-MM-dd") + "'";
                        break;
                    default:
                        throw new UnknownTypeException("Unknown type : " + typeName);
                }
                return clause;
            }
     
            private object getValue(MySqlDataReader reader, Type type, int col)
            {
                switch (type.Name)
                {
                    case "String":
                        return reader.GetString(col);
                    case "DateTime":
                        return reader.GetDateTime(col);
                    case "Boolean":
                        return reader.GetBoolean(col);
                    default:
                        throw new UnknownTypeException("Unknown type : " + type.Name);
                }
            }
     
            public void loadFromDB(string tableName, Dictionary<string, Object> keys)
            {
                // Build SQL request from parameters
                string sql = "select * from " + tableName;
                bool first = true;
     
                foreach (KeyValuePair<string, Object> kvp in keys)
                {
                    sql += (first ? " where " : " and ") + buildClause(kvp);
                    first = false;
                }
     
                // Execute sql request
                MySqlConnection myConnection = new MySqlConnection(_connectionString);
                MySqlCommand myCommand = myCommand = new MySqlCommand(sql, myConnection);
                myConnection.Open();
                MySqlDataReader reader = myCommand.ExecuteReader();
     
                // Parse result
                if (reader.HasRows)
                {
                    // Here we know there is at least one row
                    // First get the objects property
                    PropertyInfo[] props = this.GetType().GetProperties();
                    // The dictionnary will store the corresponding column number in the reader result
                    Dictionary<PropertyInfo, int> columns = new Dictionary<PropertyInfo, int>();
     
                    // Parse the properties to get the corresponding column number
                    foreach (PropertyInfo prop in props)
                    {
                        try
                        {
                            // Store the pair in the dictionnary
                            columns.Add(prop, reader.GetOrdinal(prop.Name));
                        }
                        catch (IndexOutOfRangeException e)
                        {
                            // current property does exist as column is this table
                            // ignore this error
                        }
                    }
     
                    // For each result row
                    while (reader.Read())
                    {
                        // Parse the properties to fetch them from reader data
                        foreach (KeyValuePair<PropertyInfo, int> column in columns)
                        {
                            // get the property type
                            Type type = column.Key.PropertyType;
                            // Check if it is a List
                            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
                            {
                                // Get the list item type
                                Type itemType = type.GetGenericArguments()[0];
                                // Get the list to add the value
                                var col = column.Key.GetValue(this, null) as IList;
                                if (col != null) // --> col is always null 
                                    col.Add(getValue(reader, itemType, column.Value));
                                else
                                    throw new InvalidOperationException("Not a list");
                            }
                            else
                            {
                                // If not just fetch the property or the corresponding field
                                if (column.Key.CanWrite)
                                    column.Key.SetValue(this, getValue(reader, type, column.Value), null);
                                else
                                    this.GetType().GetField("_" + column.Key.Name, BindingFlags.NonPublic | BindingFlags.Instance).SetValue(this, getValue(reader, type, column.Value));
                            }      
     
                        }
                    }
                }
            }
        }
    }
    et enfin le contenu des tables pour un calendrier

    subcalendar:
    CalendarName SubCal
    000 London
    000 New-York

    calendarview:
    CalendarName Holidays
    000 05/11/2013
    000 04/07/2013

    Malheureusement, dans le la classe Root, je n'arrive pas à récupérer l'instance de List pour y ajouter un élément. J'obtiens toujours un pointeur null.

    une idée pour me dépanner ?

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    332
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2002
    Messages : 332
    Points : 502
    Points
    502
    Par défaut
    Laisse-moi reformuler.

    Tu veux prendre un résultat brut sous forme de Resultset d'ADO.Net et créer une instance d'une classe en faisant la correspondance entre les propriétés de cette classe et le nom des colonnes dans le dataset?

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 114
    Points : 122
    Points
    122
    Par défaut
    c'est tout à fait ça.

    La requête renvoie plusieurs car on veut ajouter à la liste correspondante (SubCal ou Holidays) la valeur de la colonne du même nom

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    332
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2002
    Messages : 332
    Points : 502
    Points
    502
    Par défaut
    Je n'ai pas de solution spécifique pour ce que tu veux faire, par contre voici une classe que j'ai faite pour adapter une instance de classe vers une nouvelle instance d'un type donné en faisant la correspondance entre les propriétés.

    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
     
    public static class Adapter
        {
            /// <summary>
            /// Generic converter that will create an instance of type and fill properties that share same name (not case sensitive)
            /// </summary>
            /// <typeparam name="T">The type of instance wanted</typeparam>
            /// <param name="entity">The entity to be converted</param>
            /// <returns></returns>
            public static T ConvertTo<T>(this object entity)
            {
     
                // Create return instance
                var newEntity = (T)Activator.CreateInstance(typeof(T));
     
                if (entity != null)
                {
                    // Loop through properties
                    Parallel.ForEach(entity.GetType().GetProperties(),
                        property =>
                        {
                            // If accessible and has no parameters
                            if (property.CanRead && !(property.GetIndexParameters().Length > 0))
                            {
                                // Match properties by name
                                PropertyInfo other = typeof(T).GetProperty(property.Name);
                                if ((other != null) && (other.CanWrite))
                                    other.SetValue(newEntity, property.GetValue(entity, null), null);
                            }
                        });
                }
     
                return newEntity;
            }
     
        }
    Si tu peux parcourir en boucle ton dataset, il suffira de faire quelque chose comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     
            public virtual IMyClass GetData()
            {
                var liste = new List<MaClasse>();
                Parallel.ForEach(DB.GetMyData(sql), result => { liste.Add(result.ConvertTo<MaClasse>()); } );
                return liste;
            }
    Il suffirait de mofidier ce code pour travailler avec des noms de colonnes plutôt que des propriétés.

    Sinon, tu peux aussi regarder le code source d'un ORM open source tel que celui-ci.

    http://code.google.com/p/servicestack/source/checkout

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 114
    Points : 122
    Points
    122
    Par défaut
    Merci pour le tuyau.

    Je vais aussi investiguer du côté de LINQ to SQL pour essayer de régler mon problème sans code ou presque

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 114
    Points : 122
    Points
    122
    Par défaut
    bon j'suis trop bête.

    mon code fonctionne parfaitement à condition d'allouer les listes dans le constructeur de Calendar ...

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

Discussions similaires

  1. Ajouter des éléments à une liste
    Par hassen07 dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 16/05/2010, 18h42
  2. Ajouter un élément à une liste
    Par izulah dans le forum Prolog
    Réponses: 5
    Dernier message: 17/03/2009, 08h57
  3. Ajouter un élément à une "List" - à l'aide!
    Par WinNew dans le forum Flex
    Réponses: 2
    Dernier message: 23/01/2009, 13h20
  4. Ajouter un élément à une liste
    Par circe dans le forum R
    Réponses: 2
    Dernier message: 24/10/2008, 18h00
  5. ajouter des valeurs à une liste déroulante
    Par Simon2 dans le forum IHM
    Réponses: 3
    Dernier message: 30/07/2007, 23h59

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