Mechanizm zarządzania obiektami (refleksja?)

0

Witam wszystkich

Nurtuje mnie pewna myśl, a mianowicie ciekawi mnie czy C# posiada mechanizm do zarządzania obiektami czyli np. mam obiekt:

 
class Obiekt1
{
    public string nazwa;
    private int liczba;
    private double wartosc;
    public string Nazwa { get {return nazwa; } set { nazwa = value; } }
    public int Liczba { get { return liczba; } set { liczba = value; } }
}

I na przykład:
- chciałbym sprawdzić czy wszystkie wartości są prywatne, a gettery i settery publiczne i mieć możliwość zmiany wartości z publicznej na prywatną
- mieć możliwość stworzenia gettera i settera dla jakiejś wartości, jeżeli go nie ma
- dostać listę wszystkich wartości w jakiejś tablicy

Wiem, że mogę analizować plik tekstowy klasy i dokonać tych zmian, a potem rekompilować program przy pomocy mechanizmu refleksji, ale moje pytanie jest takie - czy ktokolwiek z Was się spotkał z mechanizmami wspomagającymi powyższe operacje.

0

ReSharper ma wiele pomocnych opcji, np. opcję nr 2 pokryje, hmmm czy nr 1, na pewno da się różne opcje sprawdzania jakiejś poprawności wg siebie tam uwzględnić
ale nr 3, lista wartości w tabicy, to chyba troche pojęcia pomyliłeś, bo w pkt 1 i 2 pytasz o jakieś możliwości walidacji kodu w pliku, a pkt 3 wg mnie związany jest już z runtime, kiedy obiekt żyje i ma konkretne wartości (w tym przypadku tablica)
poza tym czy ty chcesz modyfikować definicję klas w runtime?

0

Hm, ty chcesz to w runtime robić?

Aż mi się przypomniało w jaki genialny pomysł "schakierowałem" raz aplikację, która miała kilka prywatnych klas, które miały metody zwracające sprytnie oczywiście klucze do szyfrowania. Był też jakiś jeszcze sprytniejszy obfuskator, który wywalał Reflectora. To zrobiłem "ildasm", otworzyłem w notatniku (32mb plik!), znajdź/zamień, "private" na "public", zapisz, "ilasm", dołączyłem referencję i.. wystarczyło wywołać odpowiednią metodę ;P.
.NET otwarty jak nigdy.

0

poza tym czy ty chcesz modyfikować definicję klas w runtime?

Dokładnie tak, a przynajmniej w runtime mieć możliwość sprawdzenia struktury klas np. przelecieć po wszystkich polach klasy i sprawdzić, czy mają settery i gettery, a jak nie to wypisać te, które ich nie mają. Biorąc pod uwagę, że w moim prostym kodzie setter/getter zaczyna się dużą literą i ma taką samą nazwę jak zmienna to w __pseudokodzie __ wyglądało by to następująco:

 
Obiekt1 o = new Obiekt1();
foreach(Pole pole in o)
{
    string pierwszaLitera(pole.Name.ToString(), 0, 1);
    if(pierwszaLitera == isLowerCase && pole.Operator == public)
        Console.WriteLine("Pole " + pole.Name + " jest do bani."); 
        //lub zamień public na private itd.
}

Generalnie plan jest taki, żeby stworzyć aplikację, która sama będzie się modyfikowała i rekompilowała i dodatkowo sprawdzała poprawność swoich klas. Na przykład tworzyła swoje własne połączenie do bazy danych i co jakiś czas sprawdzała, czy baza się nie zmodyfikowała i jeżeli tak, to doda lub odejmie określone pola, a potem sprawdzi, czy aby wszystko na pewno jest ok - sama wykryje błąd w generowanym prze siebie kodzie.

0
LukTar napisał(a)

Dokładnie tak, a przynajmniej w runtime mieć możliwość sprawdzenia struktury klas np. przelecieć po wszystkich polach klasy i sprawdzić, czy mają settery i gettery, a jak nie to wypisać te, które ich nie mają.

Czyli potrzebujesz normalnej refleksji. W czym konkretnie problem?

0

LuKTar chyba próbujesz iść pod wyjątkowo stromą górę.

stworzyć aplikację, która sama będzie się modyfikowała i rekompilowała i dodatkowo sprawdzała poprawność swoich klas.

no tak, ale co z tego, że będziesz miał klasy spójne ze strukturą bazy? (poza tym OR Mappera do tego użyj) Liczy się jeszcze jakaś logika biznesowa spinająca klasy, pola, tworząca powiązania, zależności etc. Baza relacyjna a model obiektowy trochę się różnią.

Może napisz dokładniej co chcesz zrobić. Założę się, że już ktoś wymyślił taki scenariusz jak ty i co lepsze wymyślił jak to rozwiązać. Jak na razie jesteś na najlepszej drodze do stworzenia potworka, takiego Frankensteina. :)

0

Jak na razie jesteś na najlepszej drodze do stworzenia potworka, takiego Frankensteina. :)

Haha dokładnie tak.
Właśnie w tych wszystkich ORM'ach (a znam się trochę na EF 4.0 i EntitySpaces) denerwuje mnie to, że trzeba uruchamiać odświeżenie wszystkich klas kiedy coś się w bazie danych zmieni i nie można o tym myśleć warstwowo czyli powiedzmy, że mamy:

SERWER BAZY DANYCH -------- ORM -> PROGRAM

w tej sytuacji po każdej zmianie bazy musimy odśwież konkretne tabele w ORM'ie, żeby skorzystać poprzez niego z bazy danych. Dodatkowo wymaga to rekompilacji programu
A teraz taka sytuacja:

SEREWR BAZY DANYCH + PROGRAM POŚREDNI ----------- PROGRAM

PROGRAM POŚREDNI cały czas bada bazę danych i jeżeli jakaś zmiana nastąpi to się sam aktualizuję, a PROGRAM łączy się z PROGRAMEM POŚREDNIM i pobiera od niego to co chce. Wystarczy, że do bazy dodamy sobie procedurę coś zwracającą/modyfikującą to od razu będzie widoczna w PROGRAMIE i będzie można z niej skorzystać.
Przykładowy scenariusz: ja dodaje do bazy procedurę która mi zwraca kolumnę nazwa i cena z tabeli produkt, mój SuperRuntimeUniversOrmTerminator tworzy sobie obiekt, który zwróci procedura - w tym przypadku

 
class NazwaMetodyZBD_Obiekt
{
    public string nazwa;
    public string cena;
}
class MetodyZBD
{
    //...
    public List<NazwaMetodyZBD_Obiekt> nazwaMetody(/*parametry*/)
    {
        //wykonaj metody i zwróć wartośc
    }
    //...
}

A ja po stronie programu nic nie muszę robić, tylko odwołuję się do znanej mi metody i otrzymuję wynik w postaci przygotowanego obiektu :).

Nie wiem, czy ktoś mnie zrozumiał :).

W Javie spotkałem się z takim mechanizmem:

Class c = Class.forName(className);
Field []f =  c.getDeclaredFields();
Method[] m = c.getMethods();

W C# było to strasznie toporne, ale tutorial z którego korzystałem był dla starej wersji C# więc myślałem, że ktoś zna jakieś ułatwienia.
Nic to - kupiłem sobie dobrą książkę wczoraj i zacząłem przeglądać tutoriale z refleksji w C#. Jak coś z tego wyjdzie to napiszę :).

0

Refleksja w C# jest bardzo podobna. Co konkretnie jest "toporne"?

Nie wystarczyłby Ci po prostu jakiś designer do ORMa?

1

czyli chcesz mieć jakąś warstwę pośrednią dostarczającą dane (program pośredni), mogą to być np. webservice, wcf etc. a usługi z tego hosta konsumowane są przez twój program
wydaje mi się, że chcesz utrudnić sobie zadanie, a jakiś szczególnych zysków nie widzę
otóż lepiej warstwę pośrednią (dostępu do danych/usług) zaprojektować tak, aby na podstawie jakiejś konfiguracji, warstwa w runtime wywoływała odpowiednie procedury oraz zwracała odpowiednio sformatowane dane, do tego celu nie musisz dla każdej procedury, czy zwracanego obiektu mieć jakiejś klasy, np. webservice jest tu doskonałym przykładem

poza tym to że zmiany pojawią sie w warstwie pośredniej, to nie znaczy że progam będzie w stanie sobie z nimi poradzić i tam musisz dokonać tam modyfikacji logiki biznesowej, bo z tego co opisałeś jeśli logiki biznesowej miałoby tam nie być, to jedynym innym miejscem gdzie mogłaby być jest - baza danych. Wierz mi nie chcesz mieć systemu, gdzie logika biznesowa jest na poziomie procedur składownych, funkcji, triggerów etc. Widziałem kilka takich potworków, to była tragedia do rozwoju, bo zanim namierzyło się co gdzie jest to schodziło kilka, kilkanaście godzin

ale jeśli upierasz się przy swoim, lepiej zrób sobie jakiś skrypt w msbuild (czy ant), który za jednym wywołaniem przekompiluje ci warstwe pośrednią, a nawet dokona odpowiednich podmian plików restartu usług etc.

0

Refleksja w C# jest bardzo podobna. Co konkretnie jest "toporne"?

Dawno się tym nie zajmowałem, bo nie było mi potrzebne, ale rzeczywiście jak teraz przeglądam tutoriale i artykuły to nie wydaje się taka skomplikowana i przerażająca jak o niej myślałem :).

Nie wystarczyłby Ci po prostu jakiś designer do ORMa?

Niestety żaden ORM nie spełniał moich oczekiwań szczególnie podczas modyfikacji bazy danych. Generowane zapytania przy większym poziomie skomplikowania i dużej bazie danych są tragicznie niewydajne. Poza tym myślę o tym, żeby iść trochę do przodu i zrobić coś bardziej elastycznego.

otóż lepiej warstwę pośrednią (dostępu do danych/usług) zaprojektować tak, aby na podstawie jakiejś konfiguracji, warstwa w runtime wywoływała odpowiednie procedury oraz zwracała odpowiednio sformatowane dane, do tego celu nie musisz dla każdej procedury, czy zwracanego obiektu mieć jakiejś klasy, np. webservice jest tu doskonałym przykładem

Nie do końca rozumie. Właśnie przez próbę przesłania danych, które pobieram za pomocą EF 4.0 z bazy danych poprzez sieć przy użyciu WebService powstał ten temat :). O jakim sposobie formatowania danych myślisz?

poza tym to że zmiany pojawią sie w warstwie pośredniej, to nie znaczy że progam będzie w stanie sobie z nimi poradzić i tam musisz dokonać tam modyfikacji logiki biznesowej,

Bardzo trafna uwaga - pierwsza i najważniejsza rzecz, która przemawia na NIE w moim projekcie.

1

Webservice zakłada przesłanie danych w postaci xml do klienta. Xml jest fajny bo wielu go rozumie. Ale wynik można formatować inaczej, oczywiście nie mówię w kontekście webservice.
Poza tym pobranie danych z bazy to jedno, a wysłanie ich klientowi to inna sprawa, tzn. nie koniecznie chcemy zawsze całość danych wysyłać. Jak masz tabele z 20 kolumnami (wiele tekstowych), to zawsze chcesz wszystkie zwracać, nawet jak masz procedurę, która zawęża l.kolumn, to z kolei musisz mieć kolejny obiekt na potrzeby EF.
Pobaw się WCF i zastanów się czy nie lepiej jest zbudować obiektowy model danych (w WCF będą to kontrakty) oraz stworzyć sobie mechanizm dostępu do danych, nie koniecznie w oparciu o OR mapper, który będzie potrafił tworzyć obiekty z modelu, na podstawie jakiś metadanych. Czasem obiekty w modelu mają hierarchiczną strukturę, co za pomocą EF chyba nie jest możliwe do osiągnięcia (nie pamiętam, więc jak kłamię poprawcie, nie mylcie z zagnieżdżonymi np. Osoba->Adres).
A poza tym podobno web service w oparciu o WCF działają dużo wydajniej, przynajmniej tak twierdzili na MTS 2010 i nawet ładne słupki pokazywali. Ale z własnych obserwacji wydaje mi się, że nie kłamali.

0

Webservice zakłada przesłanie danych w postaci xml do klienta. Xml jest fajny bo wielu go rozumie. Ale wynik można formatować inaczej, oczywiście nie mówię w kontekście webservice.

Cały protokół SOAP to w ogóle niezły wynalazek. Jeżeli chodzi o WebService to zadziwiająco ułatwia komunikację między klientem a serwerem, no ale formatowanie XML to za dużo roboty.

Poza tym pobranie danych z bazy to jedno, a wysłanie ich klientowi to inna sprawa, tzn. nie koniecznie chcemy zawsze całość danych wysyłać. Jak masz tabele z 20 kolumnami (wiele tekstowych), to zawsze chcesz wszystkie zwracać, nawet jak masz procedurę, która zawęża l.kolumn, to z kolei musisz mieć kolejny obiekt na potrzeby EF.

Dokładnie to jest przyczyną powstania tego tematu - rdzeniem :).

Pobaw się WCF i zastanów się czy nie lepiej jest zbudować obiektowy model danych

A to rozwiązaniem :).

Na pewno przeczytam sobie więcej na temat WCF już od dawna miałem zamiar, ale jakoś tak nie miałem czasu.

Rzadko się trafia na kompetentne osoby, które dzielą się swoją wiedzą, ale na tym forum jest wszystko możliwe.
Wielkie dzięki za pomoc!

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