8

我有一些只用于包含数据的类。例如

public class EntityAdresse : IEntityADRESSE
{
    public string Name1 { get; set; }
    public string Strasse { get; set; }
    public string Plz { get; set; }
    public string Ort { get; set; }
    public string NatelD { get; set; }
    public string Mail { get; set; }
    public int Id_anrede { get; set; }
    public string Telefon { get; set; }
    public int Id_adr { get; set; }
    public int Cis_adr { get; set; }
}

这代表一个地址。就像我说的,它只包含数据。没有方法(我知道界面在这里没有意义......)

现在我需要为所有这些实体类实现 ToString 并且它们有很多。

我的问题是:C# 中是否有一个元编程功能可以自动生成这个 tostring 方法?我不想为这些类中的每一个编写样板代码。

或者,我也可以编写一个 perl 或 python 脚本来生成代码。但我更喜欢直接在 C# 中进行。

4

5 回答 5

11

通常,您需要获取类的所有属性值并将它们组合成一个字符串。这可以使用以下方法完成:

public override string ToString() 
{
    PropertyDescriptorCollection coll = TypeDescriptor.GetProperties(this);
    StringBuilder builder = new StringBuilder();
    foreach(PropertyDescriptor pd in coll)
    {
        builder.Append(string.Format("{0} : {1}", pd.Name , pd.GetValue(this).ToString()));
    }
    return builder.ToString();
}
于 2013-03-06T10:14:11.910 回答
3

该功能称为反射。一个最简单的例子是:

  public class EntityBase
  {
      public override string ToString()
      {
          StringBuilder sb = new StringBuilder();

          foreach ( var property in this.GetType().GetProperties() )
          {
              sb.Append( property.GetValue( this, null ) );
          }

          return sb.ToString();
      } 
  }

  public class TheEntity : EntityBase
  {
      public string Foo { get; set; }
      public string Bar { get; set; }
  }

请对其进行微调以满足您的要求。

如您所见,这个想法是在基类中有一个实现,以便所有后代自动继承相同的行为。

于 2013-03-06T10:17:14.197 回答
2

语言中没有内置的功能可以自动执行此操作,但是您可以编写一个库来执行此操作,使用Expression框架中的功能生成一个函数来执行此操作。

你会有这样的功能:

Func<T,string> GenerateToString<T>()

在你的课堂上,你有这样的东西:

public class EntityAdresse : IEntityADRESSE
{
    private static readonly Func<EntityAdresse,string> s_ToString=Generator.GenerateToString<EntityAdresse>();

    public string Name1 { get; set; }
    public string Strasse { get; set; }
    public string Plz { get; set; }
    public string Ort { get; set; }
    public string NatelD { get; set; }
    public string Mail { get; set; }
    public int Id_anrede { get; set; }
    public string Telefon { get; set; }
    public int Id_adr { get; set; }
    public int Cis_adr { get; set; }

    public override ToString()
    {
       return s_ToString(this);
    }
}

挑战是写作GenerateToString。使用Expression框架和反射,您将能够创建一个与您手动编写代码一样高效的委托。

您可以单独使用反射,但性能损失很快就会成为一个问题。

于 2013-03-06T10:19:07.343 回答
2

有一个用于自动生成 ToString的开源框架StatePrinter 。它是非常可配置的,因此它应该可以满足您的需求。自省代码可以在Introspection找到

于 2014-04-06T11:57:48.560 回答
2

已经说过的简短版本:

public override string ToString()
{
    var propertyStrings = from prop in GetType().GetProperties()
                          select $"{prop.Name}={prop.GetValue(this)}";
    return string.Join(", ", propertyStrings);
}
于 2018-11-16T23:49:48.397 回答