Autor Beitrag
schlumsch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 122

alles Win :)
Delphi 2005 Prof, Delphi 2007
BeitragVerfasst: Di 20.04.10 15:08 
Hallo Gemeinde,

ich bin absolut neu in C# und stehe vor dem folgenden Problem:

Ich habe ein Textfile in welchem Zeilenweise Objekte mit ihren Attributen stehen. Das Format kann ich selber bestimmen, derzeit siehht es ungefähr so aus:

Zeit1|Zeit2|Objektname1|attributname1:attributtyp1|attributname2:attributty
p2|......
Zeit1|Zeit2|Objektname2|attributname1:attributtyp1|attributname2:attributty
p2|......
Zeit1|Zeit2|Objektname3|attributname1:attributtyp1|attributname2:attributty
p2|......
.
.
.

Nun bekomme ich ein Logfile und überprüfe wo dieses dem oben definierten Format entspricht, genauer: Wenn der Objektname einem Eintrag in Zeile x Position 3 meines oben geposteten Textfiles entspricht dann prüfe ich ob Anzahl und Typ der folgenden Attribute stimmen.

Soweit alles machbar denke ich, nun möchte ich allerdings nach der Prüfung gerne aus jeder Zeile meines Logfiles ein Objekt mit dem an Stelle 3 definierten Typ erstellen. Hier liegt mein Problem: wie? *g*

Das Format meines Logfiles kann sich ändern. Daher möchte ich nur an einer Stelle mein intern benutztes Format anpassen müssen, dies wäre im o.g. Textfile. Ich möchte also nicht zusätzlich "per Hand" Klassen definieren und dann Objekte daraus erstellen.

So wie ich mir das vorstelle würde ich jede Zeile meines Textfiles nach "|" und danach nach ":" splitten und dann sagen wollen:

Neue Klasse, Attributname = String vor dem ":" mit Attributtyp nach dem ":" so lange bis kein "|" ...


Geht das? :) Wenn ja wie?

_________________
icq 102779206
"God is real, unless declared integer..."
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: Di 20.04.10 15:26 
Soll ich jetzt meine Antwort und eine weitere hierher kopieren, oder wie stellst du dir das vor?

Außerdem hat deine Frage wenig mit IO zu tun (bloß weil du die Informationen aus einer Textdatei holen willst), sondern viel, viel mehr mit dem Finden und Erstellen von Objekten nach dem Klassennamen.

Jürgen
danielf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1012
Erhaltene Danke: 24

Windows XP
C#, Visual Studio
BeitragVerfasst: Di 20.04.10 15:27 
Hallo,

ja das geht. Das nennt sich in .NET Reflection. Interessant könnte für dich die Klasse Activator sein. Dort kannst du unter anderem CreateInstance verwenden um mit dem Namen eines Typ ein Objekt zu erstellen. Den Typ bekommst du wiederum mit Assembly.GetExecutingAssembly().GetType("blub") bekommen.

Properties kannst du über <type>.GetProperty("name").SetValue(<dein erstelltes objekt>, <value>, null);

Aber ich denke mit dem Stichwort Reflection kommst du eh weiter (da gibts viel im Netz). Bei konkreten Problemen kannst dich ja nochmal hier im Thread melden.



.. öhm.. beim zehnten mal durchlesen denke ich das du doch was anders suchst...

Du hast die Klassen nicht, sondern willst diese erstellen?

Warum erstellst du nicht eine Klasse die einfach eine Liste von Attributen mit (Name, Type und Wert hat) und packst alles da rein?

Oder wie willst du es später wiederverwenden?

Ich bin verwirrt :o

Bitte um weitere Aufklärung.

Gruß
schlumsch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 122

alles Win :)
Delphi 2005 Prof, Delphi 2007
BeitragVerfasst: Di 20.04.10 15:49 
@JüTho: Also irgendwie fühl ich mich ein wenig veräppelt, um mal die Kraftausdrücke bei Seite zu lassen. Ich erwarte überhaupt nicht das du mir antwortest und finde die Crassposting-Regelung ziemlich blöd. Ist nun mal so das nicht alle Leute nur in einem Forum angemeldet sind und wenn man schnell eine Antwort benötigt est es schon hilfreich in mehreren Foren nachzufragen. Es ist ja absolut ausreichend wenn der Helfende in einem Forum hilft ... klingt blöd aber was solls...
Des weiteren habe ich ie Forne hier durchgeschaut und da ich das Forum "Finden und Erstellen von Objekten nach dem Klassennamen" nicht gefunden habe bin ich hier gelandet, bitte entschuldige!

-------------

So, nun wieder zum Thema: thx @ danielf. Ich habe mittlerweile auch schon von Activator gehört und werde das versuchen, insofern ich die Rahmenstruktur für mein Programm fertig habe. Ich melde mich wenns hakt :)


--- Moderiert von user profile iconKha: Beiträge zusammengefügt ---


Ha, und ich sollte erstmal Beiträge ganz lesen bevor ich antworte :)

Was ich habe ist ein Logfile in einem bestimmten Format, welches sich ändern kann...weiter erst einmal nichts.
Dabei ist jede Zeile ein abgeschliossener Datensatz, das Attribut 3 bestimmt den Typ, unterschiedliche Typen haben unterschiedliche (auch anzahl) weiterer Attribute.

Nun habe ich mir gedacht dass ich mir ein Textfile mit der Formatdef. erstelle, welches ich ggf. abändern kann. Klar ich in für jedes Objekt eine Klasse anlegen und dort alles hineinpacken , würde allerdings bedeutes dass ich bei jeder Formatänderung nicht nur meine FTextfile sondern eben auch jede Klasse abändern müsste...

_________________
icq 102779206
"God is real, unless declared integer..."
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 20.04.10 16:16 
user profile iconschlumsch hat folgendes geschrieben Zum zitierten Posting springen:
Ist nun mal so das nicht alle Leute nur in einem Forum angemeldet sind und wenn man schnell eine Antwort benötigt est es schon hilfreich in mehreren Foren nachzufragen.
Und wenn verschiedene Personen in den verschiedenen Foren die gleiche Lösung erarbeiten, ohne voneinander zu wissen, ist das ja nicht dein Problem, stimmt ;) ...

user profile iconschlumsch hat folgendes geschrieben Zum zitierten Posting springen:
Das Format meines Logfiles kann sich ändern. Daher möchte ich nur an einer Stelle mein intern benutztes Format anpassen müssen, dies wäre im o.g. Textfile. Ich möchte also nicht zusätzlich "per Hand" Klassen definieren und dann Objekte daraus erstellen.
Dann gibt es nur zwei Möglichkeiten: Entweder du verzichtest auf die Textdatei und speicherst die Informationen stattdessen wie von Daniel vorgeschlagen in Attributen direkt in der Klasse oder du lässt aus der Textdatei automatisch Text generieren - mit T4 sollte das relativ leicht möglich sein.
Beide Verfahren fallen aber wahrscheinlich nicht gerade unter die Kategorie "anfängerfreundlich" :| .

_________________
>λ=
schlumsch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 122

alles Win :)
Delphi 2005 Prof, Delphi 2007
BeitragVerfasst: Di 20.04.10 16:44 
Okay, ja nach Anfängerfreundlich klingt das wirklich nicht. Um mich da mal nicht in Tutorials zu verrennen denke ich wird es (zumindest im ersten Schritt) besser sein Klassen zu definieren. Danach werd ich mir mal Reflection zu Gemüte führen

_________________
icq 102779206
"God is real, unless declared integer..."
schlumsch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 122

alles Win :)
Delphi 2005 Prof, Delphi 2007
BeitragVerfasst: Mi 21.04.10 15:06 
Ja .. *meld* :)
Also ich versuche mich ein wenig in Reflektion einzuarbeiten und komme nicht wirklich weiter. Alle beispiele die ich bis jetzt gesehen habe drehen sich um die Auflistung von Feldern & methoden von Assemblys. Wenn ich das richtig verstehe ist eine Assembly zB ein Programm, sprich exe oder dll. Das bringt mir allerdings nicht allzuviel. Ich müsste quasi aus meinem Textfile mit den Objektdefinitionen jeweils eine Zeile auslesen und dann zur Laufzeit eine Klasse daraus generieren und dann beliebig instanziieren.

Der Klassenname müsste der jeweils 3te Eintrag in meinem Textfile sein, die Felder und Feldtypen werden durch die verbleibenden Einträge dieser Zeile definiert.

Eventuell kann mir da jemand einen Tip geben wo ich mich da schlau machen kann, derzeit verrenne ich mich in allen möglichen Tutorials :twisted:

thx a lot

_________________
icq 102779206
"God is real, unless declared integer..."
danielf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1012
Erhaltene Danke: 24

Windows XP
C#, Visual Studio
BeitragVerfasst: Mi 21.04.10 15:33 
Was bringt es den dir eine Klases zur Laufzeit zu generieren? Was willst du damit erreichen?

Ich hab die Frage schon mal gestellt... und finde es dreist wie du hier reagierst. Das führt nur dazu das dir niemand mehr antwortet - egal in welchem Forum.
schlumsch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 122

alles Win :)
Delphi 2005 Prof, Delphi 2007
BeitragVerfasst: Mi 21.04.10 16:03 
Moment .. wieso denn dreist? Ich dachte ich hätte auf die Frage geantwortet, sorry wenn dem nicht so ist.
Mein Hauptproblem ist im Endeffekt das ich mit einem Logfile umgehen muss, dessen Format sich unter Umständen öfters ändert. Bei einer derartigen Änderung soll nicht jedes Mal mein ganzes Programm umgeschrieben werden. Deswegen ist mein derzeitigerc Ansatz das ich mir eine Definitions-datei anlege, dort zeilenweise hineinschreibe welches Feld von welchem Typ ein bestimmtes Objekt hat.

Bsp:
25.01.2010|26.01.2010|meinAuto|Farbe:String|Marke:String|......


Wenn ich nun in meinem Programm "selber" eine Klasse meinAuto anlege und dort die Felder als String definiere, so muss ich immer wenn ein anderes Logfileformat vorliegt auch die Klasse ändern.

25.01.2010|26.01.2010|meinAuto|Farbe:String|Marke:String|Länge:String|.... würde bedeuten ich muss die Klasse in meinem Programm ebenfalls "selbst" erweitern.

Nun dachte ich es wäre doch sicher möglich "einfach" ( :P ) die Klasse meinAuto nach dem Lesen des Definitionsfiles zu erstellen, der Klasse die im Definitionsfile hinterlegten Felder mit Feldtypen zu geben.
Danach könnte ich dann mein logfile einlesen, bei jedem "meinAuto" ein neues Objekt meiner eben angelegten Klasse instanziieren und meine Verarbeitungen starten.

Vorteil ist nun, dass ich nur das Definitionsfile anpassen muss sobald sich der log ändert.

_________________
icq 102779206
"God is real, unless declared integer..."
danielf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1012
Erhaltene Danke: 24

Windows XP
C#, Visual Studio
BeitragVerfasst: Mi 21.04.10 16:29 
Dreist hinsichtlich des crosspoints und dem damit nicht verbundenen Reuegefühl. Sowie die Tatsache, damit du dich nicht mit unseren Antworten befasst, sondern unbeeindruckt Fragen auf bereits gelöste Aspekte stellst.

Also ich versuche es nochmal.

Du musst doch so oder so deinen Code anpassen, wenn sich die Attribute deiner Klasse ändern. Abgesehen davon, ob du das nun manuell oder mithilfe eines Programm machst. Bsp:

Deine Klasse Auto:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
class Auto
{
   public string Farbe { get; set; }
   public string Marke { get; set; }
}


Wenn nun die Klasse um das Attribut Länge erweitert wird, würde ein Code-Generator die Eigenschaft Länge vom Typ (dein Beispiel) string hinzu fügen. Den restlichen Code (wo du die Länge verwenden willst) musst du nun aber alles selber anpassen. Weil die Änderung der Klassenstruktur hat keinerlei Auswirkung auf deinen restlichen Code. Dort müsstest du bei jedem Zugriff überall das Auslesen/Setzen der Eigenschaft Länge per Hand nachziehen!!

Deshalb haben wir dir geraten einen generischen Typ zu machen, der wie deine Definitionsdatei/Logdatei/beliebige Quelle agiert und dementsprechend flexibel ist.

Das erreichst du eben, wenn du eine Klasse machst, die eine Liste von Attributen hat... wie in deiner Quelle.

Eine spezifische Klasse würde dir eh nichts nützen.

Comprende?
schlumsch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 122

alles Win :)
Delphi 2005 Prof, Delphi 2007
BeitragVerfasst: Mi 21.04.10 17:23 
Okay, zum Thema crosspoints hatte ich meine Auffassung geschildert und habe eure Argumentation keinesfalls ignoriert. Bislang habe ich es so gehalten das ich bei Antworten in einem Forum eventuelle Lösungsvorschläge eines anderen Forums mit eingebunden habe, sorry.


Zu der von dir erwähnten erforderlichen Codeanpassung: Ich muss lediglich die Daten aus dem Logfile überprüfen und danach in ein xml schreiben. Neue Felder werden also "nicht wirklich" verarbeitet, sondern müssen nur abgespeichert werden.
Soweit ich weiss kann das XML auf einer bestehenden Datenstruktur einfach via XmlSerializer erstellt werden.


Mit den Vorschlägen zur Lösung habe ich mich auch beschäftigt und ganz einfach Probleme mit der Umsetzung, wie gesagt ich habe sogesehen noch keine Zeile C# programmiert bevor ich dieses Projekt hier angehen durfte. (Ich habe so einige Beispiele zu Reflektion ausgetestet, ein wenig hat es mir auch geholfen)


Aber mal zurück zu der von dir angesprochenen Liste von Attributen:
Zitat:

Deshalb haben wir dir geraten einen generischen Typ zu machen, der wie deine Definitionsdatei/Logdatei/beliebige Quelle agiert und dementsprechend flexibel ist.
Das erreichst du eben, wenn du eine Klasse machst, die eine Liste von Attributen hat... wie in deiner Quelle.


Sorry, leider verstehe ich das nicht so ganz und steh hier auf dem Schlauch.
Wie sähe die von dir angesprochene Liste von Attributen aus?

_________________
icq 102779206
"God is real, unless declared integer..."
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 21.04.10 17:35 
user profile iconschlumsch hat folgendes geschrieben Zum zitierten Posting springen:
Neue Felder werden also "nicht wirklich" verarbeitet, sondern müssen nur abgespeichert werden.
Dumm gefragt: Wofür dann überhaupt eine typisierte Container-Klasse? Würde es nicht genügen, wenn man über meinAuto["Farbe"] zugreifen würde?

Ansonsten ist mir nicht mehr klar, welchen der drei Wege du nun bestreiten willst - die Definitionsdatei fallen lassen und stattdessen in Attribute kodieren?

_________________
>λ=
norman2306
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 222
Erhaltene Danke: 16

Win XP, Win 7 64-Bit
C# 4.0 (VS2010)
BeitragVerfasst: Mi 21.04.10 18:40 
So eine Spielerei mit dynamisch erstellten Typen habe ich mal gemacht, obwohl ich bezweifle, dass das, was du damit machen möchtest wirklich den Aufwand wert ist. Ich klemme dir trotzdem mal den Code ran. Er wandelt einen Dictionary<string,object> in einen dynamischen Typen um, wobei den Feldern/Properties immer der Typ zugewiesen wird, den der Wert des objects gerade hat. Ich würde dir aber trotzdem eher empfehlen, die Hinweise von Kah und Daniel zu beachten.

ausblenden volle Höhe 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:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
        public static object ConvertToDynType(Dictionary<stringobject> ClassDefinition, string name, bool ConvertSubs)
        {
            // This code creates a single-module assembly (.dll). The module contains 
            // a type (consisting of objects), which is defined by Classdefinition. The key
            // is object-name, the dict-value is allocated to the objects value.
            // The resulting Type is "VDynamicType", that have the (public) fields and
            // the appropriate properties that gets and sets the fields and a constructors that 
            // initialize the fields.

            Dictionary<stringobject> ClassDef_tmp =
                new Dictionary<stringobject>(ClassDefinition);

            AssemblyName aName = new AssemblyName(name);

            // Writes a new Assembly in actual App-Domain
            AssemblyBuilder ab =
                AppDomain.CurrentDomain.DefineDynamicAssembly(
                    aName,
                    AssemblyBuilderAccess.RunAndSave);

            // Calls the ModuleBuilder to Create a new Module in the Assembly

            ModuleBuilder mb =
                ab.DefineDynamicModule(aName.Name, "VDynLib" + ".dll");
            
            // TypeBuilder to Create a new (public) class
            // is like:
            // public class VoithDynamicType
            // {
            // }
            TypeBuilder tb = mb.DefineType(
                name,
                 TypeAttributes.Public);




            // Creates a FieldBuilder-Array to create new objects
            // The Array-Size is the number of keys in ClassDef_tmp
            // (we want the same amount of object in the new Class).
            FieldBuilder[] Fields = new FieldBuilder[ClassDef_tmp.Keys.Count];

            // Creates a Type-Array. That´s necessary for the Konstruktor and
            // and to set the types of the object (we could take 'object' as
            // global type, but thats would be a little bit slower and takes
            // more Cache in the stack
            Type[] parameterTypes = new Type[Fields.Count()];


            // if the ClassDef_tmp contains sub-dictionaries, the are also converted
            // to a dynamic type
            if (ConvertSubs)
                for (int j = 0; j < ClassDef_tmp.Count; j++)
                {
                    if (ClassDef_tmp.Values.ToArray()[j] != null && ClassDef_tmp.Values.ToArray()[j].GetType() == typeof(Dictionary<stringobject>))
                    {
                        string sub_name = "Type" + ClassDef_tmp.Keys.ToArray()[j];
                        object subType = ConvertToDynType((Dictionary<stringobject>)ClassDef_tmp.Values.ToArray()[j], sub_name);
                        ClassDef_tmp[ClassDef_tmp.Keys.ToArray()[j]] = subType;
                    }
                }

            // Add the private fields
            for (int i = 0; i < ClassDef_tmp.Count; i++)
            {   Type T1 = typeof(object);
                //Get the Type of the value
               if(ClassDef_tmp.Values.ToArray()[i] == null)
                 T1 = typeof(object);
               else
                T1 = ClassDef_tmp.Values.ToArray()[i].GetType();


                //If the type of the value is a dynamic type, then save it
                //as 'object', else take the type of the value
                Type RefType = T1.FullName == tb.FullName ?
                    typeof(object) : T1;

                //Defines the Field
                //Like:
                // private string name;
                // private int TestInt;
                // ...
                Fields[i] = tb.DefineField(
                   "_" + ClassDef_tmp.Keys.ToArray()[i],
                   RefType,
                   FieldAttributes.Private);

                //fills the Type-Arr for the constructor-def
                if (ClassDef_tmp.Values.ToArray()[i] == null)
                    parameterTypes[i] = typeof(object);
                else
                    parameterTypes[i] = ClassDef_tmp.Values.ToArray()[i].GetType();

            }

            // Define a constructor that takes the object arguments and 
            // stores it in the fields. 
            // Like:
            // public VoithDynamicClass(int i1, string s1, double d1, int i2, ...)

            ConstructorBuilder ctor1 = tb.DefineConstructor(
                MethodAttributes.Public,
                CallingConventions.Standard,
                parameterTypes);

            // Creates an MSIL-Generator
            // (The Language between Assembler and Compiler)
            ILGenerator ctor1IL = ctor1.GetILGenerator();


            // Push the Instance of our new Class to the stack
            ctor1IL.Emit(OpCodes.Ldarg_0);

            // Creates some kind of an empty Constructor
            ctor1IL.Emit(OpCodes.Call,
                typeof(object).GetConstructor(Type.EmptyTypes));

            // Pushing the arguments
            // that have to be assigned to the fields.
            for (int k = 0; k < Fields.Count(); k++)
            {
                //Load our Class
                ctor1IL.Emit(OpCodes.Ldarg_0);
                //Load the Param at Position k
                ctor1IL.Emit(OpCodes.Ldarg_S, k + 1);
                //Write it to our Field-Definition
                ctor1IL.Emit(OpCodes.Stfld, Fields[k]);

                //{
                //  int i = 0;
                //  string s = "irgendwas";
                //  ...
                //}


            }
            // Close the Constructor (like: return)
            ctor1IL.Emit(OpCodes.Ret);

            // Defines the set and get-Accessors
            for (int n = 0; n < ClassDef_tmp.Keys.Count; n++)
            {
                Type T1 = ClassDef_tmp.Values.ToArray()[n].GetType();
                Type RefType = T1.FullName == tb.FullName ?
                    typeof(object) : T1;




                PropertyBuilder pbNumber = tb.DefineProperty(
                        ClassDef_tmp.Keys.ToArray()[n],
                        PropertyAttributes.HasDefault,
                        RefType,
                        null);

                // Defines a compiler attribute. The attribute is used for tell
                // a PropertyGrid the category name
                CustomAttributeBuilder CAB = new CustomAttributeBuilder(
                    typeof(System.ComponentModel.CategoryAttribute).GetConstructor(new Type[1] { typeof(string) }),
                    new object[1] { name.Replace("Type""") });
                pbNumber.SetCustomAttribute(CAB);



                MethodAttributes getSetAttr = MethodAttributes.Public |
                        MethodAttributes.SpecialName | MethodAttributes.HideBySig;

                //Definition des Get-Accessors

                MethodBuilder mbNumberGetAccessor = tb.DefineMethod(
                        "get_Field",
                        getSetAttr,
                        RefType,
                        Type.EmptyTypes);

                ILGenerator numberGetIL = mbNumberGetAccessor.GetILGenerator();

                numberGetIL.Emit(OpCodes.Ldarg_0);
                numberGetIL.Emit(OpCodes.Ldfld, Fields[n]);
                numberGetIL.Emit(OpCodes.Ret);

                pbNumber.SetGetMethod(mbNumberGetAccessor);

                //Definition des Set_Accessors

                MethodBuilder mbNumberSetAccessor = tb.DefineMethod(
                        "set_Field",
                        getSetAttr,
                        null,
                        new Type[] { RefType });

                ILGenerator numberSetIL = mbNumberSetAccessor.GetILGenerator();
                // Load the instance and then the numeric argument, then store the
                // argument in the field.
                numberSetIL.Emit(OpCodes.Ldarg_0);
                numberSetIL.Emit(OpCodes.Ldarg_1);
                numberSetIL.Emit(OpCodes.Stfld, Fields[n]);
                numberSetIL.Emit(OpCodes.Ret);

                pbNumber.SetSetMethod(mbNumberSetAccessor);




            }
            CustomAttributeBuilder CAB1 = new CustomAttributeBuilder(
                typeof(TypeConverterAttribute).GetConstructor(new Type[1] { typeof(Type) }), new object[1] { typeof(VDTPropertyConverter) });
            tb.SetCustomAttribute(CAB1);

            CustomAttributeBuilder CAB1 = new CustomAttributeBuilder(
                typeof(SerializableAttribute).GetConstructor(new Type[1] { typeof(Type) }), new object[1] { typeof(SerializableAttribute) });
            tb.SetCustomAttribute(CAB1);

            Type t = tb.CreateType();

            // The following line saves the single-module assembly. This
            // requires AssemblyBuilderAccess to include Save. You can also write a program that has
            // a reference to the assembly, and use the DynamicType type.
            // 
            /*
            try
            {
                ab.Save(aName.Name + ".dll");
            }
            catch
            {
              //add
            }
            */



            object[] args = new object[ClassDef_tmp.Count];
            args = ClassDef_tmp.Values.ToArray();

            // Creates a Instance of our new class:-)
            object o2 = Activator.CreateInstance(t, args);




            return o2;
        }
schlumsch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 122

alles Win :)
Delphi 2005 Prof, Delphi 2007
BeitragVerfasst: Mi 21.04.10 20:46 
Ja - welchen Weg will ich bestreiten ... gute Frage. Zunächst habe ich noch immer ein Verständnisproblem zu dem
Vorschlag generischer Typ von danielf. Bei einem generischen Typ lege ich den genauen Typ, also ob String, int..., nicht fest, right? Ich denke mal zu Generics muss ich mich noch schlau machen, habe noch nicht damit gearbeitet. Hat da vielleicht jemand ein kurzes Beispiel oder einen guten Link?

Wie du an meinem "hin und her" hier im Thread merkst ist mir der genaue Lösungsweg mehr oder weniger egal, hauptsache das ganze ist am Ende einigermassen dynamisch. Wenn ich die oben genannten, mir derzeit noch fremden Generics aussen vor lasse würde ich auf deine Frage:
Zitat:

...wenn man über meinAuto["Farbe"] zugreifen würde?

so antworten:

Nicht ganz, prinzipiell schon *g*, ich müsste über alle Attribute der Klasse iterieren können. Aus meinem Log-File kann ich ja den Names eines Attributes ermitteln (das was vor dem : steht).Den Namen der Klasse habe ich auch aus dem Log. Nun müsste ich meine definierte Klasse instanziieren und für jeden Logfile-Eintrag nach dem passenden Attribut in der Klasse suchen und dort den Wert zuweisen.

@norman2306: ich danke dir für deinen code.
Ich denke mal ich werde morgen sowohl das Thema Generics wie auch den Code mal genauer anschauen und danach endlich zu einer Entscheidung kommen, wie ich mein Problem löse. Jetzt ist erstmal Fussball :shock: 8)

thx, bis morgen *g*

_________________
icq 102779206
"God is real, unless declared integer..."
schlumsch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 122

alles Win :)
Delphi 2005 Prof, Delphi 2007
BeitragVerfasst: Do 22.04.10 14:18 
Hallo noch einmal,


ich habe mich dann doch dafür entschieden das Def-File weg zu lassen und das ganze in Klassen zu packen.
So habe ich zB. eine Klasse

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
    class Auto
    {
        public int A;
        public string B;
    }

und
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
    class Bahn
    {
        public bool C;
        public dictionary<stringint> D;
    }


Nun kann ich natürlich Listen vom Typ Auto oder Bahn erzeugen, soweit klar.
Es gibt doch sicher auch die Möglichkeit das ganze in einer Struktur zu speichern,
untypisierte Liste fällt mir hier ein aber darüber meckert ja jeder :)
Oder bin ich da voll auf dem Holzweg?

_________________
icq 102779206
"God is real, unless declared integer..."
danielf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1012
Erhaltene Danke: 24

Windows XP
C#, Visual Studio
BeitragVerfasst: Do 22.04.10 15:40 
Hmm.. wohl eher Holzweg ;)

Gegeben ist dein Loginput:
Zeit1|Zeit2|Objektname1|attributname1:attributtyp1|attributname2:attributty
p2|......
Zeit1|Zeit2|Objektname2|attributname1:attributtyp1|attributname2:attributty

Dynamisch sind jeweils die Attribute, die restlichen Eigenschaften dieser Zeile sind fix. Deshalb lässt sich daraus folgende Klasse ableiten:
ausblenden volle Höhe 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:
class LogEntry
{
    // pattern um die Log-Zeile zu erkennen --> ANPASSEN
    public const string Pattern = "Zeit1|Zeit2|Objektname1|attributname1:attributtyp1|attributname2:attributty";

    public DateTime Zeit1 { get; private set; }
    public DateTime Zeit2 { get; private set; }
    public string Name { get; private set; }
    public Dictionary<stringstring> Attribute ( get; private set; }

    private LogEntry(
    {
        Attribute = new Dictionary<stringstring>();
    }

    public LogEntry CreateLogEntry(string line)
    {
       LogEntry logEntry = new LogEntry();
       string[] args = line.Split('|');

       logEntry.Zeit1 = DateTime.Parse(args[0]);
       logEntry.Zeit2 = DateTime.Parse(args[1]);
       logEntry.Name = args[2];

       for (int i=3; i < args.Length; i++)
       {
            string[] keyValue = args[i].Split(':');

            Attribute.Add(keyValue[0], keyValue[1]);
       }
    }
}


Folgendermaßen würde die Verwendung aussehen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
string[] lines = File.ReadAllLines("Application.log");
List<LogEntry> logEntries = new List<LogEntry>();

foreach(var line in lines)
{
   if (IsRegex.Match(LogEntry.Pattern, line))
   {
      logEntries.Add(LogEntry.CreateLogEntry(line));
   }
}


So ungefährt :o
schlumsch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 122

alles Win :)
Delphi 2005 Prof, Delphi 2007
BeitragVerfasst: Do 22.04.10 16:42 
Ich danke dir erstmal. Das ist soweit nachvollziehbar und passt wohl besser :)
Ich teste es und gebe Bescheid ... habe da mitbekommen das ich mich in dem
Thread anfangs wirklich etwas unklar ausgedrückt habe deswegen muss ich da
noch etwas anpassen - wie gesagt thx.

_________________
icq 102779206
"God is real, unless declared integer..."
schlumsch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 122

alles Win :)
Delphi 2005 Prof, Delphi 2007
BeitragVerfasst: Fr 23.04.10 10:38 
Hallo nochmal,

ich habe da ein, genauer gesagt 3, Probleme mit dem Code.
Ich habe deine Klasse Logentry erstellt und den Aufruf in meiner
Programmklasse in die Main[] gepostet.


ausblenden volle Höhe 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:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Agls_New.Datenmodell;
using System.Xml;
using System.IO;
using System.Xml.Serialization;
using System.Text.RegularExpressions;

namespace Agls_New
{
   class Program

    {
        static void Main(string[] args)
        {



            string[] lines = File.ReadAllLines("Application.log");
            List<LogEntry> logEntries = new List<LogEntry>();

            foreach (var line in lines)
            {
                if (IsRegex.Match(LogEntry.Pattern, line))
                {
                    logEntries.Add(LogEntry.CreateLogEntry(line));
                }
            }
...





folgendes kommt dabei raus:



* Der Name "IsRegex" ist im aktuellen Kontext nicht vorhanden

* Für das nicht statische Feld, die Methode oder die Eigenschaft "LogEntry.CreateLogEntry(string)" ist ein Objektverweis erforderlich.

* LogEntry.CreateLogEntry(string)": Nicht alle Codepfade geben einen Wert zurück.


Kannst du mir da nochmal helfen?

_________________
icq 102779206
"God is real, unless declared integer..."
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: Fr 23.04.10 11:50 
Das sind alles Standard-Fehlermeldungen:
user profile iconschlumsch hat folgendes geschrieben Zum zitierten Posting springen:
* Der Name "IsRegex" ist im aktuellen Kontext nicht vorhanden

Du hättest durch einen Blick in die SDK-Doku/MSDN/Hilfe feststellen können, dass es keine Standardmethode ist. Wegen des Namens und der Argumente vermute ich, es handelt sich um eine statische Methode von LogEntry.

user profile iconschlumsch hat folgendes geschrieben Zum zitierten Posting springen:
* Für das nicht statische Feld, die Methode oder die Eigenschaft "LogEntry.CreateLogEntry(string)" ist ein Objektverweis erforderlich.

CreateLogEntry muss wohl als statisch deklariert werden. Diese Methode soll schließlich "aus dem Nichts" (nämlich nach dem String) ein Objekt vom Typ LogEntry erstellen.

user profile iconschlumsch hat folgendes geschrieben Zum zitierten Posting springen:
* LogEntry.CreateLogEntry(string)": Nicht alle Codepfade geben einen Wert zurück.

Es fehlt offensichtlich (!) die return-Anweisung für das erzeugte Element.

Daniel sollte den Code also nochmals überprüfen und ergänzen.

Gruß Jürgen
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Fr 23.04.10 11:56 
@user profile iconschlumsch: Erwartest du überhaupt, dass in der Logdatei einzelne Zeilen sind, die nicht dem Format entsprechen? Wenn nicht, lass die IsRegex-Zeile einfach weg und fange ggf. lieber Exceptions aus CreateLogEntry ab.
Statt einer statischen Methode bietet sich hier auch an, CreateLogEntry einfach zu einem Konstruktor zu machen (logEntry darin dann durch this ersetzen).

user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:
Daniel sollte den Code also nochmals überprüfen und ergänzen.
Och, user profile iconschlumsch kann es gerne auch erst einmal selbst versuchen ;) .

_________________
>λ=