using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace Masuit.Tools.Dynamics.Implementation; internal static class Arguments { public static INamedEnumerable FromT(IEnumerable arguments, IEnumerable names) { return new NamedEnumerable(arguments, names); } public static INamedEnumerable From(IEnumerable arguments, IEnumerable names) { return new NamedEnumerable(arguments, names); } private class NamedEnumerable : INamedEnumerable { private readonly IEnumerable _arguments; private readonly IEnumerable _names; public NamedEnumerable(IEnumerable arguments, IEnumerable names) { if (arguments == null) { throw new ArgumentNullException(nameof(arguments)); } if (names == null) { throw new ArgumentNullException(nameof(names)); } var list = arguments.ToList(); var nameList = names.ToList(); if (list.Count < nameList.Count) { throw new ArgumentException("arguments.Count() < names.Count()"); } _arguments = list; _names = nameList; } IEnumerator IEnumerable.GetEnumerator() { return _arguments.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return _arguments.GetEnumerator(); } IEnumerable INamedEnumerable.Positional => _arguments.Take(_arguments.Count() - _names.Count()); IDictionary INamedEnumerable.Named => new Named(_arguments, _names); private class Named : IDictionary { private readonly IEnumerable _arguments; private readonly IEnumerable _names; private ICollection _argumentsCollection; private ICollection _namesCollection; public Named(IEnumerable arguments, IEnumerable names) { var args = arguments as IList ?? arguments.ToList(); var ns = names as IList ?? names.ToList(); _arguments = args.Skip(args.Count - ns.Count()); _names = ns; } private IEnumerable> MakeEnumerable() { return _arguments.Zip(_names, (arg, name) => new KeyValuePair(name, arg)); } IEnumerator> IEnumerable>.GetEnumerator() { return MakeEnumerable().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return MakeEnumerable().GetEnumerator(); } void ICollection>.Add(KeyValuePair item) { throw new NotImplementedException(); } void ICollection>.Clear() { throw new NotImplementedException(); } bool ICollection>.Contains(KeyValuePair item) { return MakeEnumerable().Contains(item); } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { throw new NotImplementedException(); } bool ICollection>.Remove(KeyValuePair item) { throw new NotImplementedException(); } int ICollection>.Count => _names.Count(); bool ICollection>.IsReadOnly => true; bool IDictionary.ContainsKey(string key) { return _names.Contains(key); } void IDictionary.Add(string key, T value) { throw new NotImplementedException(); } bool IDictionary.Remove(string key) { throw new NotImplementedException(); } bool IDictionary.TryGetValue(string key, out T value) { var pair = MakeEnumerable().FirstOrDefault(kv => kv.Key == key); value = pair.Value; return pair.Key != null; } T IDictionary.this[string key] { get => MakeEnumerable().Where(kv => kv.Key == key).Select(kv => kv.Value).FirstOrDefault(); set => throw new NotImplementedException(); } ICollection IDictionary.Keys => _namesCollection ??= _names as ICollection ?? _names.ToArray(); ICollection IDictionary.Values => _argumentsCollection ??= _arguments as ICollection ?? _arguments.ToArray(); } } public static INamedEnumerable Empty() { return From(Enumerable.Empty(), Enumerable.Empty()); } }