Jak obsłużyć tabele z dynamiczną ilością kolumn i właściwości

0

Cześć,
czy w c# jest możliwość stworzenia klasy dynamicznie tj. w trakcie wykonywania się programu a następnie utworzyć na jej podstawie obiekt?

Chodzi o to, że dostaję od użytkownika informację o tym z jakich elementów klasa ma się składać (jakie ma mieć właściwości tj. jak mają się nazywać oraz jakiego typu mają być) a następnie otrzymuję dużo danych, które chciałbym zapisać w tablicy obiektów takiego typu, który stworzyłem. Czy jest to możliwe?

4

Tak jest to możliwe, za pomocą Roslyn API można skompilować dowolny kod, wczytać go do pamięci i używać w tym samym procesie.

Ale raczej tego nie potrzebujesz, nie lepiej po prostu zamodelować każdą właściwość jako oddzielny obiekt?

0

To może lepiej opiszę o co mi chodzi:
Piszę sobie apkę w blazorze (to w sumie może mieć znaczenie).
Aplikacja ma wyświetlać m.in. tabelę z różnymi danymi. Liczba kolumn do wyświetlenia jest nieokreślona (user określa które dane chce pobierać). Kolumny mogą być różnych typów, ale są one określone (przed pobraniem danych user otrzymuje informację jakiego typu są dane, które pobiera). Wszystkie dane będą przesyłane w postaci tablicy stringów.
Mogę oczywiście trzymać sobie dane cały czas w tablicy stringów (tj. List<List<string>>) i na niej wykonywać różne operacje, ale dużo łatwiej by było, gdybym mógł przekonwertować dane na właściwy typ i trzymać je w obiekcie tj. mieć tablicę obiektów (List<DynamicType>).
Zależy mi również na wydajności - danych będzie bardzo dużo, a nie chcę wielokrotnie konwertować danych (chciałbym to zrobić raz).

5

Ten problem można z łatwością rozwiązać bez generowania kodu w trakcie działania, każda właściwość/kolumna niech będzie oddzielnym obiektem, można sobie nawet stworzyć dedykowane kolumny do obsługi specyficznych zachowań dla danych typów, szkielet w teń deseń widzę :

     class Row
        {
            List<IColumn> Columns = new List<IColumn>();
        }

        interface IColumn
        {

            void DoSomethig();
            string GetStringRepresentation();
        }



        class BaseColumn<T> : IColumn
        {
            T value;

            public virtual void DoSomethig()
            {
                
            }

            public virtual string GetStringRepresentation()
            {
                return value.ToString();
            }
        }
0

Przyznam, że nie do końca rozumiem Twoją ideę :/
Ty korzystasz z klasy generycznej, która wymaga podanie typu w momencie kompilacji. A ja nie znam typu w momencie kompilacji - to user określa które dane będzie pobierał i ile ich będzie a to determinuje typ.

Przykład:
Pobierasz z jakiegoś WebApi dane, które mogą wyglądać tak (inny user może pobierać inne kolumny - innych typów):

"NazwaKolumny1", "NazwaKolumny2", "NK3", "NK4"... //nazwy kolumn
"string", "decimal", "int", "string"... //typy danych
"Jakiś napis", "123.45M", "123", "Kolejny napis", ... //dane - pierwszy wiersz
"Inny napis", "321.11M", "111", "napis", ... //dane - drugi wiersz
... //itd.

W momencie kompilacji ja nie wiem jakiego typu będą to kolumny, dlatego typ generyczny odpada.

Rozważałem zrobienie klasy, która będzie przechowywać tablicę każdego z wykorzystywanych typów tj.:

class Row
{
public string[] string_list;
public decimal[] decimal_list;
public int[] int_list;
... itd.
}

I mając informację jakie kolumny mają być pobrane wrzucać je do takiego obiektu, ale nie wiem czy to dobry pomysł...
Oczywiście miałbym listę takich obiektów - jeden obiekt to jeden wiersz z danymi.

1

User podaje ci które kolumny chce
Ty je pobierasz z bazy i zwracasz

a masz robić coś poza zwróceniem/wyświetleniem tego? bo jeżeli nie, to może wystarczy https://stackoverflow.com/questions/16516971/linq-dynamic-select i od razu zamienienie tego na jsona

4
Kofcio napisał(a):

Przyznam, że nie do końca rozumiem Twoją ideę :/

if (columnType == ColumnType.String)
    lista.Add(new Column<string>(columnData))
else if (columnType == ColumnType.Int)
    lista.Add(new Column<int>(columnData))
...

a jeszcze lepiej utworzyć do tego fabrykę i ładnie to opakować

0

@1a2b3c4d5e wydaje mi się, że problem jest z innej strony. Ja nie mam problemu z wysłaniem danych z bazy danych do usera - to będzie wysyłane jako tablica stringów (nie potrzebuję jsona). Problem jest po stronie usera tzn. z punktu widzenia aplikacji, która pobiera dane (każdy user korzystający z aplki może pobierać innego typu dane).
@abrakadaber faktycznie, już rozumiem... dzięki :)

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