-
Notifications
You must be signed in to change notification settings - Fork 966
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
added non-generic DehumanizeTo - addresses #92 #93
Conversation
Yeah looks fine. Though you could DRY it out by simply making the generic version call the non-generic then casting the result. Thanks for adding. |
added non-generic DehumanizeTo - addresses #92
This is now released as v1.11.3 on NuGet |
Actually I spoke too soon, I can't use this as throws an exception if not found, where I need it to return null. private static Enum DehumanizeTo(string input, Type enumType)
{
return Enum.GetValues(enumType).Cast<Enum>().FirstOrDefault(value => string.Equals(value.Humanize(), input, StringComparison.OrdinalIgnoreCase));
} On a side note: EnumHumanizeExtensions.Humanize throws a null exception if the enum is null, but that looks consistent with all the other Humanize methods so fairplay |
I personally think DehumanizeTo should throw exception if it cannot match. It's kinda like you're asking the framework to do a wrong thing and it complains. One solution is to keep the current behavior as the default and also allow it to return null by passing a second optional parameter to the method ( What do you think? |
I agree its hard to see the best way to go. If we look at the equivalent methods in the BCL: if (Enum.IsDefined(coreType, strOfEnum))
return Enum.Parse(coreType, strOfEnum, true); But I don't like how the BCL does it anyway i.e., I would prefer it if Enum.Parse returned null, but there are a lot of places where, IMHO, the BCL throws exceptions when it would be better if it didn't. Some opinions here: http://stackoverflow.com/questions/175532/should-a-retrieval-method-return-null-or-throw-an-exception-when-it-cant-prod BTW why did you roll your own exception rather than use ArgumentException like Enum.Parse? |
Nah, I guess it's cool to add the optional param to the non-generic method (keeping the same name); but instead of a bool we should use an enum so instead of WRT
That's too vague IMO. |
Do you want to send me a PR with the optional param? :) I guess before it's too late we could also rename the custom exception to something a bit more generic like |
PR. is this what you were after? public static class EnumDehumanizeExtensions
{
/// <summary>
/// Dehumanizes a string into the Enum it was originally Humanized from!
/// </summary>
/// <typeparam name="TTargetEnum">The target enum</typeparam>
/// <param name="input">The string to be converted</param>
/// <exception cref="ArgumentException">If TTargetEnum is not an enum</exception>
/// <exception cref="NoMatchFoundException">Couldn't find any enum member that matches the string + input</exception>
/// <returns></returns>
public static TTargetEnum DehumanizeTo<TTargetEnum>(this string input)
where TTargetEnum : struct, IComparable, IFormattable, IConvertible
{
return (TTargetEnum)DehumanizeToPrivate(input, typeof(TTargetEnum), NoMatch.ThrowsException);
}
/// <summary>
/// Dehumanizes a string into the Enum it was originally Humanized from!
/// </summary>
/// <param name="input">The string to be converted</param>
/// <param name="targetEnum">The target enum</param>
/// <param name="whatToDoWhenNotMatched">What to do when input is not matched to the enum.</param>
/// <returns></returns>
/// <exception cref="NoMatchFoundException">Couldn't find any enum member that matches the string + input</exception>
/// <exception cref="ArgumentException">If targetEnum is not an enum</exception>
public static Enum DehumanizeTo(string input, Type targetEnum, NoMatch whatToDoWhenNotMatched = NoMatch.ThrowsException)
{
return (Enum) DehumanizeToPrivate(input, targetEnum, whatToDoWhenNotMatched);
}
private static object DehumanizeToPrivate(string input, Type targetEnum, NoMatch whatToDoWhenNotMatched)
{
var match = Enum.GetValues(targetEnum).Cast<Enum>().FirstOrDefault(value => string.Equals(value.Humanize(), input, StringComparison.OrdinalIgnoreCase));
if (match == null && whatToDoWhenNotMatched == NoMatch.ThrowsException)
throw new NoMatchFoundException("Couldn't find any enum member that matches the string " + input);
return match;
}
}
public enum NoMatch
{
ThrowsException,
ReturnsNull
}
/// <summary>
/// This is thrown on String.DehumanizeTo enum when the provided string cannot be mapped to the target enum
/// </summary>
public class NoMatchFoundException : Exception
{
public NoMatchFoundException()
{
}
public NoMatchFoundException(string message)
: base(message)
{
}
public NoMatchFoundException(string message, Exception inner)
: base(message, inner)
{
}
} |
Thanks. This looks nice. Although it is missing the unit tests, explaining the feature in readme and adding the PR and broken change to release_notes :p |
Ahh, I've just read https://github.com/MehdiK/Humanizer#how-to-contribute, which I missed before, I don't suppose you've thought about adding a table of contents to your readme.md? WRT ArgumentException vs custom exception, what does it matter if there are different ArgumentExceptions for different situations? As long as the exception message is different its just as clear as having a custom exception I would think. |
ToC for readme - good idea. I guess it's big enough to need that. Well, I guess this is a good opportunity to learn git then :) Reading message is easy for humans but hard to do programatically. I hate to catch an exception and have to put an if condition around the message to find out what exactly went wrong. Catching different types of exceptions helps avoid that. |
Implemented in #95 and released as v1.12.4 to NuGet |
No description provided.