Autor |
Beitrag |
danielf
      
Beiträge: 1012
Erhaltene Danke: 24
Windows XP
C#, Visual Studio
|
Verfasst: Fr 01.06.12 09:54
Hallo,
ich habe ein Objekt welches verschiedene Interfaces implementiert. Für jedes Interface möchte ich nun gerne eine Methode aufrufen. Wie realisiere ich das?
Ich dachte irgendwie das ich es mit einem Visitor-Pattern realisieren kann ... daran bin ich aber gescheitert (ruft ja nur eine spezifische Methode für ein Objekt auf).
Zum Beispiel:
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:
| interface IHasColor { string Color { get; } }; interface IHasSize { int Size { get; } } ;
class SingleObject : IHasColor { public string Color { get { return "Blue"; } } }
class MultipleObject : IHasColor, IHasSize { public string Color { get { return "Red"; } } public int Size { get { return 2; } } }
... Serialize .. { SingleObject single = new SingleObject(); MultipleObject multiple = new MultipleObject();
Serialize(single); Serialize(multipleObject); }
... Serialize( IHasColor color ) { return "Color=" + color.Color; }
... Serialize( IHasSize size) { return "Size=" + size.Size.ToString(); } |
Aus Performance-Gründen würde ich mir gern ein 'is' ersparen.
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| string Serialize(object obj) { StringBuilder sb = new StringBuilder(); if (obj is IHasColor) { sb.AppendLine(Serialize((IHasColor) obj)); }
if (obj is IHasSize) { sb.AppendLine(Serialize((IHasSize) obj)); } } |
Danke und Gruß
Daniel
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Fr 01.06.12 11:48
Wieso implementiert nicht jede Klasse einfach auch ein ISerialize und serialisiert sich selbst? In der Implementierung dieses Interfaces kannst du wieder auf deine wahrscheinlich schon vorhandenen Serialize Methoden umlenken.
|
|
danielf 
      
Beiträge: 1012
Erhaltene Danke: 24
Windows XP
C#, Visual Studio
|
Verfasst: Fr 01.06.12 12:00
Danke für die Anwort.
Weil ich nicht in jeder Klasse die gleichen Attribute wieder und wieder serialisieren will.
Mit Vererbung geht es auch nicht, da die Vererbungshierarchie nicht vorhanden ist.
( A hat Eigenschaften von B und C,
D hat Eigenschaften von F und C )
Dennoch will ich C nur einmal verarbeiten müssen.
Edit:
Eine gemeinsame Basisklasse mit C reicht auch nicht für das C-Attribut. Das Problem würde dann aber wieder auftauchen bei einem Element G.
A : B, C
D : F, C
G : B, F
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Fr 01.06.12 12:15
Ich habe deinen Einwurf noch nicht ganz durchschaut.
Die Serialize Methode von Klasse A sähe nach meinem Vorschlag zum Beispiel so aus.
C#-Quelltext 1: 2: 3: 4: 5: 6:
| string ISerialize.Serialize() { MeineKlasseMitDenSerializeMethoden.SerializeA(this); MeineKlasseMitDenSerializeMethoden.SerializeB(this); MeineKlasseMitDenSerializeMethoden.SerializeC(this); } |
|
|
danielf 
      
Beiträge: 1012
Erhaltene Danke: 24
Windows XP
C#, Visual Studio
|
Verfasst: Sa 02.06.12 12:44
Ich habe nochmal drüber nach gedacht und du hast natürlich recht. So muss ich die Serialisierung natürlich nicht mehrfach schreiben, aber ich muss dennoch die Methoden aufrufen.
Ich suche einen Ansatz bei dem ich dem Objekt nur die gewissen Schnittstellen implementieren muss und er dann abhängig von den Schnittstellen die Serialize-Methoden aufruft.
Bei dem Beispiel würde ich ja einmal IA : IB, IC definieren und nochmals eine Serialize Methode mit IA die dann Serialize IA, IB, IC aufruft.
Das ganze sollte ohne Reflection oder is/Cast gehen (wegen Performance).
Hast du da vielleicht noch einen Ansatz?
Ich hatte ja gehofft, dass ich es irgendwie so machen kann, dass die verschiedenen Interface-Serializer zwei Methoden haben und wenn das Objekt das Interface implementiert er die "richtige" Methode ausführt und wenn nicht er eine leer Methode ausführt die nichts macht (oder einen Default raus schreibt). Deshalb dachte ich auch an ein Visitor-Pattern, weil da ja da ja ohne Casts, switch oder oder man für jedes Interface/Klasse die richtige Methode ausgwählt wird.
Gruß
Daniel
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Sa 02.06.12 17:57
Zitat: | Hast du da vielleicht noch einen Ansatz? |
Nicht wirklich. Bezweifle auch das das was du möchtest erreichbar ist. Wenn du Reflection, is, as, casts und Konsorten wegen der Performance ausschließt hast du im Prinzip jede Möglichkeit ausgeschlossen generischen Code der zur Laufzeit ausgewertet wird zu erstellen. Um schnellen Code zu schreiben bleibt dann nur die Möglichkeit das durch Wissen zur Designzeit zu ersetzen und entsprechend konkreten Code je Klasse zu erzeugen. Nicht zum reinen Vergnügen versucht ja zum Beispiel der XMLSerializer ja dynamisch Assemblies mit dem Serializercode zu erzeugen. Wenn dir das ~zu blöd~, ~zu aufwendig~, ~zu langweilig~ ist je Klasse ein Serialize Interface manuell zu erstellen und entsprechenden Code dafür zu schreiben würde ich eher in die Richtung denken mir für das Serialisieren einen Codegenerator, Custom Tool, Aspekt etc zu schreiben der mir die Arbeit abnimmt.
|
|
danielf 
      
Beiträge: 1012
Erhaltene Danke: 24
Windows XP
C#, Visual Studio
|
Verfasst: Mo 04.06.12 08:21
Okay - scheint wohl so  Hab gehofft es gibt vielleicht ein Pattern das ich da anwenden kann.
Dann werde ich die Serialisierungsmethoden vom Objekt aufrufen.
Danke und Gruß
Daniel
|
|