Existe um equivalente para ToStringBuilder de Java para C #? O que seria uma boa característica versão C #?

StackOverflow https://stackoverflow.com/questions/2417647

Pergunta

No mundo Java temos Apache Commons' ToStringBuilder para ajuda com a criação de toString () implementações.

Alguém sabe de uma implementação livre decente para C #? Existem alternativas melhores eu não sei sobre?

Se nenhuma implementação livre existe do que eu acho que essa questão torna-se mais de uma questão de "O que faria um bom ToStringBuilder em C # 3?"

Em cima da minha cabeça:

  • Ele poderia oferecer tanto a reflexão e criação de corda ToString manual.

  • Seria muito legal se ele poderia fazer uso de árvores de expressão.

Algo como isso ..

 public override string ToString()
   {
      return new ToStringBuilder<Foo>(this)
         .Append(t => t.Id)
         .Append(t => t.Name)
         .ToString();
   }

que retornaria:

 "Foo{Id: 1, Name: AName}"
  • Ele poderia usar System.Reflection.Emit pré-compilar um delegado ToString.

Quaisquer outras ideias?

Atualizar

Só para esclarecer ToStringBuilder é uma criatura diferente para StringBuilder .. Eu estou procurando algo semelhante à funcionalidade do ToStringBuilder do Apache comum, ele tem recursos como multi-linha de formatação diferentes estilos e criação ToString base de reflexão. Obrigado.

UPDATE 2

Eu construí a minha própria. Veja aqui .

Foi útil?

Solução

Editar : OK, você quer usar a reflexão para que você não tem que digitar os nomes de propriedade. Acho que isso vai te dar o que você está depois:

// 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() + "}";
    }
}

Exemplo:

// 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();
}

Eis que o comportamento que você está depois:

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());
}

Output:

Coisa {Id: 10, nome: "Bob"}

Outras dicas

A pergunta original em causa C # 3.5, mas desde então tenho atualizado para C # 4.

Eu pensei que eu iria partilhar a minha nova versão aqui no caso, é para benefício de outros. Ele tem todas as características mencionadas neste segmento e compila em tempo de execução a um método stringify rápido.

Obter aqui: ToStringBuilder

Pode não ser exatamente o que você está depois, uma vez que não é livre, mas ReSharper vai fazer isso. É um plugin fantástico para estúdio visual que faz muito mais do que gerar ToString. Mas ele vai fazer isso. colocar o cursor dentro de sua classe, bateu alt + Inserir e escolha a formatação membros.

Use .NET é StringBuilder .

Note que você terá que fornecer um pouco template si mesmo.

por exemplo:

public StringBuilder ToStringBuilder<T>(T type) where T : IYourInterface
{
StringBuilder sb = new StringBuilder();
sb.append(type.key);
// more appends

return sb;
}

Desde uma maneira meio generic aqui. Você vai ser capaz de criar sua própria solução elegante com o namespace System.Reflection em .NET

Felicidades

ObjectPrinter vai fazer isso por você com uma série de recursos de personalização. documentação ainda é um pouco difícil, mas temos vindo a usá-lo em produção por anos com grandes resultados.

Eu acho que você é sobre a algo com o uso de expressões. Eu li este artigo apenas a outra noite: Obtendo informações sobre objetos, tipos e membros com árvores de expressão

Eu aposto que você poderia combinar essas técnicas com o código que Dan postou neste tópico para obter o que você está depois.

Eu não sei de quaisquer projectos existentes que iria fazer o que quiser, mas não seria tão difícil de implementar o exemplo que você deu usando lambdas.

Aqui está outro [uncompiled / possivelmente defeituoso não testado /] idéia usando delegados anônimos:

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

Essa sobrecarga ToString() seria escrito como um método de extensão, de modo a obter uma referência para o objeto de origem, e aceitaria uma Action<T> onde [T] é o tipo de objeto de origem. O método ToString (), então, nova-se um construtor de string ou objeto interno de algum tipo, executar o método anônimo passado do autor da chamada, e em seguida, enrole o resultado em qualquer abertura / fechamento de texto que é necessário.

Para ser claro, eu não tenho realmente tentou isso. Eu só acho que é um pouco mais flexível do que o exemplo à base de lambda na pergunta original.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top