using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; namespace MAX.Core.Helpers; /// /// This is a generic parameters base class used for Dialog Parameters and Navigation Parameters. /// public abstract class ParametersBase : IEnumerable> { private readonly List> _entries = []; /// /// Default constructor. /// protected ParametersBase() { } /// /// Constructs a list of parameters. /// /// Query string to be parsed. protected ParametersBase(string query) { if (!string.IsNullOrWhiteSpace(query)) { int num = query.Length; for (int i = ((query.Length > 0) && (query[0] == '?')) ? 1 : 0; i < num; i++) { int startIndex = i; int num4 = -1; while (i < num) { char ch = query[i]; if (ch == '=') { if (num4 < 0) { num4 = i; } } else if (ch == '&') { break; } i++; } string key = null; string value; if (num4 >= 0) { key = query.Substring(startIndex, num4 - startIndex); value = query.Substring(num4 + 1, i - num4 - 1); } else { value = query.Substring(startIndex, i - startIndex); } if (key != null) { Add(Uri.UnescapeDataString(key), Uri.UnescapeDataString(value)); } } } } /// /// Searches Parameter collection and returns value if Collection contains key. /// Otherwise returns null. /// /// The key for the value to be returned. /// The value of the parameter referenced by the key; otherwise null. public object this[string key] { get { foreach (KeyValuePair entry in _entries) { if (string.Compare(entry.Key, key, StringComparison.Ordinal) == 0) { return entry.Value; } } return null; } } /// /// The count, or number, of parameters in collection. /// public int Count => _entries.Count; /// /// Returns an IEnumerable of the Keys in the collection. /// public IEnumerable Keys => _entries.Select(x => x.Key); /// /// Adds the key and value to the parameters collection. /// /// The key to reference this value in the parameters collection. /// The value of the parameter to store. public void Add(string key, object value) => _entries.Add(new KeyValuePair(key, value)); public void Remove(string key) { _entries.RemoveAll(x => x.Key == key); } public void Update(string key, object value) { _entries.RemoveAll(x => x.Key == key); Add(key, value); } /// /// Checks collection for presence of key. /// /// The key to check in the collection. /// true if key exists; else returns false. public bool ContainsKey(string key) { return _entries.Any(x => string.Compare(x.Key, key, StringComparison.Ordinal) == 0); } /// /// Gets an enumerator for the KeyValuePairs in parameter collection. /// /// Enumerator. public IEnumerator> GetEnumerator() => _entries.GetEnumerator(); /// /// Returns the value of the member referenced by key. /// /// The type of object to be returned. /// The key for the value to be returned. /// Returns a matching parameter of if one exists in the Collection. public T GetValue(string key) => _entries.GetValue(key); /// /// Returns an IEnumerable of all parameters. /// /// The type for the values to be returned. /// The key for the values to be returned. ///Returns a IEnumerable of all the instances of type . public IEnumerable GetValues(string key) => _entries.GetValues(key); /// /// Checks to see if the parameter collection contains the value. /// /// The type for the values to be returned. /// The key for the value to be returned. /// Value of the returned parameter if it exists. public bool TryGetValue(string key, out T value) => _entries.TryGetValue(key, out value); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); /// /// Converts parameter collection to a parameter string. /// /// A string representation of the parameters. public override string ToString() { StringBuilder queryBuilder = new(); if (_entries.Count > 0) { queryBuilder.Append('?'); bool first = true; foreach (KeyValuePair kvp in _entries) { if (!first) { queryBuilder.Append('&'); } else { first = false; } queryBuilder.Append(Uri.EscapeDataString(kvp.Key)); queryBuilder.Append('='); queryBuilder.Append(Uri.EscapeDataString(kvp.Value != null ? kvp.Value.ToString() : "")); } } return queryBuilder.ToString(); } /// /// Adds a collection of parameters to the local parameter list. /// /// An IEnumerable of KeyValuePairs to add to the current parameter list. public void FromParameters(IEnumerable> parameters) => _entries.AddRange(parameters); } public static class ParametersExtensions { /// /// Searches for /// /// The type of the parameter to return /// A collection of parameters to search /// The key of the parameter to find /// A matching value of if it exists [EditorBrowsable(EditorBrowsableState.Never)] public static T GetValue(this IEnumerable> parameters, string key) => (T)GetValue(parameters, key, typeof(T)); /// /// Searches for value referenced by /// /// A collection of parameters to search /// The key of the parameter to find /// The type of the parameter to return /// A matching value of if it exists /// Unable to convert the value of Type [EditorBrowsable(EditorBrowsableState.Never)] public static object GetValue(this IEnumerable> parameters, string key, Type type) { foreach (KeyValuePair kvp in parameters) { if (string.Compare(kvp.Key, key, StringComparison.Ordinal) == 0) { if (TryGetValueInternal(kvp, type, out object value)) { return value; } throw new InvalidCastException($"Unable to convert the value of Type '{kvp.Value.GetType().FullName}' to '{type.FullName}' for the key '{key}' "); } } return GetDefault(type); } /// /// Searches for value referenced by /// /// The type of the parameter to return /// A collection of parameters to search /// The key of the parameter to find /// The value of parameter to return /// Success if value is found; otherwise returns false [EditorBrowsable(EditorBrowsableState.Never)] public static bool TryGetValue(this IEnumerable> parameters, string key, out T value) { Type type = typeof(T); foreach (KeyValuePair kvp in parameters) { if (string.Compare(kvp.Key, key, StringComparison.Ordinal) == 0) { bool success = TryGetValueInternal(kvp, typeof(T), out object valueAsObject); value = (T)valueAsObject; return success; } } value = default; return false; } /// /// Searches for value referenced by /// /// The type of the parameter to return /// A collection of parameters to search /// The key of the parameter to find /// An IEnumerable{T} of all the values referenced by key [EditorBrowsable(EditorBrowsableState.Never)] public static IEnumerable GetValues(this IEnumerable> parameters, string key) { List values = []; Type type = typeof(T); foreach (KeyValuePair kvp in parameters) { if (string.Compare(kvp.Key, key, StringComparison.Ordinal) == 0) { TryGetValueInternal(kvp, type, out object value); values.Add((T)value); } } return values.AsEnumerable(); } private static bool TryGetValueInternal(KeyValuePair kvp, Type type, out object value) { value = GetDefault(type); bool success = false; if (kvp.Value == null) { success = true; } else if (kvp.Value.GetType() == type) { success = true; value = kvp.Value; } else if (type.IsAssignableFrom(kvp.Value.GetType())) { success = true; value = kvp.Value; } else if (type.IsEnum) { string valueAsString = kvp.Value.ToString(); if (Enum.IsDefined(type, valueAsString)) { success = true; value = Enum.Parse(type, valueAsString); } else if (int.TryParse(valueAsString, out int numericValue)) { success = true; value = Enum.ToObject(type, numericValue); } } if (!success && type.GetInterface("System.IConvertible") != null) { success = true; value = System.Convert.ChangeType(kvp.Value, type); } return success; } /// /// Checks to see if key exists in parameter collection /// /// IEnumerable to search /// The key to search the for existence /// true if key exists; false otherwise [EditorBrowsable(EditorBrowsableState.Never)] public static bool ContainsKey(this IEnumerable> parameters, string key) => parameters.Any(x => string.Compare(x.Key, key, StringComparison.Ordinal) == 0); private static object GetDefault(Type type) { if (type.IsValueType) { return Activator.CreateInstance(type); } return null; } }