123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- #pragma warning disable CS8603 // Possible null reference return.
- #pragma warning disable CS8601 // Possible null reference assignment.
- namespace EasyDevCore.Common.Wrapper
- {
- /// <summary>
- /// Defines common methods for INameValueList and IReadOnlyNameValueList.
- /// </summary>
- public interface INameValueListBase<TValue>
- {
- /// <summary>
- /// Returns the first Value of the given Name if one exists, otherwise null or default value.
- /// </summary>
- TValue FirstOrDefault(string name);
- /// <summary>
- /// Gets the first Value of the given Name, if one exists.
- /// </summary>
- /// <returns>true if any item of the given name is found, otherwise false.</returns>
- bool TryGetFirst(string name, out TValue value);
- /// <summary>
- /// Gets all Values of the given Name.
- /// </summary>
- IEnumerable<TValue> GetAll(string name);
- /// <summary>
- /// True if any items with the given Name exist.
- /// </summary>
- bool Contains(string name);
- /// <summary>
- /// True if any item with the given Name and Value exists.
- /// </summary>
- bool Contains(string name, TValue value);
- }
- /// <summary>
- /// Defines an ordered collection of Name/Value pairs where duplicate names are allowed but aren't typical.
- /// </summary>
- public interface INameValueList<TValue> : IList<(string Name, TValue Value)>, INameValueListBase<TValue>
- {
- /// <summary>
- /// Adds a new Name/Value pair.
- /// </summary>
- void Add(string name, TValue value);
- /// <summary>
- /// Replaces the first occurrence of the given Name with the given Value and removes any others,
- /// or adds a new Name/Value pair if none exist.
- /// </summary>
- void AddOrReplace(string name, TValue value);
- /// <summary>
- /// Removes all items of the given Name.
- /// </summary>
- /// <returns>true if any item of the given name is found, otherwise false.</returns>
- bool Remove(string name);
- }
- /// <summary>
- /// Defines a read-only ordered collection of Name/Value pairs where duplicate names are allowed but aren't typical.
- /// </summary>
- public interface IReadOnlyNameValueList<TValue> : IReadOnlyList<(string Name, TValue Value)>, INameValueListBase<TValue>
- {
- }
- /// <summary>
- /// An ordered collection of Name/Value pairs where duplicate names are allowed but aren't typical.
- /// Useful for things where a dictionary would work great if not for those pesky edge cases (headers, cookies, etc).
- /// </summary>
- public class NameValueList<TValue> : List<(string Name, TValue Value)>, INameValueList<TValue>, IReadOnlyNameValueList<TValue>
- {
- private StringComparison _ComparisonType;
- /// <summary>
- /// Instantiates a new empty NameValueList.
- /// </summary>
- public NameValueList(StringComparison comparisonType)
- {
- _ComparisonType = comparisonType;
- }
- /// <summary>
- /// Instantiates a new NameValueList with the Name/Value pairs provided.
- /// </summary>
- public NameValueList(IEnumerable<(string Name, TValue Value)> items, StringComparison comparisonType)
- {
- _ComparisonType = comparisonType;
- AddRange(items);
- }
- /// <inheritdoc />
- public void Add(string name, TValue value) => Add((name, value));
- /// <inheritdoc />
- public void AddOrReplace(string name, TValue value)
- {
- var i = 0;
- var replaced = false;
- while (i < this.Count)
- {
- if (!string.Equals(this[i].Name, name, _ComparisonType))
- i++;
- else if (replaced)
- this.RemoveAt(i);
- else
- {
- this[i] = (name, value);
- replaced = true;
- i++;
- }
- }
- if (!replaced)
- this.Add(name, value);
- }
- /// <inheritdoc />
- public bool Remove(string name) => RemoveAll(x => string.Equals(x.Name, name, _ComparisonType)) > 0;
- /// <inheritdoc />
- public TValue FirstOrDefault(string name) => GetAll(name).FirstOrDefault();
- /// <inheritdoc />
- public bool TryGetFirst(string name, out TValue value)
- {
- foreach (var v in GetAll(name))
- {
- value = v;
- return true;
- }
- value = default;
- return false;
- }
- /// <inheritdoc />
- public IEnumerable<TValue> GetAll(string name) => this
- .Where(x => string.Equals(x.Name, name, _ComparisonType))
- .Select(x => x.Value);
- /// <inheritdoc />
- public bool Contains(string name) => this.Any(x => string.Equals(x.Name, name, _ComparisonType));
- /// <inheritdoc />
- public bool Contains(string name, TValue value) => Contains((name, value));
- }
- }
|