Есть ли эквивалент Java ToStringBuilder для C #? Что было бы хорошим вариантом C # версии? - PullRequest
15 голосов
/ 10 марта 2010

В мире Java у нас есть Apache Commons ' ToStringBuilder , чтобы помочь с созданием реализаций toString ().

Кто-нибудь знает о приличной бесплатной реализации для C #? Есть ли лучшие альтернативы, о которых я не знаю?

Если не существует бесплатной реализации, чем, я думаю, этот вопрос становится скорее вопросом «Что бы сделать хороший ToStringBuilder в C # 3?»

С макушки моей головы:

  • Может предлагать как отражение, так и ручное создание строки 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.

Есть еще идеи?

UPDATE

Просто для пояснения, что ToStringBuilder отличается от StringBuilder. Я ищу что-то похожее на функциональность ToStringBuilder Apache Common, у него есть такие функции, как многострочное форматирование, различные стили и создание ToString базы отражения. Спасибо.

ОБНОВЛЕНИЕ 2

Я построил свой собственный. См. здесь .

Ответы [ 8 ]

13 голосов
/ 10 марта 2010

РЕДАКТИРОВАТЬ : ОК, вы хотите использовать отражение, поэтому вам не нужно вводить имена свойств. Я думаю, что это даст вам то, что вы ищете:

// 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, Имя: "Боб"}

4 голосов
/ 10 февраля 2011

Первоначальный вопрос касался C # 3.5, но с тех пор я обновился до C # 4.

Я думал, что поделюсь своей новой версией здесь на случай, если она принесет пользу другим. Он обладает всеми функциями, упомянутыми в этом потоке, и компилируется во время выполнения в быстрый метод Stringify.

Получите это здесь: ToStringBuilder

3 голосов
/ 10 марта 2010

Это может быть не совсем то, что вам нужно, поскольку это не бесплатно, но Resharper сделает это. Это фантастический плагин для визуальной студии, который делает гораздо больше, чем просто генерирует ToString. Но это сделает это с. поместите курсор в свой класс, нажмите alt + insert и выберите форматирование членов.

1 голос
/ 27 декабря 2013

ObjectPrinter сделает это за вас с помощью ряда настраиваемых функций. документация все еще немного грубовата, но мы использовали ее в производстве в течение многих лет с отличными результатами.

1 голос
/ 10 марта 2010

Посмотреть этот проект ...

http://commonsdotnet.codeplex.com/

1 голос
/ 10 марта 2010

Использование .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

Приветствия

0 голосов
/ 10 марта 2010

Я не знаю ни одного существующего проекта, который бы делал то, что вы хотите, но было бы не так сложно реализовать пример, который вы привели, используя лямбды.

Вот еще одна [непроверенная / не скомпилированная / возможно ошибочная] идея с использованием анонимных делегатов:

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

Эта перегрузка ToString() будет записана как метод расширения, поэтому вы получите ссылку на исходный объект и примете Action<T>, где [T] - тип исходного объекта. Затем метод ToString () запустит построитель строк или некоторый внутренний объект, выполнит анонимный метод, переданный от вызывающей стороны, и затем обернет результат в любой открывающий / закрывающий текст, который необходим.

Чтобы было ясно, я на самом деле не пытался это. Я просто думаю, что он немного более гибкий, чем лямбда-пример в оригинальном вопросе.

0 голосов
/ 10 марта 2010

Я думаю, что вы что-то используете с помощью выражений. Я читал эту статью как-то вечером: Получение информации об объектах, типах и элементах с деревьями выражений

Могу поспорить, что вы могли бы объединить эти приемы с кодом, который Дан разместил в этой теме, чтобы получить то, что вам нужно.

...