Parsing very simple CSS into selector and declarations (as as single piece) The last part of my HTML genrator requries a few styles. Because all styles are inline and the styling is for emails there won't be any fancy selectors, just by element, id or class. 

The most complex css might look like this:

var css = @"
h1 { 
    font-family: Sans-Serif; color: green; font-weight: normal; margin-top: 1.5em; 
}
h2 { 
    font-family: Sans-Serif; color: green; font-weight: normal; margin-top: 1.5em; 
}
#foo, p { 
    font-family: Sans-Serif; color: green; 
}
hr, .foo { 
    border: 0; border-bottom: 1px solid #ccc; background: #ccc; 
}";


I read it into a dictionary that the StyleVisitor will consume and applay.

static class Css
{   
    public static IDictionary&lt;string, string&gt; Parse(string css)
    {
        return          
            Regex
                // Match "selector { declarations }"
                .Matches(css.Minify(), @"(?&lt;selectors&gt;[a-z0-9_\-\.,\s#]+)\s*{(?&lt;declarations&gt;.+?)}", RegexOptions.IgnoreCase)
                .Cast&lt;Match&gt;()
                .Select(m =&gt; Regex
                    // Split selectors separated by ",".
                    .Split(m.Groups["selectors"].Value, @",")
                    // Skip empty results.
                    .Where(s =&gt; !string.IsNullOrEmpty(s))
                    .Select(selector =&gt; new KeyValuePair&lt;string, string&gt;(
                        key: selector.Trim().ToLowerInvariant(),
                        value: m.Groups["declarations"].Value.Trim())))
                .SelectMany(x =&gt; x)
                .ToDictionary(x =&gt; x.Key, x =&gt; x.Value);
    }

    private static string Minify(this string css) =&gt; Regex.Replace(css, @"(\r\n|\r|\n)", string.Empty);
}


I'm assuming the css does not require any vaidation because it's been created and validated with an editor like jsfiddle etc.

The result of Css.Parse(css) is

h1    font-family: Sans-Serif; color: green; font-weight: normal; margin-top: 1.5em;
h2    font-family: Sans-Serif; color: green; font-weight: normal; margin-top: 1.5em;
#foo  font-family: Sans-Serif; color: green;
p     font-family: Sans-Serif; color: green;
hr    border: 0; border-bottom: 1px solid #ccc; background: #ccc
.foo  border: 0; border-bottom: 1px solid #ccc; background: #ccc
Some helper functions can make the query look a lot cleaner. LINQ is quite readable on it's own but in your case it has gotten a bit more complex and it's not exactly easy to modify something.

Example of how the main method can look:

public static IDictionary&lt;string, string&gt; Parse(string css)
{
    return GetSelectorMatches(css.Minify())
        .Select(match =&gt; new {match, selectors = ExtractSelectorsByPattern(match, ",")})
        .SelectMany(t =&gt; SelectorToDeclarationValue(t.selectors, t.match))
        .ToDictionary(pair =&gt; pair.Key, pair =&gt; pair.Value);
}


Where the methods have similar implementation to this one.

private static IEnumerable&lt;Match&gt; GetSelectorMatches(string css)
{
    return Regex.Matches(css, @"(?&lt;selectors&gt;[a-z0-9_\-\.,\s#]+)\s*{(?&lt;declarations&gt;.+?)}",
        RegexOptions.IgnoreCase).Cast&lt;Match&gt;();
}

private static IEnumerable&lt;string&gt; ExtractSelectorsByPattern(Match match, string pattern)
{
    return Regex.Split(match.Groups["selectors"].Value, pattern).Where(s =&gt; !string.IsNullOrEmpty(s));
}

private static IEnumerable&lt;KeyValuePair&lt;string, string&gt;&gt; SelectorToDeclarationValue(
    IEnumerable&lt;string&gt; selectors, Match match)
{
    return selectors.Select(selector =&gt; new KeyValuePair&lt;string, string&gt;(
        selector.Trim().ToLowerInvariant(),
        match.Groups["declarations"].Value.Trim()));
}


I'm not sure if it makes sense to have .Where(s =&gt; !string.IsNullOrEmpty(s)) in the method like this maybe additional bool parameter removeEmpty can decide that.

Besides that you can use some Dependency Injection to modify the delegates passed in most of the methods as they're quite specific I really cant provide an example of that as I'm not aware what makes sense to your project to be modifiable and what not.

You can even go one step further and implement some sort of class hierarchy and pass interfaces instead.