using System; using System.Collections; using System.Collections.Generic; namespace Config.Net.Core.Box { class CollectionResultBox : ResultBox { private readonly ResultBox _elementResultBox; private string? _basePath; private DynamicReader? _reader; public CollectionResultBox(string name, ResultBox elementBox) : base(name, elementBox.ResultType, null) { _elementResultBox = elementBox; } public ResultBox ElementResultBox => _elementResultBox; public bool IsInitialised { get; private set; } public IEnumerable? CollectionInstance { get; private set; } public void Initialise(string? basePath, int length, DynamicReader reader) { _basePath = basePath; _reader = reader; CollectionInstance = CreateGenericEnumerable(length); IsInitialised = true; } private IEnumerable? CreateGenericEnumerable(int count) { Type t = typeof(DynamicEnumerable<>); t = t.MakeGenericType(ResultType); IEnumerable? instance = (IEnumerable?)Activator.CreateInstance(t, count, this); return instance; } private object? ReadAt(int index) { return _reader?.Read(ElementResultBox, index); } private class DynamicEnumerable : IEnumerable { private readonly int _count; private readonly CollectionResultBox _parent; public DynamicEnumerable(int count, CollectionResultBox parent) { _count = count; _parent = parent; } public IEnumerator GetEnumerator() { return new DynamicEnumerator(_count, _parent); } IEnumerator IEnumerable.GetEnumerator() { return new DynamicEnumerator(_count, _parent); } } private class DynamicEnumerator : IEnumerator { private int _index = -1; private readonly int _count; private readonly CollectionResultBox _parent; private T? _current; public DynamicEnumerator(int count, CollectionResultBox parent) { _count = count; _parent = parent; } #pragma warning disable CS8603 // Possible null reference return. public T Current => _current ?? default(T); object IEnumerator.Current => _current; #pragma warning restore CS8603 // Possible null reference return. public void Dispose() { } public bool MoveNext() { _index += 1; _current = (T?)_parent.ReadAt(_index); return _index < _count; } public void Reset() { _index = -1; } } } }