PDA

View Full Version : [c#] Aiuto sulla riflessione


grigor91
03-12-2010, 18:13
Salve.
Avrei bisogno di un aiuto riguardante la riflessione.
In pratica dovrei creare un ciclo in cui utilizzo una variabile. Il problema è che questa variabile è nella forma:

parteFissa + "stringa"

So che devo utilizzare la riflessione, solo non riesco a capire quali metodi devo utilizzare per quello che devo fare.

Non devo creare nuove variabili, devo solo riferirmi ad una variabile il cui nome conoscerò solo in fase d'esecuzione.

Suggerimenti? :help:

Kralizek
03-12-2010, 21:44
non sono sicuro che Reflection possa risolvere il tuo caso. ad ogni modo prova a guardare la situazione dal di fuori perchè hai un problema molto particolare e magari cambiando le condizioni al contorno riesci ad evitare in toto il problema =)

tomminno
03-12-2010, 23:57
Qui (http://msdn.microsoft.com/en-us/library/53seyfee.aspx) c'è un esempio di come si usa FieldInfo che dovrebbe essere quello che fa al caso tuo.
Anche se a parte ASP.NET, con la generazione automatica di controlli ripetuti, un caso come il tuo non mi è mai capitato.

grigor91
04-12-2010, 15:01
Grazie per avermi risposto.
Avevo già provato FieldInfo, solo che sembra che funzioni solo con gli attributi una classe.

Per adesso mi sono arrangiato in qualche modo, però mi viene in mente una domanda:
Se con Reflection è possibile creare istanze di oggetti dinamicamente, a queste istanze verrà dato un nome. Quindi suppongo che esista un modo per collegare una stringa che è il nome di una istanza con l'istanza stessa, no?

Kralizek
04-12-2010, 18:00
Grazie per avermi risposto.
Avevo già provato FieldInfo, solo che sembra che funzioni solo con gli attributi una classe.

Per adesso mi sono arrangiato in qualche modo, però mi viene in mente una domanda:
Se con Reflection è possibile creare istanze di oggetti dinamicamente, a queste istanze verrà dato un nome. Quindi suppongo che esista un modo per collegare una stringa che è il nome di una istanza con l'istanza stessa, no?

no perchè tipicamente tu fai qualcosa tipo


Type tDateTime = typeof(DateTime);
ConstructorInfo ciDateTime = tDateTime.GetConstructor(new Type[] { typeof(int), typeof(int), typeof(int) });

object obj = ciDateTime.Invoke(new object[]{ 1982, 12, 10 });
DateTime dt = (DateTime)obj;


e quindi il tuo oggetto viene assegnato ad una variabile nota a compile time quale "obj" nell'esempio

grigor91
04-12-2010, 22:05
no perchè tipicamente tu fai qualcosa tipo


Type tDateTime = typeof(DateTime);
ConstructorInfo ciDateTime = tDateTime.GetConstructor(new Type[] { typeof(int), typeof(int), typeof(int) });

object obj = ciDateTime.Invoke(new object[]{ 1982, 12, 10 });
DateTime dt = (DateTime)obj;


e quindi il tuo oggetto viene assegnato ad una variabile nota a compile time quale "obj" nell'esempio

Ma quindi quale sarebbe l'utilità in questo caso?

Kralizek
05-12-2010, 02:00
Reflection serve per "esplorare" i tipi presenti all'interno di una libreria.

Ad esempio recentemente avevo bisogno di una lista di classi che implementavano una certa interfaccia e per ogni elemento costruire un'istanza di una classe generica passandogli quel tipo ed, infine, per ciascuna coppia, avviare un servizio WCF basato su questi due tipi.

Certo avrei potuto costruire un Dictionary<Type, Type> e popolarlo in design-time, ma volevo automatizzare il tutto ed ero disposto a pagare il prezzo in performance dovuto a reflection visto che l'operazione viene fatta solo una volta ad avvio del Windows Service che hosta il tutto.

grigor91
05-12-2010, 11:35
Ma se conosco il nome dell'oggetto da referenziare solo in fase d'esecuzione, come posso fare?

Kralizek
05-12-2010, 12:04
Ma se conosco il nome dell'oggetto da referenziare solo in fase d'esecuzione, come posso fare?

e se usassi un Dictionary<string, TuaClasse> in cui metti le varie istanze in modo che fai sempliemente


Dictionary<string, TuaClasse> container = LoadObjectsFromSomewhere();

TuaClasse obj = null;
container.TryGet("oggetto1", out obj);


?

grigor91
05-12-2010, 13:04
e se usassi un Dictionary<string, TuaClasse> in cui metti le varie istanze in modo che fai sempliemente


Dictionary<string, TuaClasse> container = LoadObjectsFromSomewhere();

TuaClasse obj = null;
container.TryGet("oggetto1", out obj);


?

E per ottenere il riferimento tutte le istanze di una specifica classe in modo da popolare il dizionario?

Kralizek
05-12-2010, 21:36
nella classe crei un dizionario statico e nel costruttore di istanza aggiungi un riferimento all'oggetto creato al dizionario.

qualcosa tipo

void Main()
{
TuaClasse cl = new TuaClasse ();

TuaClasse cl2 = TuaClasse.GetIstanza("something");
}

// Define other methods and classes here
public class TuaClasse
{
static Dictionary<string, TuaClasse> Container = new Dictionary<string, TuaClasse>();

public static TuaClasse GetIstanza(string key)
{
return Container[key];
}

public TuaClasse()
{
// Inizializzazione


// Salvo riferimento
Container.Add(GetKey(), this);
}

private string GetKey()
{
return "something";
}
}

grigor91
06-12-2010, 09:58
Esiste qualcosa di simile per le classi della libreria .NET?

Kralizek
06-12-2010, 10:35
Esiste qualcosa di simile per le classi della libreria .NET?

non credo. posso chiederti lo scenario di utilizzo? probabilmente esiste una soluzione migliore :D

ad ogni modo, prova qualcosa come questo:


void Main()
{
InstanceTracker<DateTime>.Add("today", DateTime.Today);

var today = InstanceTracker<DateTime>.Get("today");
}

public static class InstanceTracker<T>
{
static Dictionary<string, T> Tracker = new Dictionary<string, T>();

public static void Add(string key, T obj)
{
Tracker.Add(key, obj);
}

public static T Get(string key)
{
return Tracker[key];
}
}


ocio che questo "coso" non si svuota e rischi di andare in oom

grigor91
06-12-2010, 14:05
doppio

grigor91
06-12-2010, 14:13
non credo. posso chiederti lo scenario di utilizzo? probabilmente esiste una soluzione migliore :D



Ecco, Mi sa che è meglio, magari la soluzione è più semplice di quello che sembra :D

In pratica ho una serie di TextBox il cui nome differisce solamente per un numero alla fine, tipo text1, text2, text3, etc...
Ho un ciclo for in cui il contatore stabilisce in quale textBox inserire del testo.
Attualmente ho creato un array che popolo con le istanze e uso questo array nel ciclo.


TextBox textBoxArray = {textBox1, testBox2, textBox3};

for(i = 0; i < n; i++)
textBoxArray[i].Text = "una stringa";


Solo che questo è fattibile solo se le textBox non sono eccessive.
Avrei bisogno di una collezione di tutte le istanze della classe TextBox con cui possa fare fare riferimento a una istanza particolare tramite una stringa. Se questa collezione esiste già bene, altrimenti se possibile creo un dizionario.
Ecco il mio problema.

gugoXX
06-12-2010, 20:38
nella classe crei un dizionario statico e nel costruttore di istanza aggiungi un riferimento all'oggetto creato al dizionario.

qualcosa tipo

void Main()
{
TuaClasse cl = new TuaClasse ();

TuaClasse cl2 = TuaClasse.GetIstanza("something");
}

// Define other methods and classes here
public class TuaClasse
{
static Dictionary<string, TuaClasse> Container = new Dictionary<string, TuaClasse>();

public static TuaClasse GetIstanza(string key)
{
return Container[key];
}

public TuaClasse()
{
// Inizializzazione


// Salvo riferimento
Container.Add(GetKey(), this);
}

private string GetKey()
{
return "something";
}
}

Come da te gia' indicato, il problema e' dietro l'angolo.
Funziona, ma ti becchi tanti memory leak.
Non nel senso C, ma nel senso di memoria allocata.
Nessuno liberera' mai quella Dictionary statica, e il singolo oggetto, essendo referenziato da un altro oggetto almeno (la dictionary stessa), non verra' mai effettivamente distrutto.

Kralizek
07-12-2010, 22:24
Ecco, Mi sa che è meglio, magari la soluzione è più semplice di quello che sembra :D

In pratica ho una serie di TextBox il cui nome differisce solamente per un numero alla fine, tipo text1, text2, text3, etc...
Ho un ciclo for in cui il contatore stabilisce in quale textBox inserire del testo.
Attualmente ho creato un array che popolo con le istanze e uso questo array nel ciclo.


TextBox textBoxArray = {textBox1, testBox2, textBox3};

for(i = 0; i < n; i++)
textBoxArray[i].Text = "una stringa";


Solo che questo è fattibile solo se le textBox non sono eccessive.
Avrei bisogno di una collezione di tutte le istanze della classe TextBox con cui possa fare fare riferimento a una istanza particolare tramite una stringa. Se questa collezione esiste già bene, altrimenti se possibile creo un dizionario.
Ecco il mio problema.
ma non é che ti serve una lista dinamica di textbox "simili" all'interno di un particolare form?

Come da te gia' indicato, il problema e' dietro l'angolo.
Funziona, ma ti becchi tanti memory leak.
Non nel senso C, ma nel senso di memoria allocata.
Nessuno liberera' mai quella Dictionary statica, e il singolo oggetto, essendo referenziato da un altro oggetto almeno (la dictionary stessa), non verra' mai effettivamente distrutto.

vabbé ma quel coso lí neanche é degno di essere compilato... l'ho scritto solo per dare un'idea a grigor.

grigor91
08-12-2010, 11:05
ma non é che ti serve una lista dinamica di textbox "simili" all'interno di un particolare form?



Esatto.

Kralizek
08-12-2010, 22:43
Esatto.

uhm... allora il problema è di facile risoluzione (anche se non lavorando con WF non ricordo perfettamente)

cmq hai due strade: o usi un controllo tipo panel (mi sembra si chiamasse group qualcosa) e ci metti tutte le textbox dentro) oppure mi sembra puoi dare lo stesso nome a tutte le textbox e cambiare una proprietà tipo index (ma forse era vb6...)

scusa per il consiglio vago ma ci lavoro veramente poco in windows forms. magari passa qualcuno e ti dà una mano =)