17

Java の世界では、 toString() 実装の作成を支援するApache Commons のToStringBuilderがあります。

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

私は自分自身を構築しました。ここを参照してください。

4

8 に答える 8

13

EDIT: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、名前: "ボブ"}

于 2010-03-10T14:44:00.090 に答える
4

元の質問はC#3.5に関するものでしたが、それ以来、C#4にアップグレードしました。

他の人の利益になる場合に備えて、ここで新しいバージョンを共有したいと思いました。このスレッドで説明されているすべての機能を備えており、実行時に高速のStringifyメソッドにコンパイルされます。

ここで入手:ToStringBuilder

于 2011-02-10T15:52:27.030 に答える
3

無料ではないため、あなたが求めているものとは正確には異なるかもしれませんが、Resharperはこれを行います. これは、ToString を生成するだけでなく、ビジュアル スタジオの素晴らしいプラグインです。しかし、それはそうします。カーソルをクラス内に置き、alt+insert を押して、書式設定メンバーを選択します。

于 2010-03-10T18:58:43.913 に答える
1

このプロジェクトを見る...

http://commonsdotnet.codeplex.com/

于 2010-03-10T15:05:59.767 に答える
1

.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.NET の名前空間を使用して、独自のきちんとしたソリューションを作成できます。

乾杯

于 2010-03-10T14:34:52.917 に答える
0

式を使用して何かに取り組んでいると思います。先日、この記事を読みました:式ツリーを使用してオブジェクト、型、およびメンバーに関する情報を取得する

これらの手法と Dan がこのスレッドに投稿したコードを組み合わせて、目的を達成できると思います。

于 2010-03-10T15:41:45.450 に答える
0

あなたが望むことを行う既存のプロジェクトは知りませんが、ラムダを使用してあなたが示した例を実装することはそれほど難しくありません。

匿名デリゲートを使用する別の[テストされていない/コンパイルされていない/おそらく欠陥のある]アイデアは次のとおりです。

public override string ToString() {
    return this.ToString(x => {
        x.Append(t => t.Id);
        x.Append(t => t.Name);
    });
}

このオーバーロードは拡張メソッドとして記述されるため、ソース オブジェクトへの参照を取得し、 [T] がソース オブジェクトの型であるToString()を受け入れます。Action<T>ToString() メソッドは、文字列ビルダーまたは何らかの内部オブジェクトを新しく作成し、呼び出し元から渡された匿名メソッドを実行してから、必要な開始/終了テキストで結果をラップします。

明確にするために、私は実際にこれを試していません。元の質問のラムダベースの例よりも少し柔軟だと思います。

于 2010-03-10T15:47:51.897 に答える