2014-04-28 40 views
4

我使用ReSharper並試圖遵守它的默認規則。ToPascalCase()所有大寫C#縮寫

在我的部分代碼中,我需要將字符串Property更改爲PascalCase。

我已經嘗試了很多方法,但找不到一個適用於包含所有大寫縮寫的東西。

EX:

MPSUser --> Still MPSUser (should be MpsUser) 
ArticleID --> Still Article ID (Should be ArticleId) 
closeMethod --> Works and changes to CloseMethod 

誰能幫我創建一個可以將任何字符串PascalCase的方法? 謝謝!

+2

注意,您可以使用ReSharper的註冊縮寫,它將使他們能夠在PascalCased名稱中使用。例如,對於ArticleID,您可以將ID註冊爲縮寫,並且不會再投訴。 –

回答

4

我知道的轉換爲PascalCase的唯一內置方法是TextInfo.ToTitleCase,它不能處理設計中的全部大寫字母。要解決這個問題,我已經制作一個自定義的正則表達式,可以檢測到所有的字部位,然後將它們分別轉化爲標題/帕斯卡爾案例:

string ToPascalCase(string s) 
{ 
    // Find word parts using the following rules: 
    // 1. all lowercase starting at the beginning is a word 
    // 2. all caps is a word. 
    // 3. first letter caps, followed by all lowercase is a word 
    // 4. the entire string must decompose into words according to 1,2,3. 
    // Note that 2&3 together ensure MPSUser is parsed as "MPS" + "User". 

    var m = Regex.Match(s, "^(?<word>^[a-z]+|[A-Z]+|[A-Z][a-z]+)+$"); 
    var g = m.Groups["word"]; 

    // Take each word and convert individually to TitleCase 
    // to generate the final output. Note the use of ToLower 
    // before ToTitleCase because all caps is treated as an abbreviation. 
    var t = Thread.CurrentThread.CurrentCulture.TextInfo; 
    var sb = new StringBuilder(); 
    foreach (var c in g.Captures.Cast<Capture>()) 
     sb.Append(t.ToTitleCase(c.Value.ToLower())); 
    return sb.ToString(); 
} 

這個功能應該處理常見的用例:

s   | ToPascalCase(s) 
MPSUser  | MpsUser 
ArticleID | ArticleId 
closeMethod | CloseMethod 
1

我大量借鑑了mellamokb的解決方案,想出了一些更全面的東西。例如,我想留下數字。另外,我希望將任何非字母,非數字字符用作分隔符。那就是:

public static string ToPascalCase(this string s) { 
     var result = new StringBuilder(); 
     var nonWordChars = new Regex(@"[^a-zA-Z0-9]+"); 
     var tokens = nonWordChars.Split(s); 
     foreach (var token in tokens) { 
      result.Append(PascalCaseSingleWord(token)); 
     } 

     return result.ToString(); 
    } 

    static string PascalCaseSingleWord(string s) { 
     var match = Regex.Match(s, @"^(?<word>\d+|^[a-z]+|[A-Z]+|[A-Z][a-z]+|\d[a-z]+)+$"); 
     var groups = match.Groups["word"]; 

     var textInfo = Thread.CurrentThread.CurrentCulture.TextInfo; 
     var result = new StringBuilder(); 
     foreach (var capture in groups.Captures.Cast<Capture>()) { 
      result.Append(textInfo.ToTitleCase(capture.Value.ToLower())); 
     } 
     return result.ToString(); 
    } 

這裏是X單元測試,顯示一些測試用例:

[Theory] 
    [InlineData("imAString", "ImAString")] 
    [InlineData("imAlsoString", "ImAlsoString")] 
    [InlineData("ImAlsoString", "ImAlsoString")] 
    [InlineData("im_a_string", "ImAString")] 
    [InlineData("im a string", "ImAString")] 
    [InlineData("ABCAcronym", "AbcAcronym")] 
    [InlineData("im_a_ABCAcronym", "ImAAbcAcronym")] 
    [InlineData("im a ABCAcronym", "ImAAbcAcronym")] 
    [InlineData("8ball", "8Ball")] 
    [InlineData("im a 8ball", "ImA8Ball")] 
    [InlineData("IM_ALL_CAPS", "ImAllCaps")] 
    [InlineData("IM ALSO ALL CAPS", "ImAlsoAllCaps")] 
    [InlineData("i-have-dashes", "IHaveDashes")] 
    [InlineData("a8word_another_word", "A8WordAnotherWord")] 
    public void WhenGivenString_ShouldPascalCaseIt(string input, string expectedResult) { 
     var result = input.ToPascalCase(); 
     Assert.Equal(expectedResult, result); 
    } 
+0

工程就像一個魅力。謝謝! – psulek