7

I am using ReSharper and trying to abide by it's default rules.

In part of my code, I need to change a string Property to PascalCase.

I have tried numerous methods but cannot find one that works for things which include all capital Abbreviations.

EX:

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

Can anyone help me create a method that can turn any String to PascalCase? Thanks!

4

2 回答 2

4

我知道的唯一用于转换为的内置方法PascalCaseTextInfo.ToTitleCase,并且它不按设计处理全大写单词。为了解决这个问题,我制作了一个可以检测所有单词部分的自定义正则表达式,然后将它们单独转换为 Title/Pascal Case:

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
于 2014-04-28T16:14:40.537 回答
2

我从 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);
    }
于 2015-04-17T01:37:37.990 回答