Created
April 2, 2012 15:07
-
-
Save wcharczuk/2284226 to your computer and use it in GitHub Desktop.
C# Route Parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Web; | |
using System.Text.RegularExpressions; | |
//TODO: probably want to change this if you're using it your project | |
namespace ClothesHorse.Core | |
{ | |
/// <summary> | |
/// Utiltiy to parse routes based on a token format. | |
/// </summary> | |
/// <remarks> | |
/// Casing doesn't matter! | |
/// </remarks> | |
/// <example> | |
/// <code> | |
/// var parser = new RouteParser("{protocol}://mydomain.com/{itemCategory}/{itemId}"); | |
/// var variables = parser.Variables; //should be .Count == 3 | |
/// var values = parser.ParseRouteInstance("https://mydomain.com/foo/1"); | |
/// //values = { { "protocol" => "https"}, { "itemCategory" => "foo"}, { "itemId" => "1" } } | |
/// </code> | |
/// </example> | |
[Serializable] | |
public class RouteParser | |
{ | |
public RouteParser(String route, Char variableStartChar = '{', Char variableEndChar = '}') | |
{ | |
RouteFormat = route; | |
this.VariableStartChar = variableStartChar; | |
this.VariableEndChar = variableEndChar; | |
ParseRouteFormat(); | |
} | |
private const String RouteTokenPattern = @"[{0}].+?[{1}]"; //the 0 and 1 are used by the string.format function, they are the start and end characters. | |
private const String VariableTokenPattern = "(?<{0}>[^,]*)"; //the <>'s denote the group name; this is used for reference for the variables later. | |
/// <summary> | |
/// This is the route template that values are extracted based on. | |
/// </summary> | |
/// <value> | |
/// A string containing variables denoted by the <c>VariableStartChar</c> and the <c>VariableEndChar</c> | |
/// </value> | |
public String RouteFormat { get; set; } | |
/// <summary> | |
/// This is the character that denotes the beginning of a variable name. | |
/// </summary> | |
public Char VariableStartChar { get; set; } | |
/// <summary> | |
/// This is the character that denotes the end of a variable name. | |
/// </summary> | |
public Char VariableEndChar { get; set; } | |
/// <summary> | |
/// A hash set of all variable names parsed from the <c>RouteFormat</c>. | |
/// </summary> | |
public HashSet<String> Variables { get; set; } | |
/// <summary> | |
/// Initialize the Variables set based on the <c>RouteFormat</c> | |
/// </summary> | |
public void ParseRouteFormat() | |
{ | |
var variableList = new List<String>(); | |
var matchCollection = System.Text.RegularExpressions.Regex.Matches | |
( | |
this.RouteFormat | |
, String.Format(RouteTokenPattern, VariableStartChar, VariableEndChar) | |
, RegexOptions.IgnoreCase | |
); | |
foreach (var match in matchCollection) | |
{ | |
variableList.Add(RemoteVariableChars(match.ToString())); | |
} | |
Variables = new HashSet<string>(variableList); | |
} | |
/// <summary> | |
/// Extract variable values from a given instance of the route you're trying to parse. | |
/// </summary> | |
/// <param name="routeInstance">The route instance.</param> | |
/// <returns>A dictionary of Variable names mapped to values.</returns> | |
public Dictionary<String, String> ParseRouteInstance(String routeInstance) | |
{ | |
var inputValues = new Dictionary<string, string>(); | |
String formatUrl = new String(RouteFormat.ToArray()); | |
foreach (String variable in Variables) | |
{ | |
formatUrl = formatUrl.Replace(WrapWithVariableChars(variable), String.Format(VariableTokenPattern, variable)); | |
} | |
var regex = new Regex(formatUrl, RegexOptions.IgnoreCase); | |
var matchCollection = regex.Match(routeInstance); | |
foreach (var variable in Variables) | |
{ | |
var value = ((Group)matchCollection.Groups[variable]).Value; | |
inputValues.Add(variable, value); | |
} | |
return inputValues; | |
} | |
/// <summary> | |
/// Replace a variable in the <c>RouteFormat</c> with a specified value. | |
/// </summary> | |
/// <param name="variableName">The variable name to replace.</param> | |
/// <param name="variableValue">The value to replace with.</param> | |
/// <param name="workingRoute">An 'in progress' route that may contain values that have already been replaced.</param> | |
/// <returns>A <c>workingRoute</c></returns> | |
public String SetVariable(String variableName, String variableValue, String workingRoute = null) | |
{ | |
if (!variableName.StartsWith(VariableStartChar.ToString()) && !variableName.EndsWith(VariableEndChar.ToString())) | |
variableName = String.Format("{1}{0}{2}", variableName, VariableStartChar, VariableEndChar); | |
if(!String.IsNullOrEmpty(workingRoute)) | |
return workingRoute.Replace(variableName, variableValue); | |
else | |
return RouteFormat.Replace(variableName, variableValue); | |
} | |
#region Private Helper Methods | |
private String RemoteVariableChars(String input) | |
{ | |
if (String.IsNullOrWhiteSpace(input)) | |
return input; | |
string result = new String(input.ToArray()); | |
result = result.Replace(VariableStartChar.ToString(), String.Empty).Replace(VariableEndChar.ToString(), String.Empty); | |
return result; | |
} | |
private String WrapWithVariableChars(String input) | |
{ | |
return String.Format("{0}{1}{2}", VariableStartChar, input, VariableEndChar); | |
} | |
#endregion | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment