[ _v!rus_ @ 11.07.2007. 12:16 ] @
Zanima me da li je moguce u statickom metodu klase dobiti nekako svoj tip, u cilju konstruisanja samog sebe ili svog potomka. Problem je u tome sto keyword this ne postoji u statickom metodu.

Ispod je Delphi kod koji radi upravo to sto meni treba, samo ne mogu nikako da dodjem do C#-ovog ekvivalenta:
Code:

type TMama=class;
...

type TDete=class(TMama);
...

class function TMama.Run: TMama;
begin
  Result := Self.Create;
end;
...

procedure TForm1.FormCreate(Sender: TObject);
var
  O: TMama;
begin
  O := TDete.Run;
  ShowMessage(O.ClassName)
end;


U Delphiju Self znaci this, samo sto u statickom metodu znaci thisClass iliti typeof(this).
[ dusty @ 11.07.2007. 13:17 ] @
Hmm, ako sam ja tebe razumeo, ti bi da proveris kojeg je tipa klasa koja je pozvala staticku metodu, da li je to iz bazne ili neke nasledjene ? Nisam siguran, ali mislim da to ne moze, jer se staticke metode alociraju samo na jednom mestu nevezano za klasu kojoj pripada, dok sve ostale metode dobijaju samo stub-ove koji se posle razresavaju i pri pozivu se prosledjuje referenca na pozivajuci objekat (this).

Mozes li malo da pojasnis ?
[ _v!rus_ @ 11.07.2007. 14:06 ] @
Citat:

Hmm, ako sam ja tebe razumeo, ti bi da proveris kojeg je tipa klasa koja je pozvala staticku metodu, da li je to iz bazne ili neke nasledjene.


Skoro da je tako, ne treba mi kog je tipa klasa koja je pozvala staticki metod, nego kog je tipa klasa ciji metod pisem.
Npr. klasa Mama ima public static metod Run, klasa Dete je nasledila metod. Onda ako pozovem Dete.Run() hocu da nekako metod zna da je pozvan iz deteta, ako rayumes sta hocu da kazem.

Znaci nesto kao:
Code:

public class Mama
{
   public static void Run(Type typeOfDete)
   {
      if(!typeOfDete.IsSubclassOf(typeof(Mama)))
         throw new Exception(typeOfDete.ToString() + " is not a subclass of Mama.");

      using(Mama o = new Activator.CreateInstance(typeof(typeOfDete)))
      {
         //Radi nesto sa "o"
      }
   }
}


Problem ovde je u tome sto moram za konkretnu klasu Dete da pisem Dete.Run(typeof(Dete)) sto mi se cini cudnim da metodi klase prosledjujem tu istu klasu, odnosno typeof te iste klase, zato trazim neko bolje resenje. Druga stvar, konstruktor mora biti public zbog Activator-a, a ja ne bi hteo da neko instancira nijednu od tih klasa "na ruke", nego samo preko statickog metoda Run.

[Ovu poruku je menjao _v!rus_ dana 11.07.2007. u 15:19 GMT+1]
[ jablan @ 11.07.2007. 15:15 ] @
Koji real-world problem pokušavaš da rešiš, možda može da se reformuliše?
[ mmix @ 11.07.2007. 15:27 ] @
Zapravo treba:

Code:

Mama o = (Mama)Activator.CreateInstance(typeOfDete);



1. fora je sto to sto hoces da uradis kao sto Delphi to moze ne moze u .NETu. Type je jedini nosilac tipa i ne postoje strong typed class varijable kao u Delphi-u.
2. ako hcoes da koristis private (non-public) konstruktor iskoristi Activator.CreateInstance(typeOfDete, true);
3. Alternativa ovome je da napravis neku primenu preko generics-a, gde ces sebi sa where da olaksas proveru sublclassinga:


Code:

    public class Mama<T> where T : Mama<T>
    {
        public static void Run()
        {
            Mama<T> o = (Mama<T>)Activator.CreateInstance(typeof(T));
            //Radi nesto sa "o"
        }
    }

    public class Dete : Mama<Dete>
    {
    }

    class Program
    {
        static void Main(string[] args)
        {
            Dete.Run();
        }
    }


posto posto T mora da bude Mama ili neko od njene dece ne mroas proveravati tip
[ mmix @ 11.07.2007. 15:39 ] @
A ako se ogranicis na public default konstruktore, mozes i da izbacis refleksiju ;) :

Code:

    public class Mama<T> where T : Mama<T>, new()
    {
        public static void Run()
        {
            Mama<T> o2 = new T();
            //Radi nesto sa "o"
        }
    }
[ _v!rus_ @ 11.07.2007. 22:52 ] @
@mmix
Ono "new" je lapsus, a cast sam 'ladno zaboravio (pisem napamet). Hvala na odgovoru. Stvar je u tome da jos nisam stigao do "dzenerika" :), pisem tek prvu "ozbiljnu" aplikaciju u .netu.

@jablan
Pravim framework za unos i pregled podataka iz baze koji bi radio genericki, na osnovu prosledjenog Dataseta i njegovih tabela i relacija definisanih u design time-u. Konkretan problem koji imam moze da se resi na sigurno 100 razlicitih nacina, ali me je zanimalo da li moze ovako kako sam vec radio u Delphi-ju, tj. da portujem postojeci kod sa sto manje izmena na samoja arhitekturi frameworka. Bottom line je da ima previse razlika i u samom jeziku i u klasama za rad sa bazama, i da cu izgleda morati ponovo napravim sve od nule.
[ jablan @ 11.07.2007. 23:17 ] @
Uz rizik da sam nešto ozbiljno promašio u kapiranju:

Zašto ti je bitno da, umesto da zoveš klasičan konstruktor tipa Mama m = new Dete(); (gde je konstruktor deteta ustvari nasleđen od majke)

zoveš statičku metodu koja instancira isti taj objekat: Mama m = Dete.Create();?

Mislim, šta dobijaš time?

BTW, mislim da ako ti je postojeći program dobro napisan, nećeš morati da ga pišeš od nule. Samo reformuliši sintaksne konstrukcije.
[ _v!rus_ @ 12.07.2007. 09:28 ] @
Prvo to Create() nije staticki metod (tehnicki jeste), nego je to Delphijeva sintaksa za konstruktor, tako da te dve kodne sekcije koje si napisao su identicne, samo su u razl. jezicima.

Razlog za to sto ne koristim "klasicno" kreiranje objekata je zato sto framework nikada ne instancira objekte (forme) preko konstruktora, jer bi tako dobio referencu i morao da se nadalje "staram" za dobijeni objekat (delphi nema GC), nego sam napravio da static metod instancira pripadajucu klasu, uradi neke common stvari, prikaze formu i posle je oslobadja kada se forma zatvori. Zamisljeno je tako da ostatak programa koji upotrebljava taj data framework uvek pokrece static metod iste forme, npr. EditorForm.Run(DataTable aTable), a taj static Run metod u runtime-u kreira sebe (EditorForm je istovremeno i bazna klasa) ili svog potomka u zavisnosti od toga da li postoji custom editor za tu prosledjenu tabelu - e to u .netu ne moze, bar ne na takav 1:1 nacin nego moram da uvodim trecu klasu (pored mame i deteta) koja ce da kreira odgovarajuce dete na osnovu prosledjene datatabele, sto mozda i nije tako lose.