PropertyInfo.Setvalue() mit List-Object

MarioR

Mitglied
Hallo,

ich möchte eine Property (List<irgendwas>) mit
SetValue() setzen, aber die Property bleibt immer leer?

Code:
// Ausschnitt aus der Settings-Klasse
...
        private List<Int16> intTest;
        [Category("Test"),
        DisplayName("IntegerTestList"),
        Description(""),
        public List<Int16> IntTest
        {
            get { return intTest; }
            set { intTest = value;}
        }
...


// Im Constructor
...
     intTest = new List<System.Int16>();
...

Damit kann ich diese diese Eigenschaft im PropertyGrid editieren.

Das schreiben in eine Parameterdatei geht auch
Code:
// Ausschnitt aus der SaveRoutine
...
xmlSubNode = configXml.CreateNode(System.Xml.XmlNodeType.Element, null, "valuelist", null);
if (property.PropertyType == typeof(List<System.Int16>))
 {
     foreach (System.Int16 item in (List<System.Int16>)property.GetValue(this, null))
      {
                listItem = configXml.CreateNode(System.Xml.XmlNodeType.Element, null, "listitem", null);
                listItem.InnerText = item.ToString().Trim();
                xmlSubNode.AppendChild(listItem);
      }
 }
...

erzeugt folgende XML
Code:
    <setting name="IntTest" serializeAs="List`1">
      <valuelist>
        <listitem>1</listitem>
        <listitem>2</listitem>
        <listitem>3</listitem>
      </valuelist>
    </setting>

das lesen geht geht auch
Code:
// Ausschnitt aus der Load-Routine
...
object wert;
if (property.PropertyType == typeof(List<System.Int16>))
 {
        List<System.Int16> list = new List<System.Int16>();
        System.Int16 item;
        foreach (System.Xml.XmlNode itemNode in configItem.ChildNodes)
        {
                if (System.Int16.TryParse(itemNode.InnerText, out item))
                            list.Add(item);
        }
        wert = list; //<<<<<<< (1)
        property.SetValue(this, wert, null); //<<<<< (2)
}
...

(1) die Liste wird richtig erzeugt

(2) die Zuweisung funktioniert nicht, Warum ?

gruß Mario
 
das PropertyInfo zeigt nur auf das List Objekt.
Du musst noch Item abfragen.

Ungefähr so:
Code:
PropertyInfo pi=typeof(List<short>).GetProperty("Item");

Oder, die Add Methode per Reflection dir noch liefern lassen.
 
PropertyInfo pi=typeof(List<short>).GetProperty("Item");
funktioniert nicht.

mit einem Reflection auf die Add-Methode hat auch keine Wirkung
Code:
if (property.PropertyType == typeof(List<System.Int16>))
{
    System.Int16 item;
    List<System.Int16> list;
    property.SetValue(this, new List<System.Int16>(), null);
    list = (List<System.Int16>)property.GetValue(this, null); 
    MethodInfo miList = list.GetType().GetMethod("Add");
    foreach (System.Xml.XmlNode itemNode in configItem.ChildNodes)
    {
        if (System.Int16.TryParse(itemNode.InnerText, out item))
            miList.Invoke(list,new object[] {item});
    }
}

... hat die gleiche Wirkung wie das normale "SetValue", die Liste "list" wird gefüllt,
nicht aber die zugehörige Property.

Kann es sein, dass getValue eine Kopie der zur Property gehörenden Variable erzeugt?
 
ehm ma ne andere Frage, du hast doch eh das List Objekt als List<T>, warum verwendest du nicht direkt die normalen Methoden von dem ohne weiter mit Reflection zu arbeiten :confused:
 
du hast doch eh das List Objekt als List<T>,
Habe ich nicht, da die Klasse die Grundlage für die Settings bildet,
sie stelle Load, Save und einige andere Funtkionen.
In der Application wird diese Klasse beerbt und mit den eigendlichen
Properties gefüllt.
Also können Load und Save die Properties nicht kennen, da es diese
hier noch garnicht gibt.
Aber man kann die Properties einer Klasse mit
Code:
foreach (PropertyInfo property in this.GetType().GetProperties())
durchlaufen.
 
Ich habe mal ein ZIP mit folgenden Dateien angehängt:

-Application.par = Speicherdatei
-ClassAppsettings.cs = Uprsprungsklasse mit Load und Save etc.
-ClassSettings.cs = Ableitung der ClassAppSettings

Die ClassSettings wird im Programm initialisiert und kann dann dem
PropertyGrid.SelectedObject zugewiesen werden. Damit sind alle
Properties die nicht die Eigenschaft "Browsable(false)" haben sichtbar.
 

Anhänge

  • Settings.zip
    7,6 KB · Aufrufe: 18
ok hab mal drüber geschaut

Aber das sind sone Monster Methoden das ichs mir ehrlich gesagt auch nicht näher anschauen wollt.

Auch die Kommentierung ist mir zu befremdend (oder ist das irgendwie so eingestellt das Summary Einzeilig da stehen soll), aber das ist eh mehr geschmacks Sache. :)

Was mir aber auffällt das du ja im Prinzip versuchst deinen aktuellen Objekt Zustand zu speichern.

Deshalb schau dir mal das SerializableAttribute an und speziell BinaryFormatter oder XMLSerializer.

Die machen im Prinzip das was du hier vor hast.

Ich persönlich würde BinaryFormatter bevorzugen, beim XMLSerializer muss man zu viel beachten.
 
Aber das sind sone Monster Methoden
Deshalb poste ich auch ungern komplette Klassen oder Programme.

oder ist das irgendwie so eingestellt das Summary Einzeilig

Wenn die Beschreibung aus ein paar Wörtern besteht, mache ich die immer
einzeilig.
Bei längeren Beschreibungen breche ich die Zeilen eigentlich. Falls Du aber die
Darstellung im Objektbrowser meinst, ich habe bisher keine Möglichkeit des
Zeilenumbruches in den <summary> Tags gefunden.


Was mir aber auffällt das du ja im Prinzip versuchst deinen aktuellen Objekt Zustand zu speichern.
Deshalb schau dir mal das SerializableAttribute an und speziell BinaryFormatter oder XMLSerializer.
Die machen im Prinzip das was du hier vor hast.
Ich persönlich würde BinaryFormatter bevorzugen, beim XMLSerializer muss man zu viel beachten.
Das macht die Save-Funktion auch wunderbar.
Auch die Load-Funktion tut was sie soll. Das Serialisieren und Deserialisieren
ist auch nicht das Problem, sondern nur die "blöde" propertyinfo.SetValue.

Das die Eigenschaften alle als Properties einer Klasse gehändelt werden, hat
den Vorteil, dass ich sie dem Anwender ohne weitere Probleme in einem
PropertyGrid präsentieren kann, in dem er die Eigenschaften editieren kann.

Ich möchte aber nicht für jede Applikation wieder aufs neue eine Save und Load
Funktion schreiben müssen, auch deshalb habe ich ja die Variante über die
Properties gewählt.

Gruß Mario
 
Hallo Spyke,

ich hab den Fehler gefunden.

Eben habe ich mir die Klassen noch einmal angesehen.

Befor ich die Listen implementiert hatte wurde die Setting Klasse im Konstruktor des MainFensters
erzeugt und das LoadConfig im OnLoad-Event des MainFensters aufgerufen.

Gleichzeitig mit der Listenimplementation verlagerte ich die LoadConfig vom OnLoad des mainfensters in den Konstruktor der ClassAppsettings :-( (pure Faulheit).

Die Listenmember der ClassSettings erzeuge ich auch in deren Konstruktor.
Nur da ClassSettings von ClassAppsettings erbt wird der Konstruktor von
ClassAppsettings zuerst ausgeführt, und damit auch LoadConfig.
Somit wird zwar SetValue korrekt ausgeführt, da aber die ListProperty noch nicht Instanziert (new List<...) ist, läust sie ins Leere.

grrrr.... Warum hab ich das nicht gleich gesehen :eek::-:)-)

nun, VIELEN DANK für Deine Hilfe, manchmal braucht man den richtigen Tip

Gruß Mario

CLOSED
 

Neue Beiträge

Zurück