Generyczna Lista T problem z przeciazeniem funkcji

0

Czesc mam wrazenie ze robie cos nie tak w C# bo kompilator robi sobie ze mnie jaja ale do rzeczy w moim repo duzo funkcji wyglada tak:



        public CommonModel GetLocations(IModelWithCurrentUser<xyz> model)
        {
            var sqlParameters = SqlHelpers.GetReportSqlParameters(model);
            var outputParameters = new Dictionary<string, object>() { { "TotalCount", default(int) } };
            var result = _queryExecutor.QueryWithOutputParameters<Locations>(PermissionsQueries.GetLocations, sqlParameters, outputParameters);
            var totalCount = Convert.ToInt32(outputParameters["TotalCount"]);
            return RepositoryConverter.ToCommonDSModel(result, model.Content, totalCount);
        }

Chcialem napisac generyka by kod sie nie powtarzal:


        public CommonModel GetSqlReport<T>(IModelWithCurrentUser<xyz> model, string queryName)
        {
            var sqlParameters = SqlHelpers.GetReportSqlParameters(model);
            var outputParameters = new Dictionary<string, object>() { { "TotalCount", default(int) } };
            var result = _queryExecutor.QueryWithOutputParameters<T>(queryName, sqlParameters, outputParameters);
            var totalCount = Convert.ToInt32(outputParameters["TotalCount"]);
            return RepositoryConverter.ToCommonDSModel(result, model.Content, totalCount);
        }

Problem jest taki ze metoda ToCommonDSModel jest przeciazana po typie listy w 1 parametrze na zasadzie:


public static CommonModel ToCommonDSModel(List<Roles> data, xyz dtoModel, long itemsCount)
public static CommonModel ToCommonDSModel(List<Locations> data, xyz dtoModel, long itemsCount)
public static CommonModel ToCommonDSModel(List<abc> data, xyz dtoModel, long itemsCount)

Finalnie dostaje blad bo on niestety probuje rzutowac list<T> na jakis typ ktory wystepuje w metodzie ToCommonDSModel. Wujek google milczy na temat wiec wydaje mi sie ze robie cos zle :/. Moje pytanie jest proste czy idzie w jakis sensowny sposob napisac generyka tak by pozbyc sie tego powtarzajacego kodu z repo?

Blad:

cannot convert from 'System.Collections.Generic.List<T>' to 'System.Collections.Generic.List<Roles>'

1

Da się to pewnie obejść zamieniając :

 var result = _queryExecutor.QueryWithOutputParameters<T>(queryName, sqlParameters, outputParameters);

na

dynamic result = _queryExecutor.QueryWithOutputParameters<T>(queryName, sqlParameters, outputParameters);

ale to stąpanie po kruchym lodzie, cały ten kod też wygląda jak proszenie się o kłopoty.

Ogólnie rzecz biorąc algorytm wybierania przeciążonej metody to jedna z najtrudniejszych rzeczy jaka występuje w specyfikacji języka C#, i moim ogólnym zaleceniem jest używanie przeciążeń naprawdę w ostateczności.

0

@neves: dobra robota :0 kompiluje sie. Zastanawiam sie czemu nie widzi problemu w rzutowaniu dynamic na list ale sprawdze jak dziala w boju :D. Akurat tutaj kolopotow nie powinno byc bo typ jest podany w _queryExecutor.QueryWithOutputParameters<T> w nawisach ostrych a zwrotka juz ma swoj typ.

Co do przeciazen to zwykle same jak dla mnie wchodza do glowy jak je uzyc :) sprobuje z tym i dam znac czy wszsytko bangala good

1

Rozwiązanie z SO jest nieskończenie lepsze niż używanie dynamic, które jest po prostu swego rodzajem hinduskiego brute-force.

A problem leży w designie, bo ToCommonDSModel także powinno być generyczne.

1

Tak po bożemu to ten konwerter powinien być pobierany z jakiegoś factory dla danego typu. Czyli miałbyś wiele klas konwerterów dziedziczących z abstracta i/lub implementujących interfejs, a te przeciążenia byłyby implementowane w poszczególnych klasach.

Tak bym to zrobił Jest to jednak spory narzut i sens implementacji takiego czegoś zależy od skali projektu i czy używasz kontenera i dependency injection.

EDIT: Możesz zrobić obejście w postaci generycznej metody, w której miałbyś switcha po typie wywołującego odpowiednią implementację. Ale tak jak mówię, to jest dla mnie obejście, nie dobre rozwiązanie.

0

Factory nawet nie jest zle tylko nie przepisze calego API :D myslem o czyms bardziej na mniejsza skale tak by chociaz w swoich kawalkach kod zredukowac i uniknac duplikowania kodu :). Wlasnie switch po typie to jak dla mnie przeada gruba przesada wole miec chyba te 5 linii kopiownaych niz jakies switch po typie walic. Zostane chyba przy tym nieszczesnym dynamic :D

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