Question

C'est un exercice "voyons si cela peut être fait" plus que toute autre chose.

Supposons que j'ai un DataTable avec plusieurs colonnes. En utilisant linq, est-il possible de sélectionner les lignes de la table de telle sorte que le résultat soit une séquence d'un type anonyme où chaque propriété du type anonyme est nommée en fonction du nom de colonne du DataTable et le type de chaque propriété est défini de manière appropriée.

Donc, si mon DataTable a trois colonnes comme ceci:

Name = "Column1",  DataType = string
Name = "Column2",  DataType = integer
Name = "Column3",  DataType = bool

DataSet ds = functionThatGetsADataSet();
var seq = ds.Tables[0].AsEnumerable().Select( r => **** MAGIC HERE ****)

foreach (var s in seq)
{
    Console.WriteLine(s.Column1);
    Console.WriteLine(s.Column2);
    Console.WriteLine(s.Column3);
}

Je sais que je peux faire ceci:

DataSet ds = functionThatGetsADataSet();
var seq = ds.Tables[0].AsEnumerable().Select( r => 
   new 
   {
       Column1 = r.Field<string>("Column1"),
       Column2 = r.Field<int>("Column2"),
       Column3 = r.Field<bool>("Column3"),
   }
)

foreach (var s in seq)
{
    Console.WriteLine(s.Column1);
    Console.WriteLine(s.Column2);
    Console.WriteLine(s.Column3);
}

mais cela nécessite un codage en dur des noms de propriété dans la nouvelle clause, alors que je voudrais que les noms de propriété proviennent de la collection Columns du DataTable.

J'espère avoir expliqué cela assez clairement. Après avoir joué un peu avec ça, je commence à penser que tout ce que je proposerai sera un gros gâchis en ce qui concerne la lisibilité et la maintenabilité, mais j'ai pensé que je demanderais.

Était-ce utile?

La solution

J'ai peur qu'il n'y ait pas de telle magie (du moins pas avec les types anonymes).Les types anonymes sont des types implicites générés par le compilateur en tant que classes immuables avec leurs propriétés nommées et typées par l'opération d'affectation explicite comme dans votre deuxième exemple (au moment de la compilation).

Ce que vous voulez faire nécessiterait un type dynamique construit au moment de l'exécution.

Autres conseils

Comme déjà établi dans la réponse de Brandon, cela ne peut pas être fait avec les types Anonymes, car ils sont générés au moment de la compilation.Cependant, comme mentionné, vous pouvez utiliser la dynamique pour obtenir une syntaxe similaire.

Par exemple, vous pouvez obtenir la syntaxe suivante (basée sur votre exemple):

var seq = table.AsEnumerable().Select(row => (dynamic)new DynamicDataRow(row));
foreach (var s in seq)
{
    Console.WriteLine(s.Column1);
    Console.WriteLine(s.Column2);
    Console.WriteLine(s.Column3);
}

Utilisation d'un simple wrapper dynamique pour vos DataRows:

class DynamicDataRow : DynamicObject
{
    private readonly DataRow row;

    public DynamicDataRow(DataRow row)
    {
        this.row = row;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        DataColumn column = row.Table.Columns[binder.Name];
        if (column != null)
        {
            result = row[column];
            return true;
        }

        result = null;
        return false;
    }
}

Je ne sais pas exactement quel est votre cas d'utilisation, mais j'espère que cela vous aidera à vous orienter dans la bonne direction si vous décidez que la dynamique est un substitut acceptable aux types anonymes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top