Eine Lösung, die in den Sinn kam, als ich gelesen Dies war, um die eingebaute Unterstützung für Attributes in C# zu verwenden. Ein Attribut ist eine Möglichkeit, eine Eigenschaft, ein Feld, eine Methode, eine Klasse usw. mit einigen zusätzlichen Metadaten zu versehen, die dann von einer anderen Klasse verwendet werden, zum Beispiel während Serialization. Du wirst es dort am häufigsten sehen.
Ich hatte eine Anwendung, die ich baute, die in der Lage sein musste, eine IEnumerable
Sammlung von Objekten zu nehmen und einige Daten in eine Datei basierend auf benutzerdefinierten Auswahlmöglichkeiten auszugeben. Ich habe eine Attributklasse erstellt, die mir die Möglichkeit gab, die Auswahl durch Reflexion zu lesen und wie angewiesen zu handeln.Lassen Sie mich Ihnen ein Beispiel zeigen:
Zuerst wird die Attributklasse:
[System.AttributeUsage(AttributeTargets.Property)]
class ExportOptionsAttribute : System.Attribute
{
public string Header { get; set; }
public string FormatString { get; set; }
public bool Export { get; set; }
public int Order { get; set; }
/// <summary>
///
/// </summary>
/// <param name="header"></param>
public ExportOptionsAttribute(string header) : this (header, null, true)
{
}
/// <summary>
///
/// </summary>
/// <param name="header"></param>
/// <param name="formatString"></param>
/// <param name="export"></param>
public ExportOptionsAttribute(string header, string formatString, bool export)
{
this.Header = header;
this.FormatString = formatString;
this.Export = export;
this.Order = 0;
}
}
Mit dieser Klasse wie so definiert, konnte ich meine Datenklasse Eigenschaften wie diese dekorieren (tatsächlichen Eigenschaften verändert, um nicht auf verloren zu das Business-Jargon):
public sealed class PartsOrder
{
/// <summary>
///
/// </summary>
[ExportOptions("Customer Name", Order=0)]
public string CustomerName { get; set; }
/// <summary>
///
/// </summary>
[ExportOptions("Catalog Name", Order = 1)]
public string Catalog Name { get; set; }
/// <summary>
///
/// </summary>
[ExportOptions("Unit", Order = 2)]
public string Unit { get; set; }
/// <summary>
///
/// </summary>
[ExportOptions("Component", Order = 3)]
public string Component { get; set; }
/// <summary>
///
/// </summary>
[ExportOptions("Delivery Point", Order = 4)]
public string DeliveryPoint { get; set; }
/// <summary>
///
/// </summary>
[ExportOptions("Order Date", Order = 5)]
public string OrderDate { get; set; }
}
Also dann in meine Export Routine, statt Fest-Codierung der Eigenschaftsnamen, die variabel sind, oder eine komplexe Datenstruktur vorbei, um die sich die Informationen enthalten, auf die Felder ein- oder ausblenden und was das Ordnen war, ich habe einfach den folgenden Code unter Verwendung der Reflektion ausgeführt, um die Eigenschaften zu loopen und ihre Werte in diesem Fall in eine CSV-Datei auszugeben.
StringBuilder outputDoc = new StringBuilder();
// loop through the headers in the attributes
// a struct which decomposes the information gleaned from the attributes
List<OrderedProperties> orderedProperties = new List<OrderedProperties>();
// get the properties for my object
PropertyInfo[] props =
(typeof(PartsOrder)).GetProperties();
// loop the properties
foreach (PropertyInfo prop in props)
{
// check for a custom attribute
if (prop.GetCustomAttributesData().Count() > 0)
{
foreach (object o in prop.GetCustomAttributes(false))
{
ExportOptionsAttribute exoa = o as ExportOptionsAttribute;
if (exoa != null)
{
orderedProperties.Add(new OrderedProperties() { OrderByValue = exoa.Order, PropertyName = prop.Name, Header = exoa.Header, Export = exoa.Export });
}
}
}
}
orderedProperties = orderedProperties.Where(op => op.Export == true).OrderBy(op => op.OrderByValue).ThenBy(op => op.PropertyName).ToList();
foreach (var a in orderedProperties)
{
outputDoc.AppendFormat("{0},", a.Header);
}
// remove the trailing commma and append a new line
outputDoc.Remove(outputDoc.Length - 1, 1);
outputDoc.AppendFormat("\n");
var PartsOrderType = typeof(PartsOrder);
//TODO: loop rows
foreach (PartsOrder price in this.Orders)
{
foreach (OrderedProperties op in orderedProperties)
{
// invokes the property on the object without knowing the name of the property
outputDoc.AppendFormat("{0},", PartsOrderType.InvokeMember(op.PropertyName, BindingFlags.GetProperty, null, price, null));
}
// remove the trailing comma and append a new line
outputDoc.Remove(outputDoc.Length - 1, 1);
outputDoc.AppendFormat("\n");
}
Der Code für die OrderedProperties struct hier:
struct OrderedProperties
{
/// <summary>
///
/// </summary>
public int OrderByValue;
/// <summary>
///
/// </summary>
public string PropertyName;
/// <summary>
///
/// </summary>
public string Header;
/// <summary>
///
/// </summary>
public bool Export;
}
Wie Sie die Logik sehen können, die Eigenschaftswerte zu extrahieren, völlig unwissend über die Struktur der Klasse ist. Es werden nur die Eigenschaften gesucht, die mit dem von mir erstellten Attribut versehen sind, und damit die Verarbeitung gesteuert.
Ich hoffe, das alles macht Sinn, und wenn Sie weitere Hilfe oder Klärung benötigen, zögern Sie nicht zu fragen.
Haben Sie sich das Managed Extensibility Framework (MEF) angesehen? http://mef.codeplex.com/ http://msdn.microsoft.com/en-us/library/dd460648.aspx – spender
Ich habe davon gehört, und ich habe eine kurze Vorstellung davon ist die Verwendung. Die Sache ist, dass ich neu in der Programmierung bin und eine Lösung implementieren möchte, die leicht auf andere Sprachen und Systeme übertragbar ist. Außerdem möchte ich wirklich lernen, diese komplexen Systeme zu implementieren. –
Durch die Implementierung in C# kann es auf andere Systeme portiert werden, da Mono vorhanden ist. Dies ist ein Port des .NET-Frameworks, das auf Linux und anderen Plattformen ausgeführt wird. Ich würde mich nicht unbedingt darum sorgen, es so generisch zu machen, dass es schnell in andere Sprachen portiert würde. Jede Sprache und Plattform hat ihre eigenen Idiome und Best Practices, und etwas, das in einem gut funktioniert, kann in einem anderen nicht gut funktionieren. –