System.Attributeクラスを使用します
-
21-08-2019 - |
質問
私はSystem.Attributeクラスを使用すると良いアイデアであることを(一見)見えた状況で自分自身を得ました。
私は自分のアプリケーションで印刷するオブジェクトを持っている、と私は、各プロパティの前にラベル(またはそれ以前に単なる文字列)が必要です。私は次のようにハードコード各プロパティを置くことができます:
Console.WriteLine("Color:"+obj.color);
Console.WriteLine("Size:"+obj.size);
というように各プロパティの。しかし、その代わりにそれを、私はこの「ラベル」がハードコーディングする必要がないコードを作成しようとしていたので、私は動的にすべてのプロパティを印刷することができます。
私はSystem.Attributeクラスを使用して、そのような何かを得ます:
public class MyObject
{
[MyCustomLabel("Color:")]
public string Color;
[MyCustomLabel("Size:")]
public string Size;
//etc...
}
だからここに私の問題が来る:この属性の値を取得することは不可能ではないですが、私はそれのためにいくつかのリフレクションを使用していたので、それは友好的ではありません。
私は、リフレクションを使用して本当に怖がってないんだけど、私がそれがために作成されていなかった何かのための属性を使用していたようだった。
の属性を使用するための最良の場所がどこにあるのだろうか、これは実際にそれを使用するための状況である場合。
解決
属性と反射が手をつないで行きます。いくつかのコンパイラ/ランタイム属性を除いて、コードの上に反映して、それらを使用する方法はありません。
言った、あなたのアプローチは合理的である、とあなたが有益なメタデータとプロパティを飾るためにクラスの数を持っているSystem.ComponentModel
名前空間の属性を見てみたいことがあります。
他のヒント
あなたは正しい軌道に乗っている。
また、[表示名]属性既にテーラーメードこの目的のために、2.0から.NETになっているがあります。
http://msdn.microsoft.com/en -us /ライブラリ/ system.componentmodel.displaynameattribute.aspxする
あなただけのコンソールに書き込みをしている場合には、すなわち、それはあなたがタイプミス/コピーペースト・エラーの最小チャンスです何をしたい、その後のデバッグスタイルの出力です。
これは、ボンネットの下に紛らわしいですが、呼び出しサイトで非常に有効である。
public static void WriteNameAndValue<T,TValue>(
this TextWriter tw, T t,
Expression<Func<T, TValue>> getter)
{
var memberExpression = getter.Body as MemberExpression;
if (memberExpression == null)
throw new ArgumentException("missing body!");
var member = memberExpression.Member;
tw.Write(member.Name);
tw.Write(": ");
if (member is FieldInfo)
{
tw.Write(((FieldInfo)member).GetValue(t));
}
else if (member is PropertyInfo)
{
tw.Write(((PropertyInfo)member).GetValue(t, null));
}
}
public static void WriteNameAndValueLine<T,TValue>(
this TextWriter tw, T t,
Expression<Func<T, TValue>> getter)
{
WriteNameAndValue<T,TValue>(tw, t, getter);
tw.WriteLine();
}
あなたが書くことができます。
t.Foo = "bar";
t.Bar = 32.5;
Console.Out.WriteNameAndValueLine(t, x => x.Foo);
Console.Out.WriteNameAndValueLine(t, x => x.Bar);
// output
// Foo: bar
// Bar: 32.5
あなたがこのリソースを経由して、あなたがそうすることができますが、これはおそらく要求した場合、私は代わりに別の、より標準化されたアプローチを検討する局在化のための配慮で、実行時に複数の構成にする場合。
P.S。あなたは空想を取得したい場合は、
とのFieldInfo / PropertyInfoスイッチを置き換えることができますtw.Write(getter.Compile()(t));
とあなたが同様の式でMETHODINFOをチェックする(または任意のラムダを許可し、ちょうど行番号またはいくつかの他の一般的なテキストを挿入することができます。私はこのルートを下って行くではないことをお勧め、その後、使用方法も、これは不要な可能性があり、すでに混乱していますシンプルな伐採方法がどうあるべきかでロードします。
これは、シリアル化は、私はあなたのアプローチが合理的だと思いますので、動作します正確にどのようにあります。あなたがこれを近づくことができるもう一つの方法は、PropertyNamesとそのタイトルの辞書を作成し、プロパティ名に基づいてタイトルを検索することです。
私は自分のアプリケーションで印刷するオブジェクトを持っている、と私は、各プロパティの前にラベル(またはそれ以前に単なる文字列)が必要です。
なぜあなたはあなたのケースで属性を使用するのではと思いますか?あなたは、あなたのアプリケーションでこのオブジェクトをどこに印刷します。
たぶん、ちょうどあなたのオブジェクト(複数可)
中の ToStringメソッドの実装
例えばます。
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("PropertyX: ");
sb.AppendLine(this.PropertyX);
// get string from resource file
sb.Append(Resources.FileName);
sb.Append(": ");
sb.AppendLine(this.FileName);
sb.Append("Number: ");
sb.AppendLine(this.Number.ToString());
return sb.ToString();
}