Dynamic UI: Import and export data
Fejtegessük tovább a témát, az önmagát generáló felhasználói felületet. Most az adatok exportálására fogunk fókuszálni. Ugyanazt az adatot több féle formátumban, több féle szabvány szerint is menthetjük és ahhoz, hogy ezt megvalósítsuk, különböző exportáló osztályokat kell megírnunk.
A felhasználói felületen ezek az osztályok egy mentés ablakon keresztül kapnak szerepet. Ott kell kilistáznunk az elérhető formátumokat és a felhasználó döntése szerint létrehozni a megfelelő osztályból egy példányt az adatok mentésére. Célunk ennek a teljes folyamatnak az automatizálása.
Kezdjük is az exportáló osztályokkal:
public abstract class ReportExporter : IDisposable { } public class CsvReportExporter : ReportExporter { } public class XmlReportExporter : ReportExporter { }
A legjobb megoldás a metaadatok tárolására az attribútumok használata. A miénk legyen a ReportExporterDescriptionAttribute. Két tulajdonságot kell tartalmaznia: FormatDisplayName és FileExtension. Alkalmazzuk ezt az attribútumot a meglévő osztályokra:
[ReportExporterDescription(FormatDisplayName = "Comma Separated Values", FileExtension = ".csv")] public class CsvReportExporter : ReportExporter { }
Mostantól megvannak a megfelelő osztályaink ellátva a szükséges metaadatokkal. A következő lépés, hogy életre keltsük a felhasználói felületet. A .NET Framework Reflection képességét fogjuk használni, hogy kinyerjük az adott assemblynkből az összes olyan osztályt, amely a ReportExporter osztályból származik.
public void ExportReport() { // Get exporters using reflection Type[] exporters = typeof(ReportExporter).Assembly.GetTypes().Where( t => t.IsSubclassOf(typeof(ReportExporter)) ).ToArray(); // Show save file dialog with the available filters using (SaveFileDialog sfd = new SaveFileDialog() { Filter = String.Join( "|", exporters.Select(t => { ReportExporterDescriptionAttribute attr = (ReportExporterDescriptionAttribute)t.GetCustomAttributes( typeof(ReportExporterDescriptionAttribute), false ).First(); return String.Format("{0} (*{1})|*{1}", attr.FormatDisplayName, attr.FileExtension); }).ToArray() ) }) { if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { // Create a ReportExporter instance and render the contents using (ReportExporter exporter = Activator.CreateInstance( exporters[sfd.FilterIndex - 1], sfd.FileName ) as ReportExporter) exporter.Render(this.Report); } } }
Így ha később változtatunk a kódon és kiegészítjük egy új formátum kezelésére képes osztállyal, amit ellátunk a megfelelő attribútumokkal, akkor sehol máshol nem kell módosítanunk, mert az imént megírt metódus tökéletesen idomulni fog a változásokhoz.