ソリューションが含まれ、クライアントのすべての種類を持っていますこれはC#でAttributesのビルトインサポートを利用することでした。属性は、例えば、Serializationの間に、他のいくつかのクラスによって使用されるいくつかの追加のメタデータでプロパティ、フィールド、メソッド、クラスなどをタグ付けする方法です。あなたはそれを最も頻繁に見ます。
私は、オブジェクトのコレクションIEnumerable
を取得し、ユーザーが選択した選択肢に基づいてファイルにデータを出力できるようにするために必要なアプリケーションを作成しました。私は、リフレクションによって選択肢を読んで、指示どおりに行動する能力を与えた属性クラスを作成しました。私はあなたに例を示しましょう:
まず属性クラス:上迷子にしないよう
[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;
}
}
以下の様に定義された、このクラスでは、私はこのように私のデータクラスのプロパティを飾ることができ(実際の性質はそう変更しましたビジネス専門用語):私の輸出ルーチンでそれでは
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; }
}
、代わりにハードコーディング可変であるプロパティ名を、あるいは表示または非表示にするフィールドの情報が含まれているの周りに複雑なデータ構造を渡します注文とは何ですか、私は反射を使用してプロパティをループし、その値をCSVファイルに出力する次のコードを実行しただけです。
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");
}
OrderedProperties構造体のためのコードはここにある:
struct OrderedProperties
{
/// <summary>
///
/// </summary>
public int OrderByValue;
/// <summary>
///
/// </summary>
public string PropertyName;
/// <summary>
///
/// </summary>
public string Header;
/// <summary>
///
/// </summary>
public bool Export;
}
あなたが見ることができるように、プロパティの値を抽出するロジックは、クラスの構造を完全に無知です。それは、私が作成した属性で装飾されたプロパティを見つけ出し、それを使って処理を駆動するだけです。
私はこれがすべて意味があることを願っており、さらに助けや説明が必要な場合はお気軽にお問い合わせください。
Managed Extensibility Framework(MEF)を見ましたか? http://mef.codeplex.com/ http://msdn.microsoft.com/en-us/library/dd460648.aspx – spender
私はそれについて聞いたことがあり、その使い方の簡単なアイデアがあります。私はプログラミングに慣れていないので、他の言語やシステムに容易に移植できるソリューションを実装したいと考えています。また、私は実際にこれらの複雑なシステムを実装することを学びたいと思います。 –
C#で実装することで、Linuxや他のプラットフォーム上で動作する.NetフレームワークのポートであるMonoが存在するため、他のシステムに移植することができます。私はそれを他の言語にすばやく移植することは一般的だが、必ずしも心配する必要はない。それぞれの言語とプラットフォームには、独自のイディオムとベストプラクティスがあり、その中でうまくいくものは別の言語でうまく機能しないことがあります。 –