2013-07-30 28 views
5

Ho difficoltà a definire un dizionario per l'accesso rapido alle espressioni Lambda.C# make a Dictionary of Lambdas

Supponiamo di avere una classe ben noto come questo:

class Example 
{ 
    public string Thing1; 
    public DateTime Thing2; 
    public int Thing3; 
} 

Che voglio fare è qualcosa di simile:

var getters = new Dictionary<string, IDontKnowWhatGoesHere>(); 
getters.Add("Thing1", x => x.Thing1); 
getters.Add("Thing3", x => x.Thing3); 

è possibile?

Edit:

Questo è il mio caso d'uso per questo oggetto:

List<Example> array = new List<Example>(); 

// We actually get this variable set by the user 
string sortField = "Thing2"; 

array.Sort(getters[sortField]); 

Molte grazie per il vostro aiuto.

+0

Si sta tentando di memorizzare un 'Func 'come tipo di valore nel dizionario? È questo che vuoi? Per cosa stai cercando di usare questo? – gunr2171

+0

quindi vuoi memorizzare le espressioni? – ne2dmar

+0

Puoi dire di cosa hai bisogno? Quindi scriveremo una soluzione migliore. – Epsilon

risposta

8

Hai un paio di opzioni. Se, come nel tuo esempio, le cose che si vogliono ottenere sono tutti dello stesso tipo (ad esempio String), si può fare

var getters = new Dictionary<string, Func<Example, String>>(); 

Tuttavia, se sono tipi diversi, è necessario utilizzare il più basso sottoclasse comune, che nella maggior parte dei casi sarà Object:

var getters = new Dictionary<string, Func<Example, object>>(); 

Nota che avrete quindi bisogno di lanciare il valore di ritorno nel vostro tipo previsto.

+0

Estensione Linq OrderBy funziona bene su questo? –

+0

Per chiave, sì. Per valore, non proprio: i delegati non implementano 'IComparable', quindi dovrai scrivere il tuo' IComparer'. Se è questa la tua intenzione, potresti trovare più semplice usare le espressioni, come in 'Dictionary >' - ma questo è un problema completamente nuovo. – RoadieRich

+0

Mi dispiace che tu mi abbia sbagliato, voglio fare questo: Lista a; a.OrderBy (getter [ "thing1"]); Il problema che ho bisogno di risolvere è quello di rendere dinamico OrderBy senza scrivere il caso di switch enorme. Il campo Ordina proviene dal lato client –

3

Prova:

var getters = new Dictionary<string, Func<Example, object>>(); 
getters.Add("Thing1", x => x.Thing1); 
getters.Add("Thing3", x => x.Thing3); 

Il primo parametro di tipo generico della Func delegato è il tipo di ingresso, e il secondo parametro di tipo generico è il tipo di uscita (utilizzare object perché hai output diverso tipi). più su Func: Func<T, TResult> Delegate

3
var getters = new Dictionary<string, Expression<Func<Example, object>>>(); 

Tuttavia, string Thing1 dovrebbe essere pubblico.

+0

Funzionerà bene in questo caso? IEnumerable .OrderBy (getter ["Thing1"]) –

1

Penso davvero che stai pensando a questo nel modo sbagliato. Perché usare un dizionario? Se la definizione della classe è corretta, utilizzare solo uno List<Example>.

List<Example> dataList = new List<Example>(); 
dataList.Add(new Example { Thing1 = "asdf", Thing2 = "qwert", Thing3 = 2 }); 

Quindi è possibile utilizzare linq su di esso.

IEnumerable<Example> sortedByT3 = dataList.OrderBy(x => x.Thing3); 

sortedByT3.Last().Thing2 = "hjkl"; 

È possibile anche utilizzare un dynamic order by fornito da Marc Gravell's answer:

var sortedByString = dataList.AsQueryable().OrderBy("Thing2"); 

Non c'è bisogno di lambda, solo l'accesso diretto ai dati.

Come tutti hanno detto, è necessario rendere pubblici i membri. Suggerirei di modificarlo come segue:

public class Example 
{ 
    public string Thing1 { get; set; } 
    public string Thing2 { get; set; } 
    public int Thing3 { get; set; } 
} 
+0

Sì, ho capito, il punto è che ho bisogno di sapere su quale campo voglio ordinare la prima volta. Quindi posso creare un grande caso come i nostri programmatori antichi normalmente. Posso conviverci, ma mi piacerebbe sapere se DLR, TypeInference, Generics e Lambdas possono darmi un altro modo di farlo. –

+0

@AdrianSalazar, quindi qualcosa come 'linq dinamico '? http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx – gunr2171

+0

Sì, hai capito, ma io Non sono affatto collegato a SQL ... e non voglio salvare il mondo in un giorno e renderlo mega-generico. Se funziona con questa particolare classe, allora è abbastanza. –