Bonjour,
Je suis en plein System.Reflection avec le Compact Framework 2.0 pour Windows mobile 6.5.3.

Je cherche à extraire des données d'une base de données de façon générique car il y a plusieurs tables. L'objet MaClasse est intouchable car généré automatiquement et partager avec l'application sur le PC pour la génération de fichiers XML dans les 2 sens.

En entrée, il y a la liste des champs que je souhaite sortir (strFields), l'objet destination (objTable) et les conditions à respecter (strCondition).

En sortie, MaClasse est rempli sans que j'ai à me soucier des champs.

Mon besoin :
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
static class Program
{
    static void Main()
    {
        MaClasseHerite mcl = new MaClasseHerite();
        mcl.ExportQuery("Champ1,Champ2", new MonObjet1(), "Champ2 = 'Test'");
        mcl.ExportQuery("Champ3,Champ4,Champ5", new MonObjet2(), "Champ5 = 'Extraire'");
    }
}

// Intouchable car autogénéré
public partial class MaClasse
{
    private _MaArray1[] MonObjet1;
    private _MaArray2[] MonObjet2;

// et les accesseurs get/set classiques;
}

public class MaClasseHerite : MaClasse
{
    public void ExportQuery(string strFields, object objTable, string strCondition)
    {
        // Le nom de l'objet correspond au nom de ma table à "T_" prêt dans la requête
        string strTableName = objTable.GetType().Name;

        // Récupérer les données dans une DataTable
        DataTable dtb = clsDB.SqlRequest("SELECT " + strFields +
                                                       " FROM T_" + strTableName +
                                                       (strCondition.Length > 0 ? " WHERE " + strCondition : string.Empty));

        List<object> cmbList = new List<object>();

        foreach (DataRow drw in dtb.Rows)
        {
            object obj = Activator.CreateInstance(objTable.GetType());

            foreach (DataColumn dcl in dtb.Columns)
                foreach (PropertyInfo ppy in obj.GetType().GetProperties())
                    if (ppy.Name == dcl.ColumnName)
                        ppy.SetValue(obj, drw[dcl], null);

            cmbList.Add(obj);
        }

        if (dtb.Rows.Count > 0)
            foreach (PropertyInfo ppy in this.GetType().GetProperties())
                if (ppy.Name == strTableName)
                    ppy.SetValue(this, cmbList.ToArray(), null);
        }
}
A la dernière ligne (en gras), j'ai le message d'erreur suivant :
ArgumentException

à System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean verifyAccess, StackCrawlMark& stackMark)
à System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
à System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
à System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)
à MyNameSpace.Model.MaClasseHerite.ExportQuery(String strFields, Object objTable, String strCondition)
à MyNameSpace.Program.Main()

Mon collègue me dit de faire comme ça :
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
 
static class Program
{
    static void Main()
    {
        MaClasse mcl = new MaClasse();
 
        // Récupérer les données dans une DataTable
        DataTable dtb = clsDB.SqlRequest("SELECT Champ1,Champ2" +
                                                      " FROM T_MaArray1" +
                                                      " WHERE Champ2 = 'Test'");
 
        List<MonObjet1> cmbList = new List<MonObjet1>();
 
        foreach (DataRow drw in dtb.Rows)
            foreach (DataColumn dcl in dtb.Columns)
                {
                    MonObjet1 cbm = new MonObjet1();
 
                    cbm.Champ1 = int.Parse(drw[0].ToString());
                    cbm.Champ2 = drw[1].ToString();
 
                    cmbList.Add(cbm);
                }
 
        mcl.MaArray1 = cmbList.ToArray();
 
        // Récupérer les données dans une DataTable
        DataTable dtb = clsDB.SqlRequest("SELECT Champ3,Champ4,Champ5" +
                                                      " FROM T_MaArray2" +
                                                      " WHERE Champ5 = 'Extraire'");
 
        List<MonObjet2> cmbList = new List<MonObjet2>();
 
        foreach (DataRow drw in dtb.Rows)
            foreach (DataColumn dcl in dtb.Columns)
                {
                    MonObjet2 cbm = new MonObjet2();
 
                    cbm.Champ3 = int.Parse(drw[0].ToString());
                    cbm.Champ4 = drw[1].ToString();
                    cbm.Champ5 = drw[2].ToString();
 
                    cmbList.Add(cbm);
                }
 
        mcl.MaArray2 = cmbList.ToArray();
    }
}
 
// Intouchable car autogénéré
public partial class MaClasse
{
    private _MaArray1[] MonObjet1;
    private _MaArray2[] MonObjet2;
 
// et les accesseurs get/set classiques;
}
Bien sûr, vous l'aurez compris, il n'y a pas que 2 MaArray mais beaucoup plus. De plus, si je dois sortir un champ en plus, je dois programmer, alors qu'avec la méthode visée, je peux avoir cela dans un app.config.

Merci d'avance de m'avoir lu, j'espère m'être fait comprendre correctement sur mon besoin et surtout je suis tout ouïe de vos idées.

Edit : Erreur de transcription du code dans le Main de la demande.