¿Existe un equivalente a ToStringBuilder de Java para C#?¿Qué características tendría una buena versión de C#?

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

Pregunta

En el mundo Java tenemos Apache Commons' ParaStringBuilder para ayudar con la creación de implementaciones de toString().

¿Alguien conoce una implementación gratuita decente para C#?¿Hay mejores alternativas que no conozco?

Si no existe una implementación gratuita, supongo que esta pregunta se convierte más en una cuestión de "¿Qué haría un buen ToStringBuilder en C# 3?"

La parte superior de mi cabeza:

  • Podría ofrecer tanto reflexión como creación manual de cadenas ToString.

  • Sería realmente genial si pudiera utilizar árboles de expresión.

Algo como esto..

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

Que devolvería:

 "Foo{Id: 1, Name: AName}"
  • Podría usar System.Reflection.Emit para precompilar un delegado ToString.

¿Alguna otra idea?

ACTUALIZAR

Solo para aclarar, ToStringBuilder es una criatura diferente a StringBuilder.Estoy buscando algo similar a la funcionalidad de ToStringBuilder de Apache Common, tiene características como formato de varias líneas, diferentes estilos y creación de ToString base de reflexión.Gracias.

ACTUALIZACIÓN 2

He construido el mío propio.Ver aquí.

¿Fue útil?

Solución

Editar : OK, desea utilizar la reflexión para que no tenga que escribir los nombres de propiedades. Creo que esto le conseguirá lo que busca:

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

Ejemplo:

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

He aquí, el comportamiento que está buscando:

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

Salida:

  

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

Otros consejos

La pregunta inicial se refería a C # 3.5, pero desde entonces he aumentado a C # 4.

Yo pensé en compartir mi nueva versión aquí en caso de que sea de beneficio para los demás. Tiene todas las características mencionadas en este hilo y compila en tiempo de ejecución a un método stringify rápido.

Consíguelo aquí: ToStringBuilder

Puede que no sea exactamente lo que está después, ya que no es libre, pero ReSharper lo hará. Es un fantástico plugin para Visual Studio que hace mucho más que generar ToString. Pero va a hacer eso a. coloque el cursor dentro de su clase, presiona alt + Insertar y seleccione formatear miembros.

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

Tenga en cuenta que tendrá que proporcionar una pequeña plantilla de sí mismo.

por ejemplo:

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

return sb;
}

proporcionado una manera un poco generic aquí. Usted será capaz de crear su propia solución ordenada con el espacio de nombres System.Reflection en .NET

Saludos

ObjectPrinter va a hacer esto para usted con una serie de características personalizables. documentación está siendo un poco duro, pero hemos estado utilizando en la producción durante años con grandes resultados.

Creo que estás en algo con el uso de expresiones. Leí este artículo simplemente la otra noche: Obtener información sobre objetos, tipos y Miembros con árboles de expresión

apuesto a que usted podría combinar estas técnicas con el código que Dan publicado en este hilo para conseguir lo que está después.

No conozco ningún proyecto existente que haga lo que usted quiere, pero no sería tan difícil implementar el ejemplo que dio usando lambdas.

Aquí hay otra idea [no probada/no compilada/posiblemente defectuosa] que utiliza delegados anónimos:

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

Este ToString() La sobrecarga se escribiría como un método de extensión, por lo que se obtiene una referencia al objeto fuente y se aceptaría un Action<T> donde [T] es el tipo de objeto fuente.El método ToString() luego crearía un generador de cadenas u objeto interno de algún tipo, ejecutaría el método anónimo pasado por la persona que llama y luego envolvería el resultado en cualquier texto de apertura/cierre que sea necesario.

Para ser claro, en realidad no he intentó este.Simplemente creo que es un poco más flexible que el ejemplo basado en lambda de la pregunta original.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top