/// <summary> /// Generates a random word in the specified <see cref="StringCasing" /> using the specified parameters of this <see cref="WordGenerator" /> instance. /// </summary> /// <param name="casing">The <see cref="StringCasing" /> to be used for characters in the generated word.</param> /// <returns> /// A new <see cref="string" /> with a dynamically generated word in the specified <see cref="StringCasing" />. /// </returns> public string Generate(StringCasing casing) { Check.ArgumentOutOfRangeEx.GreaterEqual0(MinLength, nameof(MinLength)); Check.ArgumentOutOfRangeEx.GreaterEqual0(MaxLength, nameof(MaxLength)); Check.ArgumentOutOfRangeEx.GreaterEqualValue(MaxLength, MinLength, nameof(MaxLength), nameof(MinLength)); Check.ArgumentOutOfRangeEx.Between0And1(DoubleConsonantChance, nameof(DoubleConsonantChance)); Check.ArgumentOutOfRangeEx.Between0And1(DoubleVovelChance, nameof(DoubleVovelChance)); string word = ""; int length; lock (MathEx._Random) { length = MathEx._Random.Next(MinLength, MaxLength + 1); bool consonant = MathEx._Random.NextBoolean(); while (word.Length < length) { string charset = consonant ? TextResources.Consonants : TextResources.Vovels; float chance = consonant ? DoubleConsonantChance : DoubleVovelChance; consonant = !consonant; char c = MathEx._Random.NextObject(charset.ToCharArray()); word += c.Repeat(MathEx._Random.NextSingle() < chance ? 2 : 1); } } return(word.Left(length).ChangeCasing(casing)); }
public static string ToCase(string input, StringCasing casing, CasingOptions options = CasingOptions.Default) { if (string.IsNullOrEmpty(input)) { return(input); } switch (casing) { case StringCasing.Unchanged: return(input); case StringCasing.Lower: return(input.ToLowerInvariant()); case StringCasing.Upper: return(input.ToUpperInvariant()); case StringCasing.Proper: return(ToProperCase(input, options)); case StringCasing.Sentence: return(ToSentenceCase(input, options)); default: throw new ArgumentOutOfRangeException(nameof(input)); } }
/// <summary> /// Converts object to IDictionary{string,object}. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="source">Source object to convert.</param> /// <param name="keyCasing">The casing for the outputted key.</param> /// <param name="bindingAttr">Types of attributes to bind (if need to be specific).</param> /// <returns>IDictionary object representing the object passed in.</returns> /// <exception cref="InvalidCastException">Cannot automatically cast enumerable to dictionary</exception> public static IDictionary <string, object> AsDictionary <T>(this T source, StringCasing keyCasing = StringCasing.Unchanged, BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance) where T : class, new() { return(source.GetType().GetProperties(bindingAttr).ToDictionary ( propInfo => propInfo.Name.WithCasing(keyCasing), propInfo => propInfo.GetValue(source, null) )); }
/// <summary>Sets the string casing.</summary> /// <param name="source">The source string to modify.</param> /// <param name="casing">The casing to set.</param> /// <returns>System.String.</returns> public static string WithCasing(this string source, StringCasing casing) { switch (casing) { case StringCasing.Uppercase: return(source.ToUpperInvariant()); case StringCasing.Lowercase: return(source.ToLowerInvariant()); default: return(source); } }
/// <summary> /// Returns a <see cref="string"/> that represents this instance. /// </summary> /// <param name="str">The string to transform.</param> /// <param name="stringCasing">The string casing.</param> /// <returns> /// A <see cref="string"/> that represents this instance. /// </returns> public static string ToString(this string str, StringCasing stringCasing) { if (string.IsNullOrEmpty(str)) { return(str); } else { switch (stringCasing) { case StringCasing.Upper: return(str.ToUpper(CultureInfo.CurrentCulture)); case StringCasing.Lower: return(str.ToLower(CultureInfo.CurrentCulture)); case StringCasing.Sentence: return(ToSentenceCase(str)); case StringCasing.Title: return(ToTitleCase(str, CultureInfo.CurrentCulture)); case StringCasing.CapitalWord: return(ToCapitalWordCase(str)); case StringCasing.SnakeCase: return(ToSnakeCase(str)); case StringCasing.CamelCase: return(ToSnakeCase(str)); case StringCasing.None: return(str); default: throw new FormatException("Invalid string casing format."); } } }
/// <summary> /// Generates a random string with the given length. /// </summary> /// <param name="size">Size of the string</param> /// <param name="stringCasing">The string casing.</param> /// <param name="characters">The allowed characters.</param> /// <returns>Random string</returns> public static string RandomString(int size, StringCasing stringCasing, params char[] characters) { if (characters == null || characters.Length == 0) { return(string.Empty); } else { size.MustBeGreaterThan(0); characters.CannotBeNullOrEmpty(); StringBuilder builder = new StringBuilder(); for (int i = 0; i < size; i++) { builder.Append(characters[random.Next(0, characters.Length - 1)]); } return(builder.ToString().ToString(stringCasing)); } }
private static Dictionary<string, string> GetProperty(string name, object value, string prefix, StringCasing keyCasing, string keyDelimiter, bool maskPiiData, BindingFlags bindingAttr) { var returnDict = new Dictionary<string, string>(); var key = $"{prefix}{name}".WithCasing(keyCasing); Type valueType = value != null ? value.GetType() : null; bool isEnumerable = valueType != null && valueType.IsEnumerableType(); if (value == null || value.Equals(valueType.GetDefault())) { // If we dont have a value, add as empty string. returnDict.Add(key, ""); } else if (value.IsDictionary() && !isEnumerable) { foreach (DictionaryEntry item in value as IDictionary) { var itemKey = $"{prefix}{(prefix.Length>0? keyDelimiter : "")}{item.Key}".WithCasing(keyCasing); if (item.Value.IsDictionary()) { returnDict.AddRange(GetFlatDictionary(item.Value, keyCasing, keyDelimiter, itemKey, maskPiiData, bindingAttr)); } else { returnDict.Add(itemKey, item.Value.ToString()); } } } else if (isEnumerable) { // If this is an enumerable, then loop through each item and get its value for the dictionary. IEnumerable vals = value as IEnumerable; var index = 0; foreach (var val in vals) { returnDict.AddRange(val.GetFlatDictionary(keyCasing, keyDelimiter, $"{key}[{index}]", maskPiiData, bindingAttr)); index++; } } else if (valueType.IsSystemType()) { // If this is a plain old system type, then just add straight into the dictionary. returnDict.Add($"{key}", maskPiiData && (valueType.GetPiiDataProperties().Any() || valueType.GetSensitiveInfoProperties().Any()) ? "*****" : value.ToString()); } else { // Otherwise, reflect all properties of this complex type in the next level of the dictionary. returnDict.AddRange(value.GetFlatDictionary(keyCasing, keyDelimiter, key, maskPiiData, bindingAttr)); } return returnDict; }
private static Dictionary<string, string> GetFlatDictionary<T>(this T source, StringCasing keyCasing = StringCasing.Unchanged, string keyDelimiter = ":", string prefix = "", bool maskPiiData = false, BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance) where T : class, new() { var returnDict = new Dictionary<string, string>(); // Return empty dictionary if the source is null. if (source == null) return returnDict; // If this is a dictionary, parse each element one by one. if (source.IsDictionary()) { foreach (DictionaryEntry item in source as IDictionary) { var itemKey = $"{prefix}{(prefix.Length>0? keyDelimiter : "")}{item.Key}".WithCasing(keyCasing); if (item.Value.IsDictionary()) { returnDict.AddRange(GetFlatDictionary(item.Value, keyCasing, keyDelimiter, itemKey, maskPiiData, bindingAttr)); } else if (item.Value.GetType().IsEnumerableType()) { returnDict.AddRange(GetProperty(item.Key.ToString(), item.Value, prefix, keyCasing, keyDelimiter, maskPiiData, bindingAttr)); } else { returnDict.Add(itemKey, item.Value.ToString()); } } } else { // Otherwise, if this is an object, parse each property. var rootItems = source.GetType().GetProperties(bindingAttr); // If the reflected values length is zero, just add now to the dictionary. if (rootItems.Length == 0) { returnDict.Add(prefix, source == null ? String.Empty : source.ToString()); } else { if (!prefix.IsNullOrEmpty()) prefix += keyDelimiter; // Loop through each reflected property in order to build up the returned dictionary key/values. foreach (var item in rootItems) { returnDict.AddRange(GetProperty(item.Name, item.GetValue(source, null), prefix, keyCasing, keyDelimiter, maskPiiData, bindingAttr)); } } } // Return final resulting flat dictionary. return returnDict; }
/// <summary> /// Builds a dictionary of all reflected properties of a JObject, using a delimiter to denoate sub-type properties /// i.e. a class could be reflected as: /// "Prop1" "Value1" /// "Prop2:A" "Value2" /// "Prop2:B" "Value3" /// "Prop2:C" "Value4" /// "Prop3" "true" /// "Prop4" "500" /// </summary> /// <param name="source">The JToken source.</param> /// <param name="keyCasing">The string casing for outputted keys.</param> /// <param name="keyDelimiter">The delimiter.</param> /// <param name="maskPiiData">If set to <c>true</c> mask pii data (properties marked with PersonalData attribute).</param> /// <param name="bindingAttr">The binding attribute.</param> /// <returns>Dictionary<System.String, System.Object>.</returns> public static Dictionary<string, string> AsFlatStringDictionary(this JToken source, StringCasing keyCasing = StringCasing.Unchanged, bool maskPiiData = false, string keyDelimiter = ":", BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance) { JObject inner = source.Root.Value<JObject>(); var tokenDict = inner.ToDictionary(); return tokenDict.GetFlatDictionary(keyCasing, keyDelimiter, String.Empty, maskPiiData, bindingAttr); }
/// <summary> /// Builds a dictionary of all reflected properties of an object, using a delimiter to denoate sub-type properties /// i.e. a class could be reflected as: /// "Prop1" "Value1" /// "Prop2:A" "Value2" /// "Prop2:B" "Value3" /// "Prop2:C" "Value4" /// "Prop3" "true" /// "Prop4" "500" /// </summary> /// <typeparam name="T"></typeparam> /// <param name="source">The source.</param> /// <param name="keyCasing">The string casing for outputted keys.</param> /// <param name="keyDelimiter">The delimiter.</param> /// <param name="maskPiiData">If set to <c>true</c> mask pii data (properties marked with PersonalData attribute).</param> /// <param name="bindingAttr">The binding attribute.</param> /// <returns>Dictionary<System.String, System.Object>.</returns> public static Dictionary<string, string> AsFlatStringDictionary<T>(this T source, StringCasing keyCasing = StringCasing.Unchanged, bool maskPiiData = false, string keyDelimiter = ":", BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance) where T : class, new() { // If the source is not set, return empty. if (source == null) return new Dictionary<string, string>(); if (source is JToken token) { return token.AsFlatStringDictionary(keyCasing, maskPiiData, keyDelimiter, bindingAttr); } // Return final resulting flat dictionary. return source.GetFlatDictionary(keyCasing, keyDelimiter, String.Empty, maskPiiData, bindingAttr); }
// Public members public CaseConverter(StringCasing casing, CasingOptions options = CasingOptions.Default) { this.casing = casing; this.options = options; }
private static Dictionary <string, object> GetFlatDictionary <T>(this T source, StringCasing keyCasing = StringCasing.Unchanged, string keyDelimiter = ":", string prefix = "", bool maskSensitiveData = false, BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance) where T : class, new() { var returnDict = new Dictionary <string, object>(); // Return empty dictionary if the source is null. if (source == null) { return(returnDict); } var rootItems = source.GetType().GetProperties(bindingAttr); // If the reflected values length is zero, just add now to the dictionary. if (rootItems.Length == 0) { returnDict.Add(prefix, source); } else { if (!prefix.IsNullOrEmpty()) { prefix += keyDelimiter; } // Loop through each reflected property in order to build up the returned dictionary key/values. foreach (var item in rootItems) { var value = item.GetValue(source, null); var key = $"{prefix}{item.Name}".WithCasing(keyCasing); var isSysType = item.PropertyType.IsSystemType(); if (value == null || (!isSysType && value.Equals(item.PropertyType.GetDefault()))) { // If we dont have a value, add as empty string. returnDict.Add(key, null); } else if (item.PropertyType.IsEnumerableType()) { // If this is an enumerable, then loop through each item and get its value for the dictionary. IEnumerable vals = value as IEnumerable; var index = 0; foreach (var val in vals) { returnDict.AddRange(val.GetFlatDictionary(keyCasing, keyDelimiter, $"{key}[{index}]", maskSensitiveData, bindingAttr)); index++; } } else if (isSysType) { object maskValue = value; if (maskSensitiveData && item.IsSensitiveOrPersonalData()) { if (item.PropertyType == typeof(string) && (value as string).Length > 0) { // Strings get asterix as mask instead. maskValue = "*****"; } else { // If we should mask pii data, then use default of type or null, rather than the real value. maskValue = item.PropertyType.GetDefault(); } } // If this is a plain old system type, then just add straight into the dictionary. returnDict.Add($"{key}", maskValue); } else { // Otherwise, reflect all properties of this complex type in the next level of the dictionary. returnDict.AddRange(value.GetFlatDictionary(keyCasing, keyDelimiter, key, maskSensitiveData, bindingAttr)); } } } // Return final resulting flat dictionary. return(returnDict); }
/// <summary> /// Builds a dictionary of all reflected properties of an object, using a delimiter to denoate sub-type properties /// i.e. a class could be reflected as: /// "Prop1" "Value1" /// "Prop2:A" "Value2" /// "Prop2:B" "Value3" /// "Prop2:C" "Value4" /// "Prop3" true /// "Prop4" 500 /// </summary> /// <param name="source">The source.</param> /// <param name="keyDelimiter">The delimiter.</param> /// <param name="maskSensitiveData">If set to <c>true</c> mask pii data (properties marked with PersonalData attribute).</param> /// <param name="keyCasing">The string casing for outputted keys.</param> /// <param name="bindingAttr">The binding attribute.</param> /// <returns>Dictionary<System.String, System.Object>.</returns> public static Dictionary <string, object> AsFlatDictionary(this object source, StringCasing keyCasing = StringCasing.Unchanged, bool maskSensitiveData = false, string keyDelimiter = ":", BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance) { // Return final resulting flat dictionary. return(source.GetFlatDictionary(keyCasing, keyDelimiter, string.Empty, maskSensitiveData, bindingAttr)); }
/// <summary>Find mulitple strings between a start delimiter and end delimiter.</summary> /// <param name="source">The source.</param> /// <param name="startDelimiter">The start delimiter.</param> /// <param name="endDelimiter">The end delimiter.</param> /// <param name="casing">The casing of the found keys.</param> /// <returns>List<System.String>.</returns> public static List <string> FindBetweenDelimiters(this string source, string startDelimiter, string endDelimiter, StringCasing casing = StringCasing.Unchanged) { var keys = new List <string>(); var searchIndex = 0; do { var findResult = FindBetweenDelimitersFromIndex(source, searchIndex, startDelimiter, endDelimiter); if (findResult.HasFound == false) { searchIndex = source.Length; } else { keys.Add(findResult.Content.WithCasing(casing)); searchIndex = findResult.EndIndex; } } while (searchIndex < source.Length); return(keys); }