Private Attribute über Reflection auslesen

Thomas Darimont

Erfahrenes Mitglied
Hallo!

hier mal ein kleines Beispiel wie man private Attribute via Reflection auslesen kann:
C#:
using System;
using BindingFlags = System.Reflection.BindingFlags;
using FieldInfo = System.Reflection.FieldInfo;

namespace De.Tutorials.Training
{
    /// <summary>
    /// A little example for accessing a private instance field via reflection.
    /// </summary>
    /// <author>Thomas.Darimont</author>
    public class ReflectionExample
    {

        public static void Main(string[] args)
        {
            PrivateDataHolder privateDataHolder = new PrivateDataHolder();
            Console.WriteLine(GetValueOfPrivateFieldFor(privateDataHolder,"data"));
        }

        public const BindingFlags ACCESS_PRIVATE_INSTANCE_FIELDS = BindingFlags.Instance | BindingFlags.NonPublic;
        public static object GetValueOfPrivateFieldFor(object instance, string fieldName)
        {
            FieldInfo fieldInfo = (FieldInfo)instance.GetType().GetMember(fieldName, ACCESS_PRIVATE_INSTANCE_FIELDS).GetValue(0);
            return fieldInfo.GetValue(instance);
        }

    }

    class PrivateDataHolder
    {
        private string data = "Foo";
    }
}

Gruß Tom
 
Hallo Tom!

Krasse Sache. Via Reflection bekommt man auch alles hin.
Nur leider ist das im sinne der OOP ein bissel abstrus. :D
Kannst du mir bitte ein Anwendungsbeispiel dafür nennen. Mir fällt nichts ein. :confused:
 
Hallo!

Ein Anwendungsfall ist beispielsweise der auf interne Felder einer Klasse aus einer Third-Party Library
zuzugreifen die dir sonst keine Zugriffsmöglichkeit (über Properties oder sonstiges) bietet.

Ein weiterer Anwendungsfall wäre die Entwicklung eines eigenen Debug Visualizers für Visual Studio.
Ich vermisse immernoch einen Visualizer der in IDictionary Implementierungen (beipspielsweise
HybridDictionary, ListDictionary) hinein schauen kann... :(

Außerdem muss ein O/R Mapper der Objekte auf Tabellen abbildet ja auch den "kompletten" Zustand eines Objekts analysieren können um dieses entsprechend vollständig zu speichern. Dabei muss er natürlich auch auf den Zustand zugreiffen können der in privaten Attributen versteckt ist.

Gruß Tom
 
Hallo nochmal!

Jetzt kann ich mir was darunter vorstellen. Ich muss zugeben,
dass ich noch nie auf die Idee gekommen bin einen eigenen Debug Visualizer zu schreiben,
was mir jetzt aber sicherlich nicht mehr schwer fallen wird.

Ich danke Dir. :)
 
Bezüglich O/R Mapper seh ich das nicht unbedingt so. Es hängt sehr stark davon ab, wie der O/R Mapper arbeitet und vor allem auch wie das Mapping ansich aussieht. Wichtig ist, was die öffentliche Eigenschaft zurückliefert und eigentlich weniger, wie es mit der privaten Variable aussieht, da die public Property diesen Wert ansich nicht ändern sollte. Immerhin wird normalerweise auch die öffentliche Eigenschaft gemappt und nicht die private.
 
Hallo!

Das das von der Arbeitsweise des O/R Mappers abhängt ist ja wohl klar...
Wichtig ist, was die öffentliche Eigenschaft zurückliefert und eigentlich weniger, wie es mit der privaten Variable aussieht, da die public Property diesen Wert ansich nicht ändern sollte. Immerhin wird normalerweise auch die öffentliche Eigenschaft gemappt und nicht die private.
Na ja, die interne Objektrepräsentation (private Attribute) spielt IMHO aber auch eine entscheidenede Rolle. Es kann ja durchaus Zustand geben, der nicht über ein öffentliches Property zugreifbar ist aber trotzdem das Verhalten der jeweiligen Enität beeinflusst. Würde man hier einfach nur die öffentlichen Properties berücksichtigen könnte man den Objektzustand nicht vollständig speichern.

Gruß Tom
 
Das ist schon richtig, stellt sich nur die Frage, wie sinnvoll es ist, einen bestimmten Status (der für den O/R Mapper relevant ist) nicht öffentlich zugänglich zu machen. Dadurch ist der O/R Mapper gezwungen, das komplette Objekt zu zerlegen, was ihn natürlich verlangsamt.
 
Hallo,

Mit einem O/R Mapper willst du in der Regel die transparente Persistenz deines Objektmodells ermöglichen.
D.h. du willst möglichst einfach den kompletten Entitätszustand in der Datenbank speichern und nach der
Wiederherstellung der Entität soll der Entitätszustand (und das Verhalten) wieder genauso sein wie vor der
Persistierung.

Ein Beispiel wäre beispielsweise ein Property names SubmittedJobs das nur über einen get Accessor verfügt und
intern auf ein privates Attribut namens submittedJobs abgebildet wird. Wenn diese Enität in der Datenbank abgelegt
wird und später ausgelesen wird muss der O/R Mapper die Möglichkeit haben schreibend auf diese Feld zuzugreifen.
Da hier aber kein set Mutator am Property definiert ist (submittedJobs könnte beispielsweise ein interner
Zähler sein, der bei dem Aufruf einer submit(new Job("XXX")); Methode inkrementiert wird. Da der Zustand dieses
Properties /Attributs nur von intern manipuliert wird macht ein set Mutator keinen Sinn.) kann dies nur per Reflection erfolgen.

Gruß Tom
 
Oder man geht von folgender Situation aus:

DataObject User. Jeder User hat Rechte (Referenz). Diese werden in einer ObjectList (Collection) abgebildet. Sieht dann in etwa so aus (Generics lass ich jetzt mal aussen vor):
C#:
public class User
{
   private ObjectList rights = new ObjectList(typeof(Rights));

   public ObjectList Rights
   {
      get { return rights; }
   }
}

ObjectList ist in diesem Beispiel eine Custom Collection und besitzt beispielsweise eine Methode AddRange:
C#:
ObjectList.AddRange(ObjectList objects);
Und in dieser Konstellation muss der O/R Mapper nicht auf die privaten Member zugreifen. So gesehen ist es ziemlich sinnlos darüber zu diskutieren, da genau dieses Beispiel vom O/R Mapper selbst abhängig ist bzw. vom dahinterliegenden Design.

Es gibt aber natürlich durchaus Fälle wo dies Sinn macht, vor allem wenn man an das Thema Application Server denkt.
 
Zurück