Entwickler-Ecke
WinForms - Feldname Erkennung aus String
frenchcancan - Do 31.03.11 11:05
Titel: Feldname Erkennung aus String
Hallo!
ich kämpfe immer noch mit der Übernahme von Konfigurationsdaten über einen String. ich bekomme folgenden String: ""variable1",2000;"
In C hatte ich das so gelöst: ich vergleicheden VariablenNamen in eine Tabelle wo für jeden VariablenNamen die Adresse der entsprechenden Variable im Objekt steht. Und setze den Wert über diesen Zeiger
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| typedef struct { string name; int *p_parameter; }t_cfglist;
t_cfglist parlist[] = { {"variable1",&configObjekt.variable1}, {"variable2",&configObjekt.variable2}, {"variable3",&configObjekt.variable3},
} |
Parsen und Wert zuweisen:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| for (i=0; i < 3;i++) { found = strstr(s,dslist[i].name); if (found !=NULL) // Feldname gefunden { *dslist[i].p_parameter = *value;// setzen des Wertes break; } } |
In C# scheitere ich damit aber schon beim Initialisieren des parlist array. Der Compiler nimmt dort keine Adresse von dem Objekt, den ich zuvor erstellt habe
Ich bekomme immer die Meldung:
der Zugriff WindowsFormsApplication1.allParam.geraetConfig auf ist aufgrund der SicherheitsEbene nicht möglich.Was mache ich falsch? ich mache es so:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| class allParam { public static geraetConfig poloscfg = new geraetConfig(); public class geraetConfig { int variable1; int variable2; int variable3; } private class t_cfglist { string name; int *p_parameter; }
t_cfglist parlist1 = new t_cfglist { {"variable1",&poloscfg.variable1}, {"variable2",&poloscfg.variable2}, {"variable2",&poloscfg.variable3}};
} |
Th69 - Do 31.03.11 11:51
Hallo,
mit "Sicherheitsebene" ist hier der sog. "access modifier" gemeint, d.h. "private", "protected", "internal" oder "public".
In C# mußt du jede Klassenvariable explizit mittels obigen "Zugriffsmodifizierern" angeben, ansonsten sind diese alle "private" und man hat keinen Zugriff darauf.
Außerdem benötigst du in C# (außer für System- bzw. Interop-Kommunikation) keine Zeiger!
Oder anders ausgedrückt: dein Vorgehen ist nicht 1:1 von C bzw. C++ aus übertragbar.
Da C# intern mit Referenzen arbeitet (und die Objekte vom GarbageCollector verwaltet werden), kannst du keine Speicheradressen direkt verwenden.
Am besten, du verwendest String.Split() zum Aufteilen deiner Config-Strings und dann in einer switch-case-Anweisung (C# kann hier auch Strings vergleichen!) setzt du die einzelnen Werte.
frenchcancan - Do 31.03.11 12:07
OK, danke schön, Das heißt also so etwas wie
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| void set("paramNname",value) { switch (paramName) { case "variable1": configObjekt.variable1 = value; break; case "variable2": configObjekt.variable2 = value; break; case "variable3": configObjekt.variable3 = value; break; } } |
das hätte ich so gern vermioeden, weil es eine sehr große VAriablenliste ist. Aber nach gut, das mache ich dann so.
Vielen Dank!
frenchcancan
Moderiert von
Christian S.: C#-Tags hinzugefügt
Th69 - Do 31.03.11 12:21
Hallo,
als einzige Alternative dazu fiele mir noch Reflection ein, d.h. wenn deine Klassenvariablen genauso heißen wie die Config-Parameter (alternativ natürlich mittels eines Mappings):
C#-Quelltext
1: 2: 3: 4: 5: 6:
| using System.Reflection;
FieldInfo fi = typeof(t_cfglist).GetField(paramName, BindingFlags.NonPublic | BindingFlags.Instance); if (fi != null) fi.SetValue(poloscfg, value); |
bakachan - Do 31.03.11 12:47
Also falls du die geraetConfig verändern kannst würde ich eher zu einem Dictionary tendieren.
C#-Quelltext
1:
| Dictionary<string, int> _values; |
(das int kannst du natürlich auch durch andere Klassen ersetzen, je nachdem was du benötigst, notfalls object)
frenchcancan - Fr 01.04.11 08:35
Danke für die Antworten!
Ich habe es jetzt mit System.Refelction probiert aber ich bekomme immer die Meldung "nicht gefunden"
Kannst du mir noch einen tip geben?
Und geht es auch mit verschalteten Obkekten? Z. B. wenn die Klasse ein Feldname teil1.variable1 udn teil1.variable2 hätte?
Danke schön!
Mein Klasse sieht so aus:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| class testconfig { public class geraetConfig { int variable1; int variable2; int variable3; } } |
Und mein Code:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| private void feldZuweisen(testconfig poloscfg, string paramName, int value) { FieldInfo fi = typeof(testconfig).GetField(paramName, BindingFlags.NonPublic | BindingFlags.Instance); if (fi != null) fi.SetValue(poloscfg, value); else MessageBox.Show("nicht gefunden");
}
private void Form1_Load(object sender, EventArgs e) { string neuerParameter; string[] textAbschnitte; testconfig poloscfg = new testconfig(); Match m; int value;
neuerParameter = "variable1;2000"; textAbschnitte = neuerParameter.Split(';'); m = Regex.Match(textAbschnitte[1], @"\d+"); if (!int.TryParse(textAbschnitte[1].Substring(m.Index, m.Length), out value)) value = -1; feldZuweisen(poloscfg, textAbschnitte[0], value);
} |
frenchcancan - Fr 01.04.11 08:45
bakachan hat folgendes geschrieben : |
Also falls du die geraetConfig verändern kannst würde ich eher zu einem Dictionary tendieren.
C#-Quelltext 1:
| Dictionary<string, int> _values; |
(das int kannst du natürlich auch durch andere Klassen ersetzen, je nachdem was du benötigst, notfalls object) |
Hallo! Danke für die Antwort.
Ein Dictionary wäre natürlich schön, weil ich keine festgelegt Objektstruktur hätte, sondern sie einfach beim Einlesen bilden würde.
Aber geht es auch mit verschachtelte Objekten?
In der Realität bekomme ich nämlich einen String mit "spin.admin.variable1;value"
oder "spin.admin.variable2;value" und dann spin.service.variable3"
und würde es in Baumform darstellen.
Kann ein Dictionary so etwas leisten? oder ist es zu kompliziert?
Danke schön!
Th69 - Fr 01.04.11 09:38
Hallo frenchcancan,
in dem Reflection-Code mußt du schon die richtige Klasse (d.h. den Typ) angeben, d.h.
C#-Quelltext
1:
| typeof(testconfig.geraetConfig) |
(und auch deine Variable 'poloscfg' bei SetValue muß dann von diesem Typ sein!)
Automatisch sucht er nicht in untergeordneten Klassen.
Auch bei einem Dictionary geschieht das nicht automatisch.
Vllt. solltest du noch mal genauer beschreiben, wie deine Config-Datei aussieht und wie du dir dann die Config-Klassen in deinem Programm vorstellst?
frenchcancan - Fr 01.04.11 10:08
Hallo,
vielen Dank, ich verstehe was falsch war, es war tatsächlich
Gerade hat eine Besprechung meine Versuche aber zurücjk geworfen, da wir das Programm doch mit Net 4.0 machen wollen, damit die REstellung dynamischer Objekte erlaubt sind.
Da muss ich mich wohl erstmal einlesen müssen...
Meine Konfigurationsdatei ist eingentlich relativ komplex, deswegen hatte ich sie nicht geschickt. sie hat 3 Ebenen: 1. Ebene Geräte: spin, dispense arm (bis 3 ), z-achse
jede Ebene ist unterteilt in 4 Bereichen: operator,admin,service, factory und in der letzten Ebenen sind die eigentlichen Parameter, die die Geräte beschreiben (maximale Speed, Länge, Anzahl Ventile, usw...)
verkürzt sieht sie so aus:(Siehe am Ende des Beitrages)
da das Gerät aus dem ich lese aber eine eigene Konfiguration hat (es fehlen ihm zum Beispiel ein dispense arm oder eine Z-Achse), weiß ich beim Einlesen noch nicht, wie das Ziel Objekt aussehen wird.
Ich werde also über die USB Schnittstelle Text bekommen wie
"spin.admin.language;0"
oder
"spin.oper.nextstepavail;1"
oder
"spin.factory.maxspeed;10000"
oder
"da[0].admin.parklspeed;12"
Ich stelle es mir so vor, dass ich beim Einlesen das verschachteltes Konfigurationsobjekt bilde und die werte zuordne und es dann als treeview anzeige. Mal gucken, ob es klappt.
Falls ihr tips habt, sehr gerne!
Vielen Dank und ein schönes erholsames Wochenende nachher
Konfigurationsobjekt, wie es sein kann:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65:
| public class PolosConfig { spinclass spin; zaclass za; daclass[] da = new daclass[3]; } public class spinclass { spinoper oper; spinadmin admin; spinservice service; spinfactory factory;
public class spinoper { int nextstepavail; int backtostartpos; int terminal; } public class spinadmin { int language; int vakuum_on; int emerg_decc; int emerg_novac;
} public class spinservice { int lidvariations; int depouts; } public class spinfactory { int servo; int valvefrom; int valveto; int hallsensor; int maxspeed; }
} public class daclass { daoper oper; daadmin admin; daservice service; dafactory factory;
public class daoper { int oper_startpos_rad; } public class daadmin { int posspeed; int parkspeed; int parkposdiamm; int predipensediam;
} } usw... |
Kha - Fr 01.04.11 10:44
Bei dem Umfang würde ich auf jeden Fall auf Reflection setzen. Du musst eben diesen "Property-Pfad" (oh, ok, du hast ja gar keine Properties ;) ) parsen, dich vom Wurzelobjekt aus durchhangeln und dann das angegebene Feld setzen.
frenchcancan - Fr 01.04.11 10:48
Kha hat folgendes geschrieben : |
| Bei dem Umfang würde ich auf jeden Fall auf Reflection setzen. Du musst eben diesen "Property-Pfad" (oh, ok, du hast ja gar keine Properties ;) ) parsen, dich vom Wurzelobjekt aus durchhangeln und dann das angegebene Feld setzen. |
OK, vielen Dank,
ich versuche es mit Refelection.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!