Esiste un equivalente ToStringBuilder di Java per C #? Cosa sarebbe una buona caratteristica versione C #?

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

Domanda

Nel mondo Java abbiamo Apache Commons' ToStringBuilder per aiutare con la creazione di toString () implementazioni.

Qualcuno sa di un'implementazione libera decente per C #? ci sono alternative migliori che non conosco circa?

Se non esiste implementazione libera di quanto mi immagino questa domanda diventa più di una questione di "Che cosa farebbe un buon ToStringBuilder in C # 3?"

Al largo della parte superiore della mia testa:

  • Si potrebbe offrire sia la riflessione e la creazione stringa ToString manuale.

  • Sarebbe davvero bello se si potesse fare uso di alberi di espressione.

Una cosa del genere ..

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

Il che sarebbe tornato:

 "Foo{Id: 1, Name: AName}"
  • Si potrebbe usare System.Reflection.Emit di precompilare un delegato ToString.

Altre idee?

Aggiorna

Giusto per chiarire ToStringBuilder è una creatura diversa da StringBuilder .. Sto cercando qualcosa di simile alla funzionalità di ToStringBuilder di Apache Comune, ha caratteristiche come la formattazione a più linee, stili diversi e la creazione ToString base di riflessione. Grazie.

UPDATE 2

Ho costruito la mia. Vedere qui .

È stato utile?

Soluzione

Modifica : OK, si desidera utilizzare la riflessione in modo da non dover digitare nomi di proprietà. Credo che questo ti porterà quello che stai cercando:

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

Esempio:

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

Ecco, il comportamento che stai dopo:

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:

  

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

Altri suggerimenti

La domanda iniziale riguardava C # 3.5, ma da allora ho aggiornato a C # 4.

ho pensato di condividere la mia nuova versione qui nel caso che sia di beneficio per gli altri. Ha tutte le caratteristiche menzionate in questa discussione e compila in fase di esecuzione di un metodo veloce in stringa.

Scarica qui: ToStringBuilder

Potrebbe non essere esattamente quello che stai dopo, dato che non è libero, ma ReSharper lo farà. Si tratta di un fantastico plugin per Visual Studio che fa molto di più che generare ToString. Ma lo farà a. posizionare il cursore all'interno della vostra classe, ha colpito alt + inserto e scegli formattazione membri.

Utilizza .NET href="http://msdn.microsoft.com/en-us/library/2839d5h5(VS.71).aspx" rel="nofollow noreferrer"> StringBuilder .

Si noti che dovrete fornire un po 'di template da soli.

per esempio:

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

return sb;
}

fornito un modo un po generic qui. Sarete in grado di creare la vostra soluzione ordinata, con lo spazio dei nomi System.Reflection in .NET

Saluti

Vedere questo progetto ...

http://commonsdotnet.codeplex.com/

ObjectPrinter farà questo per voi con una serie di funzionalità personalizzabili. la documentazione è ancora un po 'grezzo, ma abbiamo usato in produzione per anni con grandi risultati.

Credo che tu sia a qualcosa con l'utilizzo di espressioni. Ho letto questo articolo solo l'altra sera: Come ottenere informazioni sugli oggetti, tipi, e ai soci con Expression Trees

Scommetto che si potrebbe combinare quelle tecniche con il codice che Dan ha postato su questo thread per ottenere ciò che si sta dopo.

Non so di eventuali progetti già esistenti che farebbero ciò che si vuole, ma non sarebbe così difficile per implementare l'esempio che hai dato utilizzando lambda.

Ecco un altro [/ non compilato / forse difettoso non testati] idea utilizzando i delegati anonimi:

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

Questo sovraccarico ToString() sarebbe scritto come un metodo di estensione, in modo da ottenere un riferimento all'oggetto di origine, e avrebbe accettato un Action<T> dove [T] è il tipo di oggetto di origine. Il metodo ToString () sarebbe poi nuovo un costruttore di stringa o oggetto interno di qualche tipo, eseguire il metodo anonimo passata dal chiamante, e poi avvolgere il risultato in qualsiasi apertura / chiusura del testo che è necessaria.

Per essere chiari, non ho davvero cercato questo. Penso solo che è un po 'più flessibile rispetto all'esempio lambda basata sulla domanda originale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top