2013-07-30 19 views
5

Mam problem ze zdefiniowaniem Słownika dla szybkiego dostępu do wyrażeń Lambda.C# utworzyć słownik Lambdas

Załóżmy, że mamy dobrze znaną klasę tak:

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

Co chcesz zrobić, to coś takiego:

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

Czy to możliwe?

Edit:

To jest mój przypadek użycia tego obiektu:

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

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

array.Sort(getters[sortField]); 

Wielkie dzięki za pomoc.

+0

Próbujesz zapisać 'Func ' jako typ wartości w słowniku? Czy to jest to, czego chcesz? Do czego próbujesz to wykorzystać? – gunr2171

+0

, więc chcesz przechowywać wyrażenia? – ne2dmar

+0

Czy możesz powiedzieć, czego potrzebujesz? Potem napiszemy lepsze rozwiązanie. – Epsilon

Odpowiedz

8

Masz kilka opcji. Jeśli, jak w przykładzie, to, co chcesz dostać wszystkie są tego samego typu (np String), można zrobić

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

Jednakże, jeśli są różne typy, trzeba korzystać z najniższych wspólne podklasy, które w większości przypadków będzie Object:

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

Zauważ, że będziesz wtedy musiał rzucać zwracanej wartości do swojego oczekiwanego typu.

+0

Czy rozszerzenie Linq OrderBy dobrze sobie z tym poradzi? –

+0

Według klucza, tak. Według wartości, nie do końca: delegaci nie implementują "IComparable", więc musisz napisać własny "IComparer". Jeśli jest to twoja intencja, możesz łatwiej używać wyrażeń, jak w 'Dictionary >' - ale jest to zupełnie nowy problem. – RoadieRich

+0

Przykro mi, że źle mnie zrozumiałeś, chcę to zrobić: List a; a.OrderBy (getters ["Thing1"]); Problem, który muszę rozwiązać, polega na tym, aby stworzyć dynamiczny OrderBy bez pisania mega masywnej obudowy przełącznika. Pole Sortuj pochodzi od strony klienta. –

3

Spróbuj:

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

Pierwszy generyczny parametr typ delegata Func jest typ wejścia, a drugi parametr typ rodzajowy jest typ wyjścia (wykorzystać object bo masz innego wyjścia typy). Więcej o Func: Func<T, TResult> Delegate

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

Jednak string Thing1 powinny być publiczne.

+0

Czy to działa dobrze w tym przypadku? IEnumerable .OrderBy (getters ["Thing1"]) –

1

Naprawdę myślę, że myślisz o tym w niewłaściwy sposób. Po co używać słownika? Jeśli twoja definicja klasy jest poprawna, po prostu użyj List<Example>.

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

Następnie można użyć linq na nim.

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

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

Można również użyć dynamic order by dostarczone przez Marc Gravell's answer:

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

Nie potrzeba lambdas, tylko bezpośredni dostęp do danych.

Jak już wszyscy mówili, musisz upublicznić członków. Proponuję zmienić go na:

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

Tak, rozumiem, że muszę wiedzieć, na którym polu chcę sortować za pierwszym razem. Mogę zrobić wielką zmianę, tak jak zwykle robili nas pradawni programiści. Mogę z tym żyć, ale chciałabym wiedzieć, czy DLR, TypeInference, Generics i Lambdas mogą mi dać inny sposób robienia tego. –

+0

@AdrianSalazar, więc coś w stylu 'dynamic linq'? http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx – gunr2171

+0

Tak, mam rację, ale ja "W ogóle nie mam połączenia z SQL ... i nie chcę uratować świata w jeden dzień i sprawić, że będzie mega-generyczny. Jeśli działa z tą konkretną klasą, to wystarczy. –