Esempio n. 1
0
        /// <summary>
        /// Processes a list of format tokens into a string
        /// </summary>
        /// <param name="tokens">List of tokens to turn into a string</param>
        /// <param name="replacements">An <see cref="IDictionary"/> with keys and values to inject into the formatted result</param>
        /// <param name="missingKeyBehaviour">The behaviour to use when the format string contains a parameter that is not present in the lookup dictionary</param>
        /// <param name="fallbackReplacementValue">When the <see cref="MissingKeyBehaviour.ReplaceWithFallback"/> is specified, this string is used as a fallback replacement value when the parameter is present in the lookup dictionary.</param>
        /// <returns>The processed result of joining the tokens with the replacement dictionary.</returns>
        public static string ProcessTokens(
            IEnumerable <FormatToken> tokens,
            Func <string, ReplacementResult> handler,
            MissingKeyBehaviour missingKeyBehaviour,
            object fallbackReplacementValue,
            int outputLengthHint)
        {
            // create a StringBuilder to hold the resultant output string
            // use the input hint as the initial size
            StringBuilder resultBuilder = new StringBuilder(outputLengthHint);

            foreach (FormatToken thisToken in tokens)
            {
                if (thisToken.TokenType == TokenType.Text)
                {
                    // token is a text token
                    // add the token to the result string builder
                    resultBuilder.Append(thisToken.SourceString, thisToken.StartIndex, thisToken.Length);
                }
                else if (thisToken.TokenType == TokenType.Parameter)
                {
                    // token is a parameter token
                    // perform parameter logic now.

                    // append the replacement for this parameter
                    ReplacementResult replacementResult = handler(thisToken.Value);

                    if (replacementResult.Success)
                    {
                        // the key exists, add the replacement value
                        // this does nothing if replacement value is null
                        resultBuilder.Append(replacementResult.Value);
                    }
                    else
                    {
                        // the key does not exist, handle this using the missing key behaviour specified.
                        switch (missingKeyBehaviour)
                        {
                        case MissingKeyBehaviour.ThrowException:
                            // the key was not found as a possible replacement, throw exception
                            throw new KeyNotFoundException($"The parameter \"{thisToken.Value}\" was not present in the lookup dictionary");

                        case MissingKeyBehaviour.ReplaceWithFallback:
                            resultBuilder.Append(fallbackReplacementValue);
                            break;

                        case MissingKeyBehaviour.Ignore:
                            // the replacement value is the input key as a parameter.
                            // use source string and start/length directly with append rather than
                            // parameter.ParameterKey to avoid allocating an extra string
                            resultBuilder.Append(thisToken.SourceString, thisToken.StartIndex, thisToken.Length);
                            break;
                        }
                    }
                }
            }

            // return the resultant string
            return(resultBuilder.ToString());
        }
Esempio n. 2
0
        public static FormattableString FormattableWith(
            string formatString,
            Func <string, ReplacementResult> handler,
            MissingKeyBehaviour missingKeyBehaviour = MissingKeyBehaviour.ThrowException,
            object fallbackReplacementValue         = null,
            char openBraceChar  = '{',
            char closeBraceChar = '}')
        {
            // get the parameters from the format string
            IEnumerable <FormatToken> tokens = FormatHelpers.Tokenize(formatString, openBraceChar, closeBraceChar);

            return(FormatHelpers.ProcessTokensIntoFormattableString(tokens, handler, missingKeyBehaviour, fallbackReplacementValue, formatString.Length * 2));
        }
Esempio n. 3
0
 public static FormattableString FormattableWith(
     string formatString,
     object replacementObject,
     MissingKeyBehaviour missingKeyBehaviour = MissingKeyBehaviour.ThrowException,
     object fallbackReplacementValue         = null,
     char openBraceChar  = '{',
     char closeBraceChar = '}')
 {
     return(FormattableWith(formatString,
                            key => FromReplacementObject(key, replacementObject),
                            missingKeyBehaviour,
                            fallbackReplacementValue,
                            openBraceChar,
                            closeBraceChar));
 }
Esempio n. 4
0
 public static FormattableString FormattableWith(
     string formatString,
     IDictionary <string, string> replacements,
     MissingKeyBehaviour missingKeyBehaviour = MissingKeyBehaviour.ThrowException,
     string fallbackReplacementValue         = null,
     char openBraceChar  = '{',
     char closeBraceChar = '}')
 {
     return(FormattableWith(
                formatString,
                key => new ReplacementResult(replacements.TryGetValue(key, out string value), value),
                missingKeyBehaviour,
                fallbackReplacementValue,
                openBraceChar,
                closeBraceChar));
 }
Esempio n. 5
0
 /// <summary>
 /// Produces a <see cref="FormattableString"/> representing the input format string.
 /// </summary>
 /// <param name="formatString">The format string, containing keys like {foo}</param>
 /// <param name="handler">A handler function that transforms each parameter into a <see cref="ReplacementResult"/></param>
 /// <param name="missingKeyBehaviour">The behaviour to use when the format string contains a parameter that cannot be replaced by the handler</param>
 /// <param name="fallbackReplacementValue">When the <see cref="MissingKeyBehaviour.ReplaceWithFallback"/> is specified, this object is used as a fallback replacement value.</param>
 /// <param name="openBraceChar">The character used to begin parameters</param>
 /// <param name="closeBraceChar">The character used to end parameters</param>
 /// <returns>The resultant <see cref="FormattableString"/></returns>
 public static FormattableString FormattableWith(
     this string formatString,
     Func <string, ReplacementResult> handler,
     MissingKeyBehaviour missingKeyBehaviour = MissingKeyBehaviour.ThrowException,
     object fallbackReplacementValue         = null,
     char openBraceChar  = '{',
     char closeBraceChar = '}')
 {
     return(FormatWithMethods.FormattableWith(
                formatString,
                handler,
                missingKeyBehaviour,
                fallbackReplacementValue,
                openBraceChar,
                closeBraceChar));
 }
Esempio n. 6
0
 /// <summary>
 /// Produces a <see cref="FormattableString"/> representing the input format string.
 /// </summary>
 /// <param name="formatString">The format string, containing keys like {foo}</param>
 /// <param name="replacements">An <see cref="IDictionary"/> with keys and values to inject into the string</param>
 /// <param name="missingKeyBehaviour">The behaviour to use when the format string contains a parameter that is not present in the lookup dictionary</param>
 /// <param name="fallbackReplacementValue">When the <see cref="MissingKeyBehaviour.ReplaceWithFallback"/> is specified, this string is used as a fallback replacement value when the parameter is present in the lookup dictionary.</param>
 /// <param name="openBraceChar">The character used to begin parameters</param>
 /// <param name="closeBraceChar">The character used to end parameters</param>
 /// <returns>The resultant <see cref="FormattableString"/></returns>
 public static FormattableString FormattableWith(
     this string formatString,
     IDictionary <string, object> replacements,
     MissingKeyBehaviour missingKeyBehaviour = MissingKeyBehaviour.ThrowException,
     object fallbackReplacementValue         = null,
     char openBraceChar  = '{',
     char closeBraceChar = '}')
 {
     return(FormatWithMethods.FormattableWith(
                formatString,
                replacements,
                missingKeyBehaviour,
                fallbackReplacementValue,
                openBraceChar,
                closeBraceChar));
 }
Esempio n. 7
0
 /// <summary>
 /// Formats a string with the values of the dictionary.
 /// </summary>
 /// <param name="formatString">The format string, containing keys like {foo}</param>
 /// <param name="replacements">An <see cref="IDictionary"/> with keys and values to inject into the string</param>
 /// <param name="missingKeyBehaviour">The behaviour to use when the format string contains a parameter that is not present in the lookup dictionary</param>
 /// <param name="fallbackReplacementValue">When the <see cref="MissingKeyBehaviour.ReplaceWithFallback"/> is specified, this string is used as a fallback replacement value when the parameter is present in the lookup dictionary.</param>
 /// <param name="openBraceChar">The character used to begin parameters</param>
 /// <param name="closeBraceChar">The character used to end parameters</param>
 /// <returns>The formatted string</returns>
 public static string FormatWith(
     this string formatString,
     IDictionary <string, string> replacements,
     MissingKeyBehaviour missingKeyBehaviour = MissingKeyBehaviour.ThrowException,
     string fallbackReplacementValue         = null,
     char openBraceChar  = '{',
     char closeBraceChar = '}')
 {
     // wrap the IDictionary<string, string> in a wrapper Dictionary class that casts the values to objects as needed
     return(FormatWithMethods.FormatWith(
                formatString,
                replacements,
                missingKeyBehaviour,
                fallbackReplacementValue,
                openBraceChar,
                closeBraceChar));
 }
Esempio n. 8
0
 /// <summary>
 /// Formats a string with the values given by the properties on an input object.
 /// </summary>
 /// <param name="formatString">The format string, containing keys like {foo}</param>
 /// <param name="replacementObject">The object whose properties should be injected in the string</param>
 /// <param name="missingKeyBehaviour">The behaviour to use when the format string contains a parameter that is not present in the lookup dictionary</param>
 /// <param name="fallbackReplacementValue">When the <see cref="MissingKeyBehaviour.ReplaceWithFallback"/> is specified, this string is used as a fallback replacement value when the parameter is present in the lookup dictionary.</param>
 /// <param name="openBraceChar">The character used to begin parameters</param>
 /// <param name="closeBraceChar">The character used to end parameters</param>
 /// <returns>The formatted string</returns>
 public static string FormatWith(
     this string formatString,
     object replacementObject,
     MissingKeyBehaviour missingKeyBehaviour = MissingKeyBehaviour.ThrowException,
     object fallbackReplacementValue         = null,
     char openBraceChar  = '{',
     char closeBraceChar = '}')
 {
     // wrap the type object in a wrapper Dictionary class that exposes the properties as dictionary keys via reflection
     return(FormatWithMethods.FormatWith(
                formatString,
                replacementObject,
                missingKeyBehaviour,
                fallbackReplacementValue,
                openBraceChar,
                closeBraceChar));
 }
Esempio n. 9
0
        public static string FormatWith(
            string formatString,
            object replacementObject,
            MissingKeyBehaviour missingKeyBehaviour = MissingKeyBehaviour.ThrowException,
            object fallbackReplacementValue         = null,
            char openBraceChar  = '{',
            char closeBraceChar = '}')
        {
            if (replacementObject == null)
            {
                throw new ArgumentNullException(nameof(replacementObject));
            }

            return(FormatWith(formatString,
                              (key, format) => FromReplacementObject(key, replacementObject),
                              missingKeyBehaviour,
                              fallbackReplacementValue,
                              openBraceChar,
                              closeBraceChar));
        }
Esempio n. 10
0
        /// <summary>
        /// Processes a list of format tokens into a string
        /// </summary>
        /// <param name="tokens">List of tokens to turn into a string</param>
        /// <param name="replacements">An <see cref="IDictionary"/> with keys and values to inject into the formatted result</param>
        /// <param name="missingKeyBehaviour">The behaviour to use when the format string contains a parameter that is not present in the lookup dictionary</param>
        /// <param name="fallbackReplacementValue">When the <see cref="MissingKeyBehaviour.ReplaceWithFallback"/> is specified, this string is used as a fallback replacement value when the parameter is present in the lookup dictionary.</param>
        /// <returns>The processed result of joining the tokens with the replacement dictionary.</returns>
        public static FormattableString ProcessTokensIntoFormattableString(
            IEnumerable <FormatToken> tokens,
            Func <string, ReplacementResult> handler,
            MissingKeyBehaviour missingKeyBehaviour,
            object fallbackReplacementValue,
            int outputLengthHint)
        {
            List <object> replacementParams = new List <object>();

            // create a StringBuilder to hold the resultant output string
            // use the input hint as the initial size
            StringBuilder resultBuilder = new StringBuilder(outputLengthHint);

            // this is the index of the current placeholder in the composite format string
            int placeholderIndex = 0;

            foreach (FormatToken thisToken in tokens)
            {
                if (thisToken.TokenType == TokenType.Text)
                {
                    // token is a text token.
                    // add the token to the result string builder.
                    // because this text is going into a standard composite format string,
                    // any instaces of { or } must be escaped with {{ and }}
                    resultBuilder.AppendWithEscapedBrackets(thisToken.SourceString, thisToken.StartIndex, thisToken.Length);
                }
                else if (thisToken.TokenType == TokenType.Parameter)
                {
                    // token is a parameter token
                    // perform parameter logic now.
                    var    tokenKey     = thisToken.Value;
                    string format       = null;
                    var    separatorIdx = tokenKey.IndexOf(":", StringComparison.Ordinal);
                    if (separatorIdx > -1)
                    {
                        tokenKey = thisToken.Value.Substring(0, separatorIdx);
                        format   = thisToken.Value.Substring(separatorIdx + 1);
                    }

                    // append the replacement for this parameter
                    ReplacementResult replacementResult = handler(tokenKey);

                    string IndexAndFormat()
                    {
                        if (string.IsNullOrWhiteSpace(format))
                        {
                            return("{" + placeholderIndex + "}");
                        }

                        return("{" + placeholderIndex + ":" + format + "}");
                    }

                    // append the replacement for this parameter
                    if (replacementResult.Success)
                    {
                        // Instead of appending the replacement value directly as before,
                        // append the next placeholder with the current placeholder index.
                        // Add the actual replacement format item into the replacement values.
                        resultBuilder.Append(IndexAndFormat());
                        placeholderIndex++;
                        replacementParams.Add(replacementResult.Value);
                    }
                    else
                    {
                        // the key does not exist, handle this using the missing key behaviour specified.
                        switch (missingKeyBehaviour)
                        {
                        case MissingKeyBehaviour.ThrowException:
                            // the key was not found as a possible replacement, throw exception
                            throw new KeyNotFoundException($"The parameter \"{thisToken.Value}\" was not present in the lookup dictionary");

                        case MissingKeyBehaviour.ReplaceWithFallback:
                            // Instead of appending the replacement value directly as before,
                            // append the next placeholder with the current placeholder index.
                            // Add the actual replacement format item into the replacement values.
                            resultBuilder.Append(IndexAndFormat());
                            placeholderIndex++;
                            replacementParams.Add(fallbackReplacementValue);
                            break;

                        case MissingKeyBehaviour.Ignore:
                            resultBuilder.AppendWithEscapedBrackets(thisToken.SourceString, thisToken.StartIndex, thisToken.Length);
                            break;
                        }
                    }
                }
            }

            // return the resultant string
            return(FormattableStringFactory.Create(resultBuilder.ToString(), replacementParams.ToArray()));
        }