2013-03-06 185 views
5

我有一些只用于包含数据的类。例如,C#中的元编程:自动ToString方法

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#中执行。

回答

7

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

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

它也必须显示该属性的名称。 – 2013-03-06 10:19:15

+0

更新....我在这里添加属性名称。 – platon 2013-03-06 10:22:33

+0

@platon你可以在'pd.GetValue(this)'上用'null'检查来更新答案。在那种情况下,我在toString上得到了一个N​​ullPointer。 – FrailWords 2015-11-10 10:32:36

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

请微调它以满足您的要求。

正如你所看到的想法是在基类中有一个实现,以便所有的下降自动继承相同的行为。

+0

这不给我属性的名称,对吧? – Luke 2013-03-06 10:21:39

+0

'sb.AppendFormat(“{0} {1}”,property.Name,property.GetValue(this,null));' – 2013-03-06 10:44:22

+0

好的工作,但是......在这种情况下你不能扩展超过EntityBase – boctulus 2015-04-10 23:47:50

1

这种语言没有内置功能可以自动执行此操作,但是您可以使用框架中的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框架和反思,您可以创建一个与手动编写代码一样高效的委托。

你可以使用它自己的反射,但性能命中很快就会开始成为一个问题。

0

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