C# 用の Java の ToStringBuilder に相当するものはありますか?優れた C# バージョンの機能は何でしょうか?
-
19-09-2019 - |
質問
Java の世界には Apache Commons があります。 ToStringBuilder toString() 実装の作成に役立ちます。
C# の適切な無料実装を知っている人はいますか?私が知らないより良い代替手段はありますか?
無料の実装が存在しない場合、この質問はさらに次のような質問になると思います。 「C# 3 で優れた ToStringBuilder を実現するにはどうすればよいでしょうか?」
私の頭の上から:
リフレクションと手動による ToString 文字列作成の両方を提供できます。
式ツリーを利用できれば本当に素晴らしいでしょう。
このようなもの..
public override string ToString()
{
return new ToStringBuilder<Foo>(this)
.Append(t => t.Id)
.Append(t => t.Name)
.ToString();
}
これは次のように返されます:
"Foo{Id: 1, Name: AName}"
- System.Reflection.Emit を使用して ToString デリゲートをプリコンパイルできます。
他に何かアイデアはありますか?
アップデート
ToStringBuilder は StringBuilder とは別の生き物であることを明確にしておきます。Apache Common の ToStringBuilder の機能に似たものを探しています。これには、複数行の書式設定、さまざまなスタイル、リフレクション ベースの ToString 作成などの機能があります。ありがとう。
更新 2
自分で構築しました。見る ここ.
解決
編集:OK、あなたはプロパティ名を入力する必要はありませんので、反射を利用したいです。私は、これはあなたが後にしている何を得るだろうと思います:
// forgive the mangled code; I hate horizontal scrolling
public sealed class ToStringBuilder<T> {
private T _obj;
private Type _objType;
private StringBuilder _innerSb;
public ToStringBuilder(T obj) {
_obj = obj;
_objType = obj.GetType();
_innerSb = new StringBuilder();
}
public ToStringBuilder<T> Append<TProperty>
(Expression<Func<T, TProperty>> expression) {
string propertyName;
if (!TryGetPropertyName(expression, out propertyName))
throw new ArgumentException(
"Expression must be a simple property expression."
);
Func<T, TProperty> func = expression.Compile();
if (_innerSb.Length < 1)
_innerSb.Append(
propertyName + ": " + func(_obj).ToString()
);
else
_innerSb.Append(
", " + propertyName + ": " + func(_obj).ToString()
);
return this;
}
private static bool TryGetPropertyName<TProperty>
(Expression<Func<T, TProperty>> expression, out string propertyName) {
propertyName = default(string);
var propertyExpression = expression.Body as MemberExpression;
if (propertyExpression == null)
return false;
propertyName = propertyExpression.Member.Name;
return true;
}
public override string ToString() {
return _objType.Name + "{" + _innerSb.ToString() + "}";
}
}
例:
// from within some class with an Id and Name property
public override string ToString() {
return new ToStringBuilder<SomeClass>(this)
.Append(x => x.Id)
.Append(x => x.Name)
.ToString();
}
見よ、あなたは後にしている行動ます:
class Thing {
public int Id { get; set; }
public string Name { get; set; }
public override string ToString() {
return new ToStringBuilder<Thing>(this)
.Append(t => t.Id)
.Append(t => t.Name)
.ToString()
}
}
void Main() {
var t = new Thing { Id = 10, Name = "Bob" };
Console.WriteLine(t.ToString());
}
出力:
シング{ID:10、名称: "ボブ"}
他のヒント
元の質問は、C#3.5を懸念したが、それ以来、私はC#4にアップグレードしました。
私はそれが他の人に利益をもたらすだ場合には、ここで私の新しいバージョンを共有しようと思いました。これは、このスレッドで述べたすべての機能を持ち、高速な文字列化する方法に、実行時にコンパイルされます。
ここでそれを取得します: ToStringBuilderする
それはあなたが後にしている正確に何ではないかもしれませんが、 ReSharperのこれを行います。これは、ToStringメソッドを生成するよりも多くの処理を行い、ビジュアルスタジオに素晴らしいプラグインです。しかし、それはにそれを行います。あなたのクラス内にカーソルを置き、Alt + Insertを押すと、メンバーをフォーマットする選択します。
を使用する.NETののStringBuilder を。
あなたは少しのテンプレートを自分で提供する必要がありますので注意してください。
例えばます:
public StringBuilder ToStringBuilder<T>(T type) where T : IYourInterface
{
StringBuilder sb = new StringBuilder();
sb.append(type.key);
// more appends
return sb;
}
ここでちょっとgeneric
方法を提供すること。
あなたは、
System.Reflection
名前空間を使用して独自のきちんとしたソリューションを作成できるようになります
乾杯
このプロジェクトを参照してください...
ObjectPrinter には、カスタマイズ可能な機能の数とあなたのためにこれを行います。ドキュメントには、まだ少し荒いですが、我々は偉大な結果と年間の生産でそれを使用してきた。
私はあなたが式を使用してで何かに上だと思います。私は他の夜、この記事を読んで:<のhref = "http://blogs.msdn.com/csharpfaq/archive/2010/01/06/getting-information-about-objects-types-and-members-with-表現-trees.aspx」のrel = "nofollowをnoreferrer">式ツリーを持つオブジェクト、型、およびメンバーに関する情報を取得する
私はあなたがダンはあなたが後にしているものを取得するには、このスレッドに掲載のコードでこれらの技術を組み合わせることができることを賭けます。
私はあなたがやりたいだろう、既存のプロジェクトを知らないが、それは難しいあなたがラムダを使用した例を実装することではないでしょう。
ここでは、匿名デリゲートを使用して、別の[未テスト/未コンパイル/不良の可能性がある]アイデアです:
public override string ToString() {
return this.ToString(x => {
x.Append(t => t.Id);
x.Append(t => t.Name);
});
}
このToString()
過負荷は、ソースオブジェクトへの参照を取得するように、拡張メソッドとして書かれるであろうし、[T]は、ソースオブジェクトの種類であるAction<T>
を受け入れます。 ToStringメソッド()メソッドは文字列ビルダまたはある種の内部オブジェクトまで、新しい、必要なテキストを閉じる/呼び出し側から渡された匿名メソッドを実行した後、任意の開口部に結果をラップなります。
明確にするために、私は実際にをしていないのこれを試してみました。私は元の質問では、ラムダベースの例に比べて、もう少し柔軟だと思います。