Jak sprytnie zapakować metodę w typ

Odpowiedz Nowy wątek
2018-12-15 10:33
Trzeźwy Pomidor
0

cześć

Mam taki kod:

public enum SortingOption
    {
        AZ,
        ZA,
        PriceDescending,
        PriceAscending
    }

i teraz chciałbym na podstawie tego enuma pozyskać odpowiednią funkcję sortującą, czyli coś w tym stylu:

private Func<Product, string> GetSortingFunc(SortingOption sortingOption)
        {
            switch (sortingOption)
            {
                case SortingOption.AZ:
                    return product => product.Name;

                case SortingOption.ZA:
                    break;
                case SortingOption.PriceDescending:
                    return product => product.Price;

                case SortingOption.PriceAscending:
                    break;
                default:
                    break;
            }
        }

Tutaj pojawia się problem taki, że sortowanie po cenie wymaga Func z typem decimal, a po nazwie z typem string... Kolejny problem to rozróżnienie sortowania rosnąco i malejąco - musiałbym zwracać metodę Linq OrderBy lub OrderByDescending ale jak to zrobić zeby zwracać cos w stylu OrderByDescending(product => product.Price? Ostatecznie miałoby to wyglądać tak:

        private ???? GetSortingFunc(SortingOption sortingOption)
        {
            switch (sortingOption)
            {
                case SortingOption.AZ:
                    return OrderBy(product => product.Name);

                case SortingOption.ZA:
                    return OrderByDescending(product => product.Name);

                case SortingOption.PriceDescending:
                    return OrderBy(product => product.Price);

                case SortingOption.PriceAscending:
                    return OrderByDescending(product => product.Price);

                default:
                    break;
            }
        }

Pozostało 580 znaków

2018-12-15 10:37
0

Może lepiej użyć wzorca strategii ?
http://www.altcontroldelete.p[...]zykladowa-implementacja-w-c-/

Pokaż pozostałe 2 komentarze
po co jakiś wzorzec gdy mamy dynamic query building na delegatach? - WeiXiao 2018-12-15 14:24
A możesz rzucić jakimś przykładem? - szydlak 2018-12-15 14:41
Masz tabelkę, którą user może sobie przeszukiwać jak chce - po jednej kolumnie, po trzech, po 10, po 0. I można to fajnie)według mnie) poskładać przy tym podejściu, które stosuje OP. - WeiXiao 2018-12-15 14:43
Miałem na myśli konkretny przykład :P, link do gita cokolwiek - szydlak 2018-12-15 14:44

Pozostało 580 znaków

2018-12-15 10:57
Trzeźwy Pomidor
0

Tez o tym myslalem, ale wczesniej wywołuje na obiekcie repozytorium kilka innych metod jak Where,Select,Take,Skip i chcialbym do tego po prostu dodać odpowiednią funkcje sortującą. Przy wykorzystaniu wzorca musiałbym przesłać do strategii cały obiekt repozytorium tylko po to, żeby wykonać na nim sortowanie... Słabe :(

Pozostało 580 znaków

2018-12-15 11:36
Trzeźwy Pomidor
0

wymyśliłem cos co spełnia moje poczucie sprytności:

public static IOrderedEnumerable<Product> SortBy(this IEnumerable<Product> products, SortingOption sortingOption)
        {
            switch (sortingOption)
            {
                case SortingOption.AZ:
                    return products.OrderBy(p => p.Name);

                case SortingOption.ZA:
                    return products.OrderByDescending(p => p.Name);

                case SortingOption.PriceAscending:
                    return products.OrderBy(p => p.Price);

                case SortingOption.PriceDescending:
                    return products.OrderByDescending(p => p.Price);

                default:
                    return null;
            }
        }

jakby ktos mial lepszy pomysł to chetnie poznam

Pozostało 580 znaków

2018-12-15 11:45
0

Może powiedz co chcesz konkretnie osiągnąć bo ten kod wygląda śmierdząco. Co jak będziesz potrzebował posortować po cenie a potem po nazwie ? Co jak dojdzie pole do modelu ? Dodać następnego enuma ? Do doprowadzi do tragedii za jakiś czas :D Dla zamówień też stworzysz identyczną metodę ?

edytowany 2x, ostatnio: error91, 2018-12-15 11:47

Pozostało 580 znaków

2018-12-15 12:12
Trzeźwy Pomidor
0
error91 napisał(a):

Może powiedz co chcesz konkretnie osiągnąć bo ten kod wygląda śmierdząco. Co jak będziesz potrzebował posortować po cenie a potem po nazwie ? Co jak dojdzie pole do modelu ? Dodać następnego enuma ? Do doprowadzi do tragedii za jakiś czas :D Dla zamówień też stworzysz identyczną metodę ?

W 1 poscie wytlumaczylem co chce zrobic: posortowac repo na podstawie Enuma SortingOption.

Co jak będziesz potrzebował posortować po cenie a potem po nazwie ?

Nie rozumiem o co ci chodzi. Towar sortuje po cenie LUB po nazwie, nie ma znaczenia tutaj kolejnosc.

Co jak dojdzie pole do modelu
Jeśli dojdzie np pole IsOnStock, dodam do enuma taka wartosc i do mojej metody np products.Where(p => p.IsOnStock), nie ma problemu

Dla zamówień też stworzysz identyczną metodę ?

Nie mam jeszcze zamówień i nie pomyślałem o tym, ale pewnie będe się starał zrobić tą metodę generyczną, działającą dla Produktów i Zamówień

Pozostało 580 znaków

2018-12-15 14:28
1

Jak rozumiem, to leci do bazy? jeżeli tak, to lepiej sprawdź jak to się wykona pod spodem :D

Pozostało 580 znaków

2018-12-15 16:45
Trzeźwy Pomidor
0
WeiXiao napisał(a):

Jak rozumiem, to leci do bazy? jeżeli tak, to lepiej sprawdź jak to się wykona pod spodem :D

Nie leci do bazy. Po co w ogóle sortować dane przed zapisaniem do bazy? To jest pobieranie danych z bazy i prezentowanie ich klientowi

Pozostało 580 znaków

2018-12-15 17:12
1

A kto tu mówi o sortowaniu przed zapisem ? Jeśli budujesz z tego LINQ i działasz na IQueryable to to poleci do bazy. W innym wypadku posortujesz to w pamięci.

Pozostało 580 znaków

2018-12-15 17:56
1
Trzeźwy Pomidor napisał(a):

To jest pobieranie danych z bazy i prezentowanie ich klientowi

Jak chcesz prezentować, to po co Ci w ogóle jakieś repozytorium? Nie do tego służy ten wzorzec.

Powinieneś mieć metodę, która zwraca Expression, tak aby mogła zostać wydajnie przetworzona przez ORM na sensowny SQL. Pobieranie całej bazy, jak to robisz teraz, nie jest raczej dobrym pomysłem. A poza tym, czy ten enum jest w ogóle dobrym pomysłem? Nie lepiej po prostu przekazać z GUI nazwę właściwości i kierunek sortowania? Da to znacznie większą elastyczność.


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."
Pokaż pozostałe 17 komentarzy
@error91 - ale jak można nie robić na stringach? Jak z GUI dostaniesz gotowy expression, np. gdy user kliknie w kolumnę grida? - somekind 2018-12-18 02:52
@somekind: Miałem na myśli budowe całego expression ze stringa z użyciem Roszlyna np: var discountFilter = "album => album.Quantity > 0"; var options = ScriptOptions.Default.AddReferences(typeof(Album).Assembly); Func<Album, bool> discountFilterExpression = await CSharpScript.EvaluateAsync<Func<Album, bool>>(discountFilter, options); var discountedAlbums = albums.Where(discountFilterExpression); Dla mnie to hardcore :D - error91 2018-12-18 06:49
wtf z tym Roslyn? nie żebym miał coś przeciwko, ale na 99% da się to zrobić prościej. W ogóle obawiałbym się o to, że takie wstawki do CSharpScripting to luka w bezpieczeństwie - WeiXiao 2018-12-18 18:25
Na szczęście nie spotkałem z tym na produkcji, ale znam ludzi którzy jakby wiedzieli, że się tak da, to by używali :) - error91 2018-12-18 18:32
No zaprzęgać do tego Roslyna to lekkie przegięcie, a po drugie mocne utrudnienie. Z GUI i tak wszystko przychodzi jako tekst, wystarczy z tego zbudować normalne, ludzkie expressiony i wysłać do ORMa. - somekind 2018-12-18 23:30

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0