Hallo,
ich habe spezifische Erweiterungsmethoden für Objekte, um diese zu erzeugen. Gibt es eine Möglichkeit, eine Erweiterungsmethode ohne Objektinstanz aufzurufen?
Als Beispiel könnte hier die Xml-Deserialisierung dienen:
public static T DeserializeFromXml<T>(this T o, string path)
{
T result = default(T);
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (FileStream stream = new FileStream(path, FileMode.Open))
{
result = (T)serializer.Deserialize(stream);
}
return result;
}
Was ich jetzt erreichen möchte wäre etwa folgendes:
MyObjectType myObject = MyObjectType.Deserialize(path);
Mir ist klar, dass folgendes funktionieren würde:
MyObjectType myObject = null;
myObject = myObject.Deserialize(path);
Aber das finde ich persönlich jetzt nicht so hübsch.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
Naja. Aber für jede Klasse die gleiche Statische Methode anbieten ist wieder blöd. Genau deshalb fand ich ja Extension-Methods dafür am besten.
Hintergrund ist ja, dass es sich in meinen Fällen jeweils immer um Funktionalitäten handelt, die bei fast jedem Objekt durchgeführt werden können.
Gerade zum Beispiel die Xml-Serialisierung ist ja ein Fall, der sich nicht auf Object X beschränkt.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
Dann könnte eine Basisklasse deine Wahl sein. =)
public abstract class BaseClass<T> where T : BaseClass<T>, new()
{
public static T Create()
{
return new T();
}
}
public class ClassOne : BaseClass<ClassOne> { }
public class ClassTwo : BaseClass<ClassTwo> { }
var one = ClassOne.Create();
var two = ClassTwo.Create();
var oneFromBase = BaseClass<ClassOne>.Create();
var twoFromBase = BaseClass<ClassTwo>.Create();
EDIT: BaseClass<T> zum where hinzugefügt.
Eine Erweiterungsmethode, die statisch für den Typ und nicht dessen Instanz zählt, ist nicht möglich.
Entweder Du hast eine Klasse, die solche Methoden enthält oder Du bietest die entsprechende Methode statisch pro Klasse an.
Die vermutlich einfachste aber immer noch schöne Lösung ist mMn. die von p!lle, sie verlangt aber eine Basis-Klasse.
Eine etwas komplexere dafür aber sehr flexible Alternative, die ich mal für Parse/TryParse-Methoden geschrieben habe:
Ein ParsableAttribut, was die Namen der Parse/TryParse-Methode entgegen nimmt.
Daneben eine statische Parser-Klasse, die für den angegebenen Typ dieses Attribut abruft und anhand des Namens die Methode aufruft.
So habe ich bei der Nutzung nur eine Stelle, die ich kennen muss: Die Parser-Klasse
Ob ein Typ das Parsen unterstützt, kann über das ParsableAttribut fest gelegt werden.
Das Konzept ließe sich auch eine Deserialize-Methode übertragen.
So hättest Du dann z.B. eine Klasse Deserializer und die Methode Deserialize, welche den Ziel-Typ und die Quell-Datei entgegen nimmt.
Sie schaut dann, ob sie eine Deserialize-Methode (z.B. mit Hilfe eines entsprechenden Attributs) mit der korrekten Definition finden kann und ruft sie dann auf.
So klappt das auch generisch, ohne dass Du den Typ kennen musst und eine Erweiterung ist nur in der Ziel-Klasse nötig. Eine Basis-Klasse brauchts nicht, aber man ist an Attribute und damit Metadaten gebunden.
Das könnte man auch ohne viel Aufwand so erweitern, dass in dem Attribut optional noch die Klasse angegeben werden kann, wo die Methode gesucht werden soll.
Bei Bedarf kann ich meine Parse/TryParse-Lösung mal anhängen.
NuGet Packages im Code auslesen
lock Alternative für async/await
Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.
Oder eben so
public static T DeserializeFromXml<T>(this string path)
{
T result = default(T);
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (FileStream stream = new FileStream(path, FileMode.Open))
{
result = (T)serializer.Deserialize(stream);
}
return result;
}
string filename = "something.xml";
Foo foo = filename.DeserializeFromXml<Foo>();
😁
Ob das sinnvoll ist muss jeder selber entscheiden
Ich würde das eher als Erweiterungsmethode für FileInfo umsetzen als direkt von String 😕
Da der String alles sein kann(Dateipfad, Name, Langer Text etc.) wäre nicht wirklich klar, ob die Deserialisierung funktioniert.
Bei einer Extention auf FileInfo kann man alles in einem Rutsch abfragen und kann auch gleich prüfen ob die Datei vorhanden ist, man die Rechte zum lesen hat etc.
@Sir Rufo
Die Umsetzung sieht soweit super aus, würde ich direkt verwenden.
Nur halt eben nicht mit this string path sondern this FileInfo file.
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.