Domanda

Questo è un esercizio "Vediamo se si può fare" più di ogni altra cosa.

Supponiamo di avere un dati dataTable con diverse colonne. Usando LINQ, è possibile selezionare le righe della tabella in modo tale che il risultato sia una sequenza di un tipo anonimo in cui ogni proprietà del tipo anonimo è denominata in base al nome della colonna del dati e il tipo di proprietà è impostato appropriatamente.

Quindi, se il mio dati dati ha tre colonne come così:

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

Quindi voglio selezionare tutte le righe del dati in modo tale che il tipo anonimo abbia tre proprietà:

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);
}

So che posso farlo:

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);
}

Ma ciò richiede la codifica hard i nomi delle proprietà nella nuova clausola, mentre vorrei che i nomi delle proprietà provenissero dalla raccolta delle colonne del dataTable.

Spero di averlo spiegato abbastanza chiaramente. Dopo aver giocato con questo per un po ', sto cominciando a pensare che tutto ciò che mi viene in mente sarà un grosso disastro per quanto riguarda la leggibilità e la manutenibilità, ma ho pensato di chiedere.

È stato utile?

Soluzione

Temo che non ci sia tale magia (almeno non con tipi anonimi). I tipi anonimi sono tipi impliciti generati dal compilatore come classi immutabili con le loro proprietà denominate e digitate dall'operazione di assegnazione esplicita come nel secondo esempio (al momento della compilazione).

Quello che vuoi fare richiederebbe un tipo dinamico costruito in fase di esecuzione.

Altri suggerimenti

Come già stabilito nella risposta di Brandon, questo non può essere fatto con tipi anonimi, poiché vengono generati al momento della compilazione. Tuttavia, come accennato, puoi utilizzare le dinamiche per ottenere una sintassi simile.

Ad esempio, potresti ottenere la seguente sintassi (in base al tuo esempio):

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);
}

Utilizzo di un semplice wrapper dinamico per i tuoi 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;
    }
}

Non sono esattamente sicuro di quale sia il tuo caso d'uso, ma spero che questo ti aiuti nella giusta direzione se decidi che le dinamiche sono un sostituto accettabile per i tipi anonimi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top