Wie kann man auf die Fields dynamisch, d.h. mittels System.Reflection, zugreifen?

03/02/2009 - 16:07 von jpr1965 | Report spam
Hallo,

ich benötige eine Methode wie

/// <summary>
/// How to check all private/protected struct attributes??
/// </summary>
protected void setAllAttributes2Null()
{
Type thisType = this.GetType();

foreach (System.Reflection.FieldInfo fi in thisType.GetFields
(System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic))
{
// System.Diagnostics.Debug.WriteLine(fi.Name);
if (fi.FieldHandle.Value != null)
{
System.Diagnostics.Debug.WriteLine(fi.Name + " = " +
fi.FieldHandle.Value);
}
else
{
System.Diagnostics.Debug.WriteLine(fi.Name);
}

}

}

damit ich beim Dispose() feststellen kann, ob irgendwelche Fields
nicht auf null gesetzt wurden. Falls noch irgendwelche Referenzen
offen bleiben, kann der GC die Instanzen nicht wieder frei geben und
der Speicher wàchst und wàchst.

Man kann natürlich alle Fields im Dispose() explizit auf null setzen
mit

this.field1 = 0;
this.field2 = 0;



Aber bei großen System kann das schon mal vergessen werden, und diese
Fehler möchte ich finden oder besser gleich mit einer foreach Schleife
alles auf Null setzen.

Leider liefert im Beispiel Code thisType.GetFields(...) keine Fields,
obwohl ich mich in der Klasse selbst befinde und genügend (protected/
private) fields definiert sind. Auch public Fields werden nicht von
dieser Funktion gefunden.

Im voraus Danke für die Hilfe
jpr65
 

Lesen sie die antworten

#1 Günter Prossliner
03/02/2009 - 17:30 | Warnen spam
Hallo jpr1965!

(In diesem Forum werden normalerweise Realnames verwendet)


protected void setAllAttributes2Null()
{
Type thisType = this.GetType();

foreach (System.Reflection.FieldInfo fi in thisType.GetFields
(System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic))



Hier fehlt noch ein 'BindingFlags.Instance' (statische Felder willst Du ja
warscheinlich nicht).

{
// System.Diagnostics.Debug.WriteLine(fi.Name);
if (fi.FieldHandle.Value != null)
{



FieldHandle?

Wert lesen:
object fieldvalue = fi.GetValue(this);

Wert setzen:
fi.SetValue(this, "neuer wert");

...
damit ich beim Dispose() feststellen kann, ob irgendwelche Fields
nicht auf null gesetzt wurden. Falls noch irgendwelche Referenzen
offen bleiben, kann der GC die Instanzen nicht wieder frei geben und
der Speicher wàchst und wàchst.



Das kannst Du Dir sparen. Es ist nicht notwendig Felder auf null zu setzen,
da der GC nicht über ein Reference-Counting arbeitet.


Trotzdem sind was die Ressourceverwaltung betrifft noch weitere Dinge zu
beachten:

1. COM arbeitet über Ref-Counts. Wenn Du also COM-Objekte verwendest, kannst
Du durchaus die Referenzen auf null setzen. Je nach COM-Server ist ggf. auch
ein Marshal.(Final)ReleaseComObject n;tig.

2. Objekte welche unmanaged Resourcen beinhalten (z.b. Handles (Dateien,
Sockets, GDI-Objekte, ...) oder z.b. SqlConnections, ...) - also grob gesagt
Objekte von Typen welche IDisposable implementieren, solltest Du (sofern Du
sie in der Klasse erstellt, und in einem Feld gespeichert hast), mittels dem
entsprechenden .Dispose() Aufruf freigeben.


Man kann natürlich alle Fields im Dispose() explizit auf null setzen
mit

this.field1 = 0;
this.field2 = 0;



Das Setzen von ValueTypes ist in jedem Fall eine (Zeit)verschwendung, da
diese (ausser statische Felder) niemals "für sich" existieren. Entweder
ValueTypes sind Stack-Instanzen, oder Bestandteil von übergeordneten
Reference-Types (auch indirekt z.b. struct in struct in class).

Auch 'this.fieldX = null' ist in aller Regel nicht notwendig, sehrwohl aber
ein 'this.fieldX.Dispose()', wenn

1. Das Objekt IDisposable implementiert (klarerweise)
2. Du das Objekt selbst erstellt hast
3. Das Objekt über einen Methodenaufruf existiern, und somit nicht z.b
.mittels eines 'using { }' oder try-finally innerhalb der Methode
disposed werden kann, und somit in einem Feld gespeichert wird.




OK?
mfg GP

Ähnliche fragen