Oppure

Loading
23/11/21 9:16
Thejuster
Salve ragazzi, mi sto un pò confondendo con i tipi generici.
Magari non riesco a trovare una soluzione per la troppa confunsione che ho in testa :rotfl:
E qualcuno più lucido in questo momento può aiutarmi.

Niente di particolare, non riesco ad ottenere un tipo generico.
Devo fare una funzione che Accetta sia il Tipo come argomento che quello di ritorno.

esempio dovrei ottenere qualcosa del genere
(l'esempio non funziona ma è giusto per capire cosa voglio ottenere)


var ret = SendGetPacket<PacketData>(paket);


static object SendGetPacket<T>(T type)
{
      object obj;

      if(type.getType() == typeof(PacketData))
      {
 
             byte[] data = ((PacketData)type).Serialize(); //Errore Non è possibile convertire il tipo 'T' in Packet.PacketData'.	

              
             if ((uint)((PacketData)paket).HeaderCommand == 0x14)
             {
                     PacketData r = new PacketData();
                     r.Command = (uint)PacketData.HeaderCommand.ACT_LOGIN;
                     r.Argument1 = p.Argument1;
                     r.Argument2 = p.Argument2;

                     r.Serialize();
                     client.SendPacket(r);
                     obj = r;
             }
  
       } else { //Altro }
     

return obj;

}




Nell'esempio, Invio un tipo strutturato come argomento che contiene diverse informazioni e funzioni.
nello specifico PacketData che sarebbe un pacchetto strutturato con Header, Body e Footer.
che non supera i 60byte a pacchetto inviato.
Devo inviare ed in seguito ricevere un'altro pacchetto di risposta che può variare a seconda del tipo dell'informazione contenuta nell'Header. quindi il tipo di ritorno non sarà mai uguale a quello inviato.
per questo mi serve un tipo di ritorno generico e non standard.
Ma stranamente mi da errore dicendo di non poter convertire T in in PacketData o altro.
Da cosa può dipnedere?
Spero qualcuno possa darmi qualche illuminazione

Ultima modifica effettuata da Thejuster 23/11/21 9:44
mire.forumfree.it/ - Mire Engine
C# UI Designer
23/11/21 13:13
Carlo
se invece di dichiarare ret come var, lo dichiari object?:

object ret = SendGetPacket<PacketData>(paket);
in programmazione tutto è permesso
23/11/21 15:30
Thejuster
Sarebbe identico perché var è generico assume qualsiasi valore gli viene dato così come object.

il problema principale avviene qui, non e tanto il return che mi preoccupa.
Ma il fatto di non riuscire a forzare il compilatore a trasformare il tipo T Generico in PacketData

byte[] data = ((PacketData)type).Serialize(); //Errore Non è possibile convertire il tipo 'T' in Packet.PacketData'. 



ho tentato diverse strade, così come

T SendGetPacket<T>(T t)
        {
            if(typeof(T) == typeof(PacketData))
            {
                PacketData p = new PacketData();
                p.Argument1 = ((PacketData)t).Argument1;

                //.....
            }

            return t;
        }


Niente da fare.

Esempio della struttura PacketData alquanto ambigua giusto per farvi un idea.


 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct PacketData
    {
        public uint Command;

        public String Argument1;

        public String Argument2;

        //ecc ecc....

    }


Cioè non sò, mi sembra assurdo che il compilatore non riesce ad indentificare una semplice struttura.
Magari... servirà una conversione implicita? non ho proprio idea di come risolvere.

Ultima modifica effettuata da Thejuster 23/11/21 15:34
mire.forumfree.it/ - Mire Engine
C# UI Designer
23/11/21 20:46
Carlo
Potresti controllare in debug cosa contiene il tuo t quando lo ricevi, visto che è generico prima di fare la conversione di tipo devi capire cosa contiene:


        T SendGetPacket<T>(T t)
        {
            if (typeof(T) == typeof(PacketData))
            {
                PacketData p = new PacketData();

                object ot = t; 

               // p.Argument1 = ((PacketData)t).Argument1;

                //.....
            }

            return t;
        }


Ultima modifica effettuata da Carlo 27/11/21 7:17
in programmazione tutto è permesso
23/11/21 21:58
Thejuster
magari potrei farlo :rotfl:
segnandolo in rosso non ti fa partire nemmeno il debugger.
mire.forumfree.it/ - Mire Engine
C# UI Designer
24/11/21 13:47
Carlo
Postato originariamente da Thejuster:

magari potrei farlo :rotfl:
segnandolo in rosso non ti fa partire nemmeno il debugger.


Se hai visto il codice, l'istruzione che da errore l'ho remmata.
Ho aggiunto la variabile ot di tipo object, dove devi andare a vedere cosa c'è dentro.

object ot = t;
Ultima modifica effettuata da Carlo 27/11/21 7:18
in programmazione tutto è permesso
24/11/21 19:27
Carlo
Risolto, dopo che hai messo il tipo generico t in un oggetto, la conversione di tipo, usando l'oggetto, non da più errore e funziona:

T SendGetPacket<T>(T t)
{
        if (typeof(T) == typeof(PacketData))
        {
             PacketData p = new PacketData();
             object ot = t;
             p.Argument1 = ((PacketData)ot).Argument1;

             //.....
        }
}
Ultima modifica effettuata da Carlo 27/11/21 7:44
in programmazione tutto è permesso
29/11/21 11:40
Thejuster
Ninete non sò allora perché a me non funziona.

Teoricamente, questo tipo di funzione, dovrebbe servirmi a fare qualcosa del genere.

T SendGetPacket<T>(T t)
        {
            //PacketData è un Pacchetto strutturato generico 
           //che non richiede particolari accortenze
           //Diversamente dagli altri, ha solo funzioni limitate 
          //di Ricezione e riposta di 2 semplici argomenti
          //Argument1 e Argument2 che in seguito i valori 
          //vengono convertiti in base al tipo di richiesta
          //Contenuto nell'header

            PacketData p = new PacketData();

            object _ret = null; //oggetto generico di ritorno

            if (typeof(T) == typeof(CharPaket)) //Se T in argomento è di tipo CharPacket
            {
                               
                object ot = t; 
                if(((CharPaket)ot).hp <= 0) //se personaggio gli HP sono < = di 0
                {
                    //Invio richiesta di Morte al server
                    p.Command = (uint)PacketHeader.HeaderCommand.ACT_CHAR_DEATH;
                    p.Argument1 = ((CharPaket)ot).accountID.ToString(); //Id Account
                    p.Argument2 = ((CharPaket)ot).CharNum.ToString(); //Numero del personaggio nel database

                    
                }

                _ret = p; //Assegno alla variabile object il pacchetto PacketData da ritornare

            }
            return _ret;   //------------    Errore qui
        }



Fatto sta, ho sempre il medesimo errore.

Non è possibile convertire in modo implicito il tipo 'object' in 'T'. È presente una conversione esplicita. Probabilmente manca un cast.

il PacketData è generico come detto nei commenti.
Se sò che l'header equivale a 0x40, il client ha inviato una richiesta di login.
quindi so per certo che l'argomento 1 contiene username e il 2 la password.
così come per gli atri vari comandi che non richiedono particolari espressioni o condizioni.

Gli altri invece è più elorabata come cosa, perché ottimizzando il tutto, senza lasciare byte a caso, o vuoti,
e senza inviare al server inutili byte, gli invio quello che servono.
Perché la struttura non può superare quella soglia di bytes per regola
impostata come dimensione fissa usando il Marshalling.
Usando strutture di tipo Sequenziali con un Layout predefitino.
So che quindi a tot byte da un range da 0 - a 20 c'è un dato ecc. ecc.
Insomma è abbastanza complicato da spiegare, ma rende l'idea di ciò che ho fatto.
Avendo prestazioni altissime e pacchetti molto leggeri e complessi che non superano i 120byte ( Non KB ma Bytes)
Sfruttando poi il .NET Core come server, è un qualcosa di spettacolare.


hmmm... 8-|
Ultima modifica effettuata da Thejuster 29/11/21 11:58
mire.forumfree.it/ - Mire Engine
C# UI Designer