public static BindingTemplateToken NewExpression(string expression) { // BindingData takes precedence over builtins. BindingParameterResolver builtin; BindingParameterResolver.TryGetResolver(expression, out builtin); // check for formatter, which is applied to finale results. string format = null; if (builtin == null) { int indexColon = expression.IndexOf(':'); if (indexColon > 0) { format = expression.Substring(indexColon + 1); expression = expression.Substring(0, indexColon); } } if (!BindingTemplateParser.IsValidIdentifier(expression)) { throw new FormatException($"Invalid template expression '{expression}"); } // Expression is just a series of dot operators like: a.b.c var parts = expression.Split('.'); // For backwards compat, first part can't have a '-' if (builtin == null) { if (parts[0].IndexOf('-') >= 0) { throw new FormatException($"The parameter name '{parts[0]}' is invalid."); } } foreach (var part in parts) { if (string.IsNullOrWhiteSpace(part)) { throw new InvalidOperationException($"Illegal expression: {parts}"); } } return(new ExpressionToken(parts, format, builtin)); }
/// <summary> /// Resolves original parameterized template into a string by replacing parameters with values provided as /// a dictionary. /// </summary> /// <param name="parameters">Dictionary providing parameter values.</param> /// <returns>Resolved string if succeeded.</returns> /// <exception cref="InvalidOperationException">Thrown when required parameter value is not available. /// </exception> public string Bind(IReadOnlyDictionary <string, string> parameters) { StringBuilder builder = new StringBuilder(); if (_ignoreCase && parameters != null) { // convert to a case insensitive dictionary var caseInsensitive = new Dictionary <string, string>(parameters.Count, StringComparer.OrdinalIgnoreCase); foreach (var pair in parameters) { caseInsensitive.Add(pair.Key, pair.Value); } parameters = caseInsensitive; } foreach (BindingTemplateToken token in Tokens) { if (token.IsParameter) { string value; BindingParameterResolver resolver = null; if (parameters != null && parameters.TryGetValue(token.Value, out value)) { // parameter is resolved from binding data builder.Append(value); } else if (BindingParameterResolver.TryGetResolver(token.Value, out resolver)) { // parameter maps to one of the built-in system binding // parameters (e.g. rand-guid, datetime, etc.) value = resolver.Resolve(token.Value); builder.Append(value); } else { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, "No value for named parameter '{0}'.", token.Value)); } } else { builder.Append(token.Value); } } return(builder.ToString()); }