Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308

    [C#] Casting di Object in Hashtable

    Vediamo se riesco a rompere questo incantesimo che mi porto dietro da 6 mesi....
    Ho un hashtable MyHash[] in cui inserisco TOT oggetti con key "A", "B", "C" .... tutti di tipo T0, oggetti che espongono una proprietà P.
    Per ogni tipo ho una stringa che contiene il "nome" esteso di quel tipo: ad es.

    string T1Type = "namespace_del_progetto.T1"

    Nel corso del run-time al massimo 1 solo oggetto per volta può cambiare tipo, e precisamente:

    "A" può diventare T1
    "B" T2
    "C" T3 ecc.

    "This" è una stringa inizialmente vuota ("") che eventualmente riceve - nel run-time - la key dell'(unico) oggetto che cambia tipo. Quindi se "A" si trasforma da T0 a T1 allora This="A".
    Se in un certo momento del run-time gli oggetti sono di nuovo tutti di tipo T0 allora This torna ad essere "".
    Quando un oggetto cambia tipo, mi serve conoscere il valore della sua proprietà P.
    Io non ho saputo fare di meglio che scrivere questa tiritera:

    codice:
    if (This != "") 
    {
         if (MyHash[This].GetType().ToString() == T1Type)
         {
             T1 x = (T1)MyHash[This];
             --> x.P
         }
         else if (MyHash[This].GetType().ToString() == T2Type)
         {
             T2 x = (T2)MyHash[This];
             --> x.P
         }
         else if (MyHash[This].GetType().ToString() == T3Type)
         {
             T3 x = (T3)MyHash[This];
             --> x.P
         }
     
         ................
    e se i tipi sono T1, T2, ..., T100 devo scrivere 100 "If"!

    Esiste un modo per utilizzare un solo "If" magari dentro qualche ciclo diabolico?

    Grazie.

  2. #2
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    Non so se sono ancora in tempo per aiutarti o se sei gia stato fulminato dal Dio degli Sviluppatori per aver nominato una variabile "This".

    dovrebbe essere cosa fattibile con la reflection:

    codice:
    using System.Reflection;

    codice:
    if (This != "")
    {
        PropertyInfo pi = MyHash[This].GetType().GetProperty("p");
        string str = (string)pi.GetValue(MyHash[This], null);
    }
    se p non è di tipo string sostituisci string con il tipo giusto.

  3. #3
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    .....ma l'ho chiamata "This" non "Thor".... ed ho proprio voluto emulare il ben più famoso "This" del quale propone lo stesso aspetto, infatti "This" vuol dire "QUESTO mondo near" contrapposto a "QUEL mondo far". Il Dio degli sviluppatori mi capirà e mi ha già perdonato 1000 volte sennò non sarei qui.....

    ....cose da pazzi....la Reflection.... dammi una settimana per studiarmi queste 2 righe e provarle. Ti farò sapere.

    Ah intanto grazie, MAGO.

  4. #4
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    Ho trascritto i tuoi suggerimenti nel codice del mio progetto Albireo. Questa è la "vecchia" procedura che fa muovere la Discovery, implementata all'interno della struttura Discovery. In pratica quando l'astronave è lontana da ogni mondo risente solo del campo gravitazionale della stella (binaria) Albireo. Ma quando entra nell'orizzonte degli eventi di un qualche mondo allora risente ANCHE (e soprattutto) del suo campo gravitazionale. Questa nuova forza aggiunta dipende da due delle tante proprietà che ogni oggetto del sistema (mondo) espone: la sua massa e la sua posizione (riferita a "Location" in quanto "Position" è quella della Discovery):

    codice:
           public void Move()
            {
               Vector3 V = Go * Speed;
               
                if (This != "")
                {
                    if (My.Planets[This].GetType().ToString() == My.SphHType)
                    {
                        SphHWorld x = (SphHWorld)My.Planets[This];
                        V += My.Gfactor * My.G * x.Mass * Vector3.Normalize(x.Location - Position) / (x.Location - Position).LengthSquared();
                    }
                    else if (My.Planets[This].GetType().ToString() == My.SphHTType)
                    {
                        SphHTWorld x = (SphHTWorld)My.Planets[This];
                        V += My.Gfactor * My.G * x.Mass * Vector3.Normalize(x.Location - Position) / (x.Location - Position).LengthSquared();
                    }
                    else if (My.Planets[This].GetType().ToString() == My.SphH64Type)
                    {
                        SphHWorld64 x = (SphHWorld64)My.Planets[This];
                        V += My.Gfactor * My.G * x.Mass * Vector3.Normalize(x.Location - Position) / (x.Location - Position).LengthSquared();
                    }
                    else if (My.Planets[This].GetType().ToString() == My.SphHT64Type)
                    {
                        SphHTWorld64 x = (SphHTWorld64)My.Planets[This];
                        V += My.Gfactor * My.G * x.Mass * Vector3.Normalize(x.Location - Position) / (x.Location - Position).LengthSquared();
                    }
                    else if (My.Planets[This].GetType().ToString() == My.SphHSType)
                    {
                        SphHSWorld x = (SphHSWorld)My.Planets[This];
                        V += My.Gfactor * My.G * x.Mass * Vector3.Normalize(x.Location - Position) / (x.Location - Position).LengthSquared();
                    }
                    else if (My.Planets[This].GetType().ToString() == My.SphHTSType)
                    {
                        SphHTSWorld x = (SphHTSWorld)My.Planets[This];
                        V += My.Gfactor * My.G * x.Mass * Vector3.Normalize(x.Location - Position) / (x.Location - Position).LengthSquared();
                    }
                    else if (My.Planets[This].GetType().ToString() == My.SphHBType)
                    {
                        SphHBWorld x = (SphHBWorld)My.Planets[This];
                        V += My.Gfactor * My.G * x.Mass * Vector3.Normalize(x.Location - Position) / (x.Location - Position).LengthSquared();
                    }
                    else if (My.Planets[This].GetType().ToString() == My.SphHTBType)
                    {
                        SphHTBWorld x = (SphHTBWorld)My.Planets[This];
                        V += My.Gfactor * My.G * x.Mass * Vector3.Normalize(x.Location - Position) / (x.Location - Position).LengthSquared();
                    }
                    else if (My.Planets[This].GetType().ToString() == My.SphT3Type)
                    {
                        SphT3World x = (SphT3World)My.Planets[This];
                        V += My.Gfactor * My.G * x.Mass * Vector3.Normalize(x.Location - Position) / (x.Location - Position).LengthSquared();
                    }
                   Go = Vector3.Normalize(V);
                    Speed = V.Length();
                    AZI = azif(Go);
                    ALT = altf(Go);
                }
               ...........
    
            }
    
    A quanto ho capito il nuovo codice di Move sarebbe (dovrebbe essere) questo:

    codice:
            public void Move()
            {
               Vector3 V = Go * Speed;
               
                if (This != "")
                {
                    PropertyInfo p1 = My.Planets[This].GetType().GetProperty("Mass");
                    float M = (float)p1.GetValue(My.Planets[This], null);
                    PropertyInfo p2 = My.Planets[This].GetType().GetProperty("Location");
                    Vector3 L = (Vector3)p2.GetValue(My.Planets[This], null); 
                    V += My.Gfactor * My.G * M * Vector3.Normalize(L - Position) / (L - Position).LengthSquared();
                   Go = Vector3.Normalize(V);
                    Speed = V.Length();
                    AZI = azif(Go);
                    ALT = altf(Go);
                }
    
                ...........
    
            }
    ....ma mi dà questo errore:

    "! NullReferenceException non è stata gestita. !"
    "Riferimento a un oggetto non impostato su un'istanza di oggetto."

    in questa riga:

    codice:
    float M = (float)p1.GetValue(My.Planets[This], null);
    
    This è proprio la key del pianeta giusto, ma p1 mi risulta null. Ho controllato il metodo GetValue e la sintassi è corretta, anche il "null" come secondo parametro in quanto le proprietà degli oggetti del sistema non sono indicizzate.
    Ho provato a vedere se per caso non dipende dal fatto che Mass è un campo derivato (non fa parte dei parametri del costruttore) ed è calcolato a partire dalla densità e dal Size, mettendo "//" alle prime 2 righe ma l'errore si ripete anche per la proprietà Location che invece compare nella firma del costruttore.
    Allora?
    Ultima modifica di escocat; 16-11-2013 a 15:27

  5. #5
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    Niente. Ho provato anche
    PropertyInfo p1 = My.Planets[This].GetType().GetProperty("Mass", BindingFlags.NonPublic);

    ma è lo stesso. Credo che il problema non si possa risolvere perchè Mass e Location in effetti non sono 2 proprietà (non presentano i metodi Get e Set) di struttura ma 2 semplici campi e basta.

  6. #6
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    allora devi usare FieldInfo invece che PropertyInfo, GetField invece che GetProperty e GetValue con il solo primo argomento.

  7. #7
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    ORA SI'! Ce l'abbiamo fatta!

    Scherzo ovviamente, senza di te non ci sarei mai arrivato a questa soluzione, o forse ci sarei arrivato fra 10 anni... e non immagini quanto siano importanti queste 2 righe per tutto il progetto Albireo.Forte questa Reflection, l'avevo già usata per piccole cose e mi aveva affascinato. Ciao e grazie ancora.
    Alla prossima.

    codice:
    if ((My.GMode) & (This != ""))
    {
        FieldInfo p1 = My.Planets[This].GetType().GetField("Mass");
        float M = (float)p1.GetValue(My.Planets[This]);
        FieldInfo p2 = My.Planets[This].GetType().GetField("Location");
        Vector3 L = (Vector3)p2.GetValue(My.Planets[This]); 
        V += My.Gfactor * My.G * M * Vector3.Normalize(L - Position) / (L - Position).LengthSquared();
       Go = Vector3.Normalize(V);
        Speed = V.Length();
        AZI = azif(Go);
        ALT = altf(Go);
    }





    Ultima modifica di escocat; 17-11-2013 a 10:41

  8. #8
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    np

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.