Visualizzazione dei risultati da 1 a 10 su 10
  1. #1

    [c# + creare classe a runtime]

    Ciao Ragazzi le cose per me si complicano.

    Ho creato un array di object, usando ArrayList:

    [code] ArrayList Reference = new System.Collections.ArrayList();

    A cui a man mano registro i riferimenti di altre classe.

    [code]
    public void Ref(Object ob1)
    {
    Reference.Add(ob1);
    }
    [code/]

    A questo vorrei ricostruirmi la classe memorizzata,
    Supponiamo che la classe memorizzata in Reference, sia la classe "pippo", {pippo è una classe definita da me}

    [code]
    Pippo p1 = (pippo) Reference[position];
    [code/]

    Così è facile, perchè so che nella posizione "position" l'oggetto è pippo.


    Ed eccoci al mio problema:
    Non conosco la classe memorizzata in Reference e vorrei ricostruirla.

    Questa volta mi sa che il problema è piuttosto complicato. VVoVe:

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,466
    Cosa significa "ricostruire la classe"?
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Ciao alka, innanzitutto grazie per il tuo aiuto.Ma veniamo a noi.


    _________________________________________
    Cosa significa "ricostruire la classe"?
    _________________________________________


    Semplicemente mi basta poter fare il cast giusto.
    Praticamente facendo
    [code]
    Pippo p1 = (pippo) Reference[position];
    [code\]

    Ho fatto il cast a Pippo perchè conoscevo la classe, il mio problema è fare un'istruzione come quella sopra ma senza conoscere la classe, conoscendo solo Reference[position];

    Usando
    Reference[position].GetType(); riesco a risalire alla classe.
    Ma non posso fare
    Reference[position].GetType() p1 = Reference[position].GetType() Reference[position];

    Mi servirebbe tipo un GetClass al posto di un GetType.

    Spero di essere stato abbastanza chiaro.

  4. #4
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,466
    GetType restituisce tutte le informazioni che vuoi sapere se intendi indagare sui metadati della classe: ti restituisce proprietà, metodi e altro ancora.

    Il cast che hai fatto nel tuo codice non ha alcun senso, poichè la scrittura
    codice:
    newObj = oldObj;
    e la scrittura (sebbene non sia possibile)
    codice:
    newObj = (oldObj.Type) oldObj;
    sono identiche, o meglio la seconda non porta alcun vantaggio.

    Che senso ha trattare ogni istanza per la classe che in effetti rappresenta? E' un'informazione già nota.

    Non è ancora molto chiaro cosa intendi fare...
    Spiega le implicazioni pratiche, non la soluzione tecnica che vuoi raggiungere.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  5. #5
    Ciao alka!!!
    Ti espongo il mio problema probabilmente la mia scelta non è la più facile, magari c'è una maniera più pulita per risolvere il problema.


    Supponiamo che IO ho progettato una clsse chiamiamolo "Frame" che deve gestire varie altre classi.


    Quindi supponiamo che Tu (posso darti del Tu?), creare una classe Chiamiamola "Pippo".
    Poi viene un'altra persona e crea una sua classe, chiamiamolo "Pippo2".


    A Questo punto La classe "Pippo" e la classe "Pippo2" decidono di registrarsi nelFrame , passandogli il nome con cui vogliono essere registrate (che sarà l'identificativo di tipo stringa), e passandogli il puntatore this.


    Conclusione del fatto è che adesso la classe Frame ha un'object per ogni classe che si è registrata.
    [code]
    public void Ref(Object ob1)
    {
    Reference.Add(string id , object ob1);
    }
    [code/]


    Eccoci al dunque, adesso il Frame decide di invocare un metodo di una delle due classi, che supponiamo conoscere (supponiamo conoscere il metodo).Per fare ciò deve fare il cast alla classe e invocare il metodo.
    E non posso fare
    [code]
    Reference[position].metodo;
    [code/]

    Perchè Reference[position] è un object, non è una classe tipo Pippo o Pippo2.
    Quindi avrei bisogno di recuperare la classe , e invocare il metodo.

  6. #6
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,466
    Credo di aver capito il tuo problema, ma la soluzione che hai scelto è inapplicabile e soprattutto si risolve in modo brillante e naturale applicando un semplice principio della programmazione orientata agli oggetti: l'ereditarietà.

    Ciò che devi fare è creare una classe base dalla quale derivino tutte le classi che inserisci nella tua lista; tale classe base dovrà contenere i metodi che desideri richiamare per qualsiasi oggetto inserito in lista, indipendentemente dalla classe di appartenenza.

    Sto usando un approccio simile per gestire un'interfaccia utente: tutte le pagine che mostro sono ereditate da una classe base che costituisce la "pagina" generale standardizzata. Supponiamo che una pagina generica abbia un titolo resituito da un metodo:
    codice:
    class BasePage
    {
      protected virtual string GetTitle()
      {
        return "";
      }
    }
    A questo punto, puoi creare tutte le classi discendenti che vuoi, ridefinendo il metodo che restituisce il titolo per modificarne il valore di ritorno:
    codice:
    class AboutPage : BasePage
    {
      protected override string GetTitle()
      {
        return "Informazioni su...";
      }
    }
    
    class HelpPage : BasePage
    {
      protected override string GetTitle()
      {
        return "Aiuto in linea";
      }
    }
    Supponi ora di avere creato un numero indefinito di istanze per le classi sopra riportate (e altre eventuali discendenti dalla classe base) e di averle inserite in un array.

    Quando una classe eredita da una classe base superiore, ne acquisisce automaticamente i metodi esposti e, siccome ciascun metodo rappresenta un "messaggio" che può essere inviato a tale classe, ciò significa che possiamo inviare a ciascuna instanza il messaggio GetTitle semplicemente trattandole come il tipo base cui appartengono, cioè BasePage:
    codice:
    currentPageTitle = ((BasePage) availablePages[0]).GetTitle;
    Il codice sopra richiede che tutte le classi di appartenenza degli oggetti nel vettore availablePages discendano da BasePage; in tal caso, il "cast" è possibile, cioè è possibile trattare tutti gli oggetti come se appartenessero al tipo BasePage (condizione effettivamente verificata) e ottenere il titolo attraverso il metodo GetTitle; ciascuna classe discendente ridefinisce il comportamento del metodo restituendo una stringa differente, quindi otterremo un titolo diverso in base al tipo di oggetto cui ci stiamo riferendo con l'indice di posizione nel vettore.

    Si tratta dell'ABC della programmazione orientata agli oggetti: ereditarietà e polimorfismo.

    Secondo me, si tratta di concetti essenziali che vanno approfonditi con la lettura di un buon libro a riguardo prima di procedere col lambiccarsi il cervello con soluzioni inattuabili quando la più semplice e pulita viene fornita "di serie" con il linguaggio e la piattaforma adottata, come avviene in questo caso con C# e .NET Framework.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  7. #7
    Ciao alka.
    Io ti ringrazio per la tua idea , peccato che arriva in ritardo.
    La soluzione che mi hai proposto, è stata la mia prima soluzione.

    L'ho proposta a chi di dovere, ed è stata scartata semplicemente perchè questo mi richiede di creare la classica classe base, che è vuota, e non serve ad altro che a supportare le altre classi, le quali devono per ovvie cose estenderla.




    Adesso mi sto studiando.

    "System.Reflection;", in quando ho visto che posso scansire un'intera classe, a pertire da System.type ( che è poi quello che riesco ad ottenere facendo Reference[position].getType() )
    ed ottenere sia informazioni sui metodi che sui membri e sicur. anche sulle interfacce...ecc..
    Ti post un pò di codice.

    [code]
    System.Type t = Reference[position].getType();
    MethodInfo[] x = t.GetMethods();
    foreach (MethodInfo xtemp in x)
    {
    Console.WriteLine(xtemp.ToString());

    }
    MemberInfo[] x2 = t.GetMembers();
    foreach (MemberInfo xtemp2 in x2)
    {
    Console.WriteLine(xtemp2.ToString());
    }
    [code/]

    Chissà se riesco anche ad invocare un metodo.Ci sto lavorando.

    Cmq se riesco ad ottenere qualche risultato, ti faccio sapere.

  8. #8
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,466
    Originariamente inviato da Dylan_Web
    La soluzione che mi hai proposto, è stata la mia prima soluzione.
    L'ho proposta a chi di dovere, ed è stata scartata semplicemente perchè questo mi richiede di creare la classica classe base, che è vuota, e non serve ad altro che a supportare le altre classi, le quali devono per ovvie cose estenderla.
    Prova a chiedere a "chi di dovere" dov'è il lato negativo della cosa...non credo ci sarà una risposta sensata.

    Originariamente inviato da Dylan_Web
    Adesso mi sto studiando.
    "System.Reflection;", in quando ho visto che posso scansire un'intera classe, a pertire da System.type ( che è poi quello che riesco ad ottenere facendo Reference[position].getType() )
    ed ottenere sia informazioni sui metodi che sui membri e sicur. anche sulle interfacce...ecc..
    Scusa, ma questo non te lo avevo già detto io precedentemente quando ti ho scritto:
    "GetType restituisce tutte le informazioni che vuoi sapere se intendi indagare sui metadati della classe: ti restituisce proprietà, metodi e altro ancora."


    Originariamente inviato da Dylan_Web
    Chissà se riesco anche ad invocare un metodo.Ci sto lavorando.
    Non devo perchè non dovresti riuscirci, ad ogni modo non capisco quali vantaggi ottieni dalla tua soluzione: qualsiasi metodo tu debba chiamare in una qualsiasi classe, dovrai scrivere codice specifico, specializzato, pertanto quando le classi cambiano dovrai cambiare anche la parte di applicazione che stai sviluppando. Rispetto alla soluzione che ti ho proposto io, a cui avevi pensato e che è stata scartata, con una simile implementazione ti accorgerai degli errori solo a runtime (poichè invochi i metodi attraverso il nome e non sfruttando le caratteristiche dei tipi).

    In definitiva, continuo ad essere convinto che l'implementazione che stai adottando non sia nient'altro che un "reinventare la ruota" ricreando ciò che consente il polimorfismo.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  9. #9
    Devo dire che mi hai rincuorato.(ovviamente sono ironico)



    Ke Bello!!!

    Cmq ti faccio sapere sempre su questa discussione.

  10. #10
    Più vado avanti e più mi accorgo, quanto sia completo e utile C#.
    E' davvero un linguaggio di programmazione ben fatto.


    Tutto questo per dire che "CI SONO RIUSCITO"


    Riesco ad invocare metodi di una classe, tramite la System.Reflection, e la cosa sorprendente è che riesco addirittura a leggere una dll, ovviamente fatta in c#, ed invocare i metodi dall'interno della dll.
    Ti posto un pò di codice!!!
    [code]
    Type t = typeof(MyClass);
    Object objInstance = Activator.CreateInstance(t);
    Object[] paramsArray = new Object[1];
    paramsArray[0] = "Piripicchio";
    MethodInfo thisMethod = t.GetMethod("MyMeth()");
    thisMethod.Invoke(objInstance, paramsArray);
    [code/]

    Spero che da questa mia esperienza, ne sia uscito anche Tu, più arricchito.Grazie mille per la tua collaborazione, spero di poter continuare altre proficue discussioni.

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.