String.Format by Object Properties
Jeder C#-Entwickler wird sicherlich bereits die eine oder andere Überladung der
String.Format
-Methode verwendet haben – ansonsten wird es auf jeden Fall höchste Zeit, sich damit zu beschäftigen. Beispiel:
String.Format verwenden
Noch etwas bequemer – insbesondere auch im Zusammenhang mit anonymen Typen – wäre es jedoch, die Eigenschaften eines Objekts als Ersetzungsdaten verwenden zu können. Wir werden uns dazu eine (nicht ernsthaft optimierte) Erweiterungsmethode für den Typ 0102030405
string message = String.Format("{0} ist {1} Jahre alt und besitzt {2:C}.", "Bernd", 35, 1234.56); // "Bernd ist 35 Jahre alt und besitzt 1234,56 €."
String
schreiben, welche auf Reflexion setzt:
FormatByObject implementieren
Nun können wir statt numerischer Indizes komfortablere Zeichenketten verwenden:
01020304050607080910111213
public static string FormatByObject(this string str, object obj) { StringBuilder stringBuilder = new StringBuilder(str); { foreach(PropertyInfo propertyInfo in obj.GetType().GetProperties()) { stringBuilder.Replace( "{" + propertyInfo.Name + "}", propertyInfo.GetValue(obj).ToString() ); } }
return stringBuilder.ToString();}
FormatByObject verwenden
Dieses sehr einfache Vorgehen unterstützt jedoch bei Weitem nicht alle Möglichkeiten der ursprünglichen Implementierung, so ist beispielsweise kein 0102030405
message = "{Name} ist {Age} Jahre alt und besitzt {Balance} €.".FormatByObject(new { Name = "Bernd", Age = 35, Balance = 1234.56}); // "Bernd ist 35 Jahre alt und besitzt 1234,56 €."
{Balance:C}
zur Währungsformatierung möglich. Dies könnte dadurch behoben werden, indem wir unsere erweiterte Formatierung auf das Basisformat zurückführen – sprich, die Zeichenketten durch einen Index ersetzen. Ich werde dies in einem separaten Beitrag noch einmal aufgreifen. Aufrufer-Informationen für Methoden in C#
Manchmal kann es sinnvoll sein, sich Informationen über den Aufrufer einer Methode übermitteln zu lassen. Wir werden dies im Folgenden mit zwei praxisnahen Beispielen genauer untersuchen.
Zuerst möchten wir ein (einfaches) Logging-System implementieren:
Ich möchte noch einen weiteren praktischen Anwendungsfall mit
Zuerst möchten wir ein (einfaches) Logging-System implementieren:
Logging implementieren
Diese Klasse können wir nun beispielsweise wie folgt verwenden:
010203040506070809
public static class Logging { public static void Enter(string caller) { Trace.WriteLine(caller + " betreten"); }
public static void Leave(string caller) { Trace.WriteLine(caller + " verlassen"); }}
Logging verwenden
Nun stellt uns jedoch das .NET-Framework ein spezielles Attribut 010203040506070809
static void Main(string[] args) { Logging.Enter("Main");
/** * Aktionen ausführen **/
Logging.Leave("Main");}
CallerMemberName
zur Verfügung, um diesen Prozess ein wenig zu optimieren – dazu müssen wir unsere Klasse minimal ergänzen:
Logging-Implementierung erweitern
Der Parameter 010203040506070809
public static class Logging { public static void Enter([CallerMemberName] string caller = "") { Trace.WriteLine(caller + " betreten"); }
public static void Leave([CallerMemberName] string caller = "") { Trace.WriteLine(caller + " verlassen"); }}
caller
wird nun beim Aufruf automatisch festgelegt, so dass die explizite Angabe in Main
bei gleichem Ergebnis entfallen kann.Ich möchte noch einen weiteren praktischen Anwendungsfall mit
INotifyPropertyChanged
demonstrieren:
INotifyPropertyChanged mit impliziten Aufruferinformationen
Dies vereinfacht die Verwendung dieser Schnittstelle, die insbesondere zur Datenbindung im Rahmen der WPF Verwendung findet – vor allem bei Refaktorierungsmaßnahmen. Das Verhalten ist wie erwartet:
01020304050607080910111213141516171819202122232425262728293031323334353637
public class Person : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged;
private string name; public string Name { get { return this.name; } set { if(this.name != value) { this.name = value;
this.OnPropertyChanged(); } } }
private int age; public int Age { get { return this.age; } set { if(this.age != value) { this.age = value;
this.OnPropertyChanged(); } } }
private void OnPropertyChanged([CallerMemberName] string propertyName = "") { this?.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); }}
Objekt verwenden
Weitere Informationen (und hilfreiche Attribute) lassen sich im MSDN nachlesen. 0102030405060708091011121314151617
Person ich = new Person() { Name = "Holger", Age = 25};
ich.PropertyChanged += (sender, e) => { Debug.WriteLine("Der Wert der Eigenschaft '{0}' hat sich geändert!", (object) e.PropertyName );};
ich.Age = 26;
/** * Das Ereignis "PropertyChanged" wird ausgelöst * und "PropertyName" implizit auf "Age" gesetzt.**/
Observe changes on the file system with C#
Manchmal kann es sinnvoll sein, ein Verzeichnis auf Änderungen zu überwachen – beispielsweise, um festzustellen, ob eine Datei hinzugefügt oder entfernt wurde. Statt nun periodisch das Verzeichnis zu durchsuchen und selbst eine Sammlung der jeweiligen Zustände und eine anschließende Überprüfung auf Änderungen durch Vergleich dieser durchzuführen, bietet sich die Verwendung der
Für unser konkretes Beispiel möchten wir das Verzeichnis "
FileSystemWatcher
-Klasse an.Für unser konkretes Beispiel möchten wir das Verzeichnis "
X:\Server\Logs
" auf neue *.log
-Dateien überwachen und erzeugen dazu eine entsprechende Instanz der o. g. Klasse:
FileSystemWatcher instanziieren und konfigurieren
Abschließend abonnieren wir das Ereignis 01020304
FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(@"X:\Server\Logs") { EnableRaisingEvents = true, Filter = "*.log"};
Created
, welches bei neuen Dateien ausgelöst wird:
Ereignis abonnieren
Selbstverständlich bietet die Klasse die Möglichkeit einer detaillierteren Konfiguration und weitere Ereignisse. 010203040506
fileSystemWatcher.Created += (sender, e) => { /** * e.Name enthält nun den * Namen der neuen Datei. **/};
C# and the Clipboard
Da sich früher oder später wohl jeder Entwickler damit konfrontiert sieht, mit der Zwischenablage interagieren zu müssen, möchte ich hier prägnant zeigen, wie sich Text in der Zwischenablage speichern und wieder auslesen lässt:
Text in Zwischenablage speichern
Die weiteren Methoden (z. B. für Grafiken) sind grundsätzlich genauso einfach zu verwenden und weitestgehend selbsterklärend. Im MSDN finden sich wie üblich weitere Hinweise und Beispiele. 01
Clipboard.SetText("Test-Text");
Upload File with ASP.NET MVC
Vor einiger Zeit hatte ich bereits beschrieben, wie sich eine Datei per ASP.NET MVC ausliefern lässt. Ergänzend dazu möchte ich mit diesem Beitrag erklären, wie sich Dateien per ASP.NET MVC einfach hochladen lassen.
Zuerst erstellen wir eine minimale Ansicht (im Beispiel für eine Galerie) mit einem entsprechenden Formular:
Auch mehrere Dateien hochzuladen ist kein Problem, dazu müssen wir der Methode
Zuerst erstellen wir eine minimale Ansicht (im Beispiel für eine Galerie) mit einem entsprechenden Formular:
View: ~/Views/Gallery/Upload.cshtml
Zur Verarbeitung verwenden wir die folgende einfache Methode im Controller:
010203040506
@using(Html.BeginForm("Upload", "Gallery", FormMethod.Post, new { enctype = "multipart/form-data"})) { <input type="file" name="file" /> <input type="submit" />}
Controller: ~/Controllers/GalleryController.cs
Über 010203040506070809
public class GalleryController : Controller { public ActionResult Upload(HttpPostedFileBase file = null) { if(file != null) { file.SaveAs(file.FileName); }
return View(); }}
HttpPostedFileBase
stehen uns – wie im Beispiel ersichtlich – insbesondere die Eigenschaft FileName
mit dem ursprünglichen Dateinamen, sowie die praktische Methode SaveAs(…)
zur Verfügung.Auch mehrere Dateien hochzuladen ist kein Problem, dazu müssen wir der Methode
Upload
lediglich ein HttpPostedFileBase
-Array übergeben:
Nun können wir in der Ansicht mehrere Felder zur Auswahl einer Datei anbieten:
Project links
-
BitStadt – Stadtportal
Berlin · Hamburg · Amsterdam -
CCC – Fahrplan
Schedules for the CCCongress
Categories / Archive | Übersicht
- PHP functions in C# (136)
- Dictionary (257)
Tags
.NET · ADO.NET · Work · ASP.NET MVC · Blog · C# · Generics · Society · Computer Science · Java · LINQ · Logic · Mathematics · Network · PHP · Project · Security · Software development · Studies · Technics · Theory · Web design · WPF