Skip to content

Commit

Permalink
Merge pull request #7 from crozone/feature/2.2.0
Browse files Browse the repository at this point in the history
Feature/2.2.0
  • Loading branch information
crozone authored Oct 18, 2017
2 parents 0e09f45 + 87441da commit 43aa9a8
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 72 deletions.
6 changes: 2 additions & 4 deletions FormatWith/FormatWith.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<AssemblyName>FormatWith</AssemblyName>
<AssemblyTitle>FormatWith</AssemblyTitle>
<PackageId>FormatWith</PackageId>
<VersionPrefix>2.1.0</VersionPrefix>
<VersionPrefix>2.2.0</VersionPrefix>
<Authors>Ryan Crosby</Authors>
<Copyright>Copyright © Ryan Crosby 2017</Copyright>
<PackageTags>named string formatter extension NetStandard 2.0</PackageTags>
Expand All @@ -23,8 +23,6 @@
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<RepositoryUrl>https://github.com/crozone/FormatWith</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageReleaseNotes>- Added a Func parameter handler overload to FormatWith and FormattableWith.
- Improved performance for the object based/anonymous class overloads.
- Internal code cleanup</PackageReleaseNotes>
<PackageReleaseNotes>Added handler overload to FormatWith and FormattableWith.</PackageReleaseNotes>
</PropertyGroup>
</Project>
2 changes: 1 addition & 1 deletion FormatWith/Internal/FormatToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public string Raw {
}

/// <summary>
/// Gets the token intter text.
/// Gets the token inner text.
/// This performs a substring operation and allocates a new string object.
/// </summary>
public string Value {
Expand Down
88 changes: 30 additions & 58 deletions FormatWith/Internal/FormatWithMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,13 @@ public static string FormatWith(
char openBraceChar = '{',
char closeBraceChar = '}')
{
return FormatWith(formatString, key =>
{
return new ReplacementResult
{
Success = replacements.TryGetValue(key, out string value),
Value = value
};
},
missingKeyBehaviour,
fallbackReplacementValue,
openBraceChar,
closeBraceChar);
return FormatWith(
formatString,
key => new ReplacementResult(replacements.TryGetValue(key, out string value), value),
missingKeyBehaviour,
fallbackReplacementValue,
openBraceChar,
closeBraceChar);
}

public static string FormatWith(
Expand All @@ -39,18 +34,13 @@ public static string FormatWith(
char openBraceChar = '{',
char closeBraceChar = '}')
{
return FormatWith(formatString, key =>
{
return new ReplacementResult
{
Success = replacements.TryGetValue(key, out object value),
Value = value
};
},
missingKeyBehaviour,
fallbackReplacementValue,
openBraceChar,
closeBraceChar);
return FormatWith(
formatString,
key => new ReplacementResult(replacements.TryGetValue(key, out object value), value),
missingKeyBehaviour,
fallbackReplacementValue,
openBraceChar,
closeBraceChar);
}

private static BindingFlags propertyBindingFlags = BindingFlags.Instance | BindingFlags.Public;
Expand Down Expand Up @@ -96,18 +86,13 @@ public static FormattableString FormattableWith(
char openBraceChar = '{',
char closeBraceChar = '}')
{
return FormattableWith(formatString, key =>
{
return new ReplacementResult
{
Success = replacements.TryGetValue(key, out string value),
Value = value
};
},
missingKeyBehaviour,
fallbackReplacementValue,
openBraceChar,
closeBraceChar);
return FormattableWith(
formatString,
key => new ReplacementResult(replacements.TryGetValue(key, out string value), value),
missingKeyBehaviour,
fallbackReplacementValue,
openBraceChar,
closeBraceChar);
}

public static FormattableString FormattableWith(
Expand All @@ -118,18 +103,13 @@ public static FormattableString FormattableWith(
char openBraceChar = '{',
char closeBraceChar = '}')
{
return FormattableWith(formatString, key =>
{
return new ReplacementResult
{
Success = replacements.TryGetValue(key, out object value),
Value = value
};
},
missingKeyBehaviour,
fallbackReplacementValue,
openBraceChar,
closeBraceChar);
return FormattableWith(
formatString,
key => new ReplacementResult(replacements.TryGetValue(key, out object value), value),
missingKeyBehaviour,
fallbackReplacementValue,
openBraceChar,
closeBraceChar);
}

public static FormattableString FormattableWith(
Expand Down Expand Up @@ -183,19 +163,11 @@ private static ReplacementResult FromReplacementObject(string key, object replac
PropertyInfo propertyInfo = replacementObject.GetType().GetProperty(key, propertyBindingFlags);
if (propertyInfo == null)
{
return new ReplacementResult()
{
Success = false,
Value = null
};
return new ReplacementResult(false, null);
}
else
{
return new ReplacementResult
{
Success = true,
Value = propertyInfo.GetValue(replacementObject)
};
return new ReplacementResult(true, propertyInfo.GetValue(replacementObject));
}
}
}
Expand Down
10 changes: 8 additions & 2 deletions FormatWith/ReplacementResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ namespace FormatWith
{
public struct ReplacementResult
{
public bool Success { get; set; }
public object Value { get; set; }
public ReplacementResult(bool success, object value)
{
Success = success;
Value = value;
}

public bool Success { get; }
public object Value { get; }
}
}
94 changes: 88 additions & 6 deletions FormatWith/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,48 @@ public static string FormatWith(
closeBraceChar);
}

/// <summary>
/// Formats a string, using a handler function to provide the value
/// of each parameter.
/// </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>
/// <returns>The formatted string</returns>
public static string FormatWith(
this string formatString,
Func<string, ReplacementResult> handler)
{
return FormatWithMethods.FormatWith(formatString, handler);
}

/// <summary>
/// Formats a string, using a handler function to provide the value
/// of each parameter.
/// </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 formatted string</returns>
public static string FormatWith(
this string formatString,
Func<string, ReplacementResult> handler,
MissingKeyBehaviour missingKeyBehaviour = MissingKeyBehaviour.ThrowException,
object fallbackReplacementValue = null,
char openBraceChar = '{',
char closeBraceChar = '}')
{
return FormatWithMethods.FormatWith(
formatString,
handler,
missingKeyBehaviour,
fallbackReplacementValue,
openBraceChar,
closeBraceChar);
}

#endregion

#region FormattableWith Overloads
Expand All @@ -146,7 +188,7 @@ public static string FormatWith(
/// </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>
/// <returns>A FormattableString representing the string with dictionary keys replaced by (formatted) key values</returns>
/// <returns>The resultant <see cref="FormattableString"/></returns>
public static FormattableString FormattableWith(this string formatString, object replacementObject)
{
// wrap the type object in a wrapper Dictionary class that exposes the properties as dictionary keys via reflection
Expand All @@ -162,7 +204,7 @@ public static FormattableString FormattableWith(this string formatString, object
/// <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>A FormattableString representing the string with dictionary keys replaced by (formatted) key values</returns>
/// <returns>The resultant <see cref="FormattableString"/></returns>
public static FormattableString FormattableWith(
this string formatString,
object replacementObject,
Expand All @@ -185,7 +227,7 @@ public static FormattableString FormattableWith(
/// </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>
/// <returns>A version of the formatString string with dictionary keys replaced by (formatted) key values</returns>
/// <returns>The resultant <see cref="FormattableString"/></returns>
public static FormattableString FormattableWith(this string formatString, IDictionary<string, string> replacements)
{
// wrap the IDictionary<string, string> in a wrapper Dictionary class that casts the values to objects as needed
Expand All @@ -201,7 +243,7 @@ public static FormattableString FormattableWith(this string formatString, IDicti
/// <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>A version of the formatString string with dictionary keys replaced by (formatted) key values</returns>
/// <returns>The resultant <see cref="FormattableString"/></returns>
public static FormattableString FormattableWith(
this string formatString,
IDictionary<string, string> replacements,
Expand All @@ -225,7 +267,7 @@ public static FormattableString FormattableWith(
/// </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>
/// <returns>A version of the formatString string with dictionary keys replaced by (formatted) key values</returns>
/// <returns>The resultant <see cref="FormattableString"/></returns>
public static FormattableString FormattableWith(this string formatString, IDictionary<string, object> replacements)
{
return FormatWithMethods.FormattableWith(formatString, replacements);
Expand All @@ -240,7 +282,7 @@ public static FormattableString FormattableWith(this string formatString, IDicti
/// <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>A version of the formatString string with dictionary keys replaced by (formatted) key values</returns>
/// <returns>The resultant <see cref="FormattableString"/></returns>
public static FormattableString FormattableWith(
this string formatString,
IDictionary<string, object> replacements,
Expand All @@ -258,6 +300,46 @@ public static FormattableString FormattableWith(
closeBraceChar);
}

/// <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>
/// <returns>The resultant <see cref="FormattableString"/></returns>
public static FormattableString FormattableWith(
this string formatString,
Func<string, ReplacementResult> handler)
{
return FormatWithMethods.FormattableWith(formatString, handler);
}

/// <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);
}

#endregion

/// <summary>
Expand Down
49 changes: 49 additions & 0 deletions FormatWithTests/FormatWithTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,55 @@ public void TestAsymmetricCustomBraces()
Assert.Equal("abcReplacement1{DoesntExist>", replacement);
}

[Fact]
public void TestCustomHandler1()
{
string replacement = "Hey, {make this uppercase!} Thanks.".FormatWith(
(parameter) => new ReplacementResult(true, parameter.ToUpper())
);

Assert.Equal("Hey, MAKE THIS UPPERCASE! Thanks.", replacement);
}

[Fact]
public void TestCustomHandler2()
{
string replacement = "<abcDEF123:reverse>, <abcDEF123:uppercase>, <abcDEF123:lowercase>.".FormatWith(
(parameter) =>
{
int splitIndex = parameter.LastIndexOf(':');
if (splitIndex < 0)
{
return new ReplacementResult(true, parameter);
}
else
{
string value = parameter.Substring(0, splitIndex);
string modifier = parameter.Length > splitIndex + 1 ? parameter.Substring(splitIndex + 1) : string.Empty;
switch (modifier)
{
case "uppercase":
return new ReplacementResult(true, value.ToUpper());
case "lowercase":
return new ReplacementResult(true, value.ToLower());
case "reverse":
return new ReplacementResult(true, new string(value.Reverse().ToArray()));
default:
return new ReplacementResult(false, null);
}
}
},
MissingKeyBehaviour.ReplaceWithFallback,
"Fallback",
'<',
'>'
);

Assert.Equal("321FEDcba, ABCDEF123, abcdef123.", replacement);
}

[Fact]
public void SpeedTest()
{
Expand Down
Loading

0 comments on commit 43aa9a8

Please sign in to comment.