2010-03-10 76 views
14

在Java世界中,我們有Apache Commons'ToStringBuilder來幫助創建toString()實現。是否有與C#的Java的ToStringBuilder相當的功能?什麼是一個好的C#版本功能?

有誰知道C#有一個體面的免費實現嗎?有沒有更好的選擇我不知道?

如果沒有免費的實現存在,我想這個問題變得更多的是一個問題「什麼會在C#3中成爲一個好的ToStringBuilder?」

關閉我的頭頂:

  • ,它還可以提供反射和手動的ToString字符串創建。

  • 如果可以使用表達式樹,它將會非常酷。

事情是這樣的..

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

這將返回:

"Foo{Id: 1, Name: AName}" 
  • 它可以使用System.Reflection.Emit預編譯一個ToString委託。

還有其他想法嗎?

UPDATE

只是爲了澄清ToStringBuilder是不同的生物來的StringBuilder ..我正在尋找一個類似於阿帕奇常見的ToStringBuilder的功能,它具有的功能,如多行的格式,不同的樣式和反射基礎ToString創建。謝謝。

更新2

我已經建立了我自己。見here

+0

也許你應該鏈接到ToStringBuilder所做的描述:http://commons.apache.org/lang/api/org/apache/commons/lang/builder/ToStringBuilder。html – Powerlord 2010-03-10 14:44:04

+0

@Powerlord,謝謝我已經更新了鏈接,我猜並不是每個人都像我一樣喜歡grokking源代碼;-) – chillitom 2010-03-10 14:48:20

+0

快速C#4版本添加如下:http://stackoverflow.com/questions/2417647/is-有一個相當於javas-tostringbuilder-for-c-what-will-a-good-c-ver/4959343#4959343 – chillitom 2011-02-10 15:53:01

回答

13

編輯:OK,你要使用反射,這樣你就不必鍵入屬性名稱。我認爲這將讓你你以後:

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

例子:

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

看哪,你後的行爲:

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

輸出:

事{Id:10,Name:「Bob」}

+2

差不多一樣好,它有字符串文字,並且不能存活重構 – 2010-03-10 14:49:06

+0

謝謝Dan,這是一個非常好的解決方案。如果我們可以進一步擴展Java版本並使用表達式去除名稱字符串,這將是很酷的,這樣代碼就可以重構。 – chillitom 2010-03-10 15:02:37

+0

@chillitom:我給它敲了一下 - 看看。 – 2010-03-10 15:59:49

1

使用.NET的StringBuilder

請注意,您必須自己提供一個小模板。

E.g:

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

return sb; 
} 

提供這裏還挺generic方式。 您可以在.NET創建與System.Reflection命名自己巧妙的解決辦法

乾杯

+0

謝謝,但我追求的東西完全不同,字符串生成器很好,但需要更多嫁接成一個比Java的Apache Commons ToStringBuilder所做的漂亮的ToString。 – chillitom 2010-03-10 14:41:09

+0

看到它,你可以嘗試製作自己的ToStringBuilder方法,它包含一個stringbuilder .. – 2010-03-10 14:42:17

+0

你發佈的方法只返回一個字符串。 – 2010-03-10 14:44:54

1

看到這個項目......

http://commonsdotnet.codeplex.com/

+0

感謝mxmissile,我知道某些東西必須存在某處。雖然看起來有點令人失望,但我猜測它的目標是C#版本2及以下版本。它與Java類非常不同,它只是一堆靜態調用,並且需要將字段名稱作爲字符串列表傳入,而使用C#3肯定可能更好。 – chillitom 2010-03-10 15:17:24

+0

是的,只是注意到了,我發誓我曾在某處看過這個地方,認爲那是地方。將繼續尋找,我也可以使用這樣的事情。 – mxmissile 2010-03-10 15:24:32

0

我不知道任何現有的項目會做你想做的事情,但實現你使用lambda表達式的例子並不難。

這裏的另一個[未經測試/未編譯/可能錯誤]想法使用匿名委託:

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

ToString()超載將被寫爲一個擴展方法,所以你能在源對象的引用,並會接受Action<T>其中[T]是源對象的類型。然後,ToString()方法將新建一個字符串構建器或某種內部對象,執行從調用者傳入的匿名方法,然後將結果包含在任何必需的開始/結束文本中。

要說清楚,我實際上並沒有試過這個。我只是覺得它比原始問題中基於lambda的示例更靈活一些。

3

由於它不是免費的,它可能並不完全符合你的要求,但Resharper可以做到這一點。這是一個夢幻般的插件,視覺工作室不僅僅是生成ToString。但它會這樣做。把你的光標放在你的班級裏,按Alt + Insert並選擇格式化成員。有關

+0

+1爲了更好的修復技巧! – IAdapter 2011-02-06 21:44:45

3

原來的問題C#3.5,但從那時起,我升級到C#4

我想我會在這裏分享我的新版本的情況下,這是有利於他人。它具有此線程中提到的所有功能,並在運行時編譯爲快速的Stringify方法。

從這裏下載:ToStringBuilder

+0

hi chillitom,你的ToStringBuilder看起來很棒,但它似乎不能處理泛型列表,比如List ,它只是在列表中調用ToString()而不枚舉,所以你只需要獲取列表的全名而不是內容。我試圖增強它來處理列表,但我無法繞過使用linq表達式的泛型。你有沒有增強它來處理泛型列表?謝謝! – matao 2014-09-16 05:54:50

+0

對不起,我沒有,但我會接受一個拉請求。反射API可讓您使用泛型類型並創建具體化類型,例如typeof(List <>)。MakeGenericType(typeof(int))=== typeof(列表) – chillitom 2014-09-17 16:08:51

+0

好吧,我想弄明白,當我做我會給你發一個請求。乾杯! – matao 2014-09-18 01:30:36

0

ObjectPrinter將與一些自定義的功能爲你做這個。文檔仍然有點粗糙,但是我們已經在生產中使用了多年,並取得了很好的成果。

相關問題