How to add a new constructor that does not violate the OOP principle?

I have a wrapper class to work with IAsyncCursorthat returnsIEnumerable<TResult>

My program can accept items from two places:

IEnumerable<TResult> GetItems()
{
    List<TResult> fromA = fromA();
    IEnumerable<TResult> fromB = fromB();

    var result = fromA.Concat(fromB).ToList();
    return result;
}

But I do not want to keep resultin memory, because it is too expensive.

I would like to change my return result GetItems()to return ResultCollectionand be able to callDispose()

So, I need to change the result from the methods fromA()and fromB()to return ResultCollection, for example, the following

ResultCollection<TResult> GetItems()
{
    ResultCollection<TResult> fromA = fromA(); // wrap List<TResult> to ResultCollection
    ResultCollection<TResult> fromB = fromB(); // return collection that I can dispose when I need

    return new ResultCollection<TResult>(fromA.Concat(fromB).ToList());
}

How do I change mine ResultCollectionto store the constructor List? I need this new class to comply with all principles OOPand SOLID.

I don't need to have only one constructor inside ResultCollection, like this

public ResultCollection(IList<TResult> list)
{
    _list = list;
}
+4
2

IDisposableEnumerable, :

public interface IDisposableEnumerable<T> : IEnumerable<T>, IDisposable
{

}

DeferredResultCollection .

, IEnumerable<T>. EnumerableWrapper, Dispose.

, ( ) IDisposableEnumerable , Composite Pattern, CompositeDisposableEnumerable.

, DeferredResultCollection , .

Reactive Extensions for.NET, , , , .

UPDATE:

EnumerableWrapper CompositeDisposableEnumerable:

public class EnumerableWrapper<T> : IDisposableEnumerable<T>
{
    private readonly IEnumerable<T> m_Enumerable;

    public EnumerableWrapper(IEnumerable<T> enumerable)
    {
        m_Enumerable = enumerable;
    }

    public void Dispose()
    {

    }

    public IEnumerator<T> GetEnumerator()
    {
        return m_Enumerable.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable) m_Enumerable).GetEnumerator();
    }
}

public class CompositeDisposableEnumerable<T> : IDisposableEnumerable<T>
{
    private readonly IDisposableEnumerable<T>[] m_DisposableEnumerables;

    public CompositeDisposableEnumerable(params IDisposableEnumerable<T>[] disposable_enumerables)
    {
        m_DisposableEnumerables = disposable_enumerables;
    }

    public IEnumerator<T> GetEnumerator()
    {
        foreach (var disposable_enumerable in m_DisposableEnumerables)
        {
            foreach (var item in disposable_enumerable)
                yield return item;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public void Dispose()
    {
        foreach (var disposable_enumerable in m_DisposableEnumerables)
            disposable_enumerable.Dispose();
    }
}

UPDATE:

:

public IDisposableEnumerable<T> GetItems<T>()
{
    List<T> collection1 = ....;

    DeferredResultCollection<T> collection2 = new DeferredResultCollection<T> (async_cursor);

    return new CompositeDisposableEnumerable<T>(new EnumerableWrapper<T>(collection1), collection2);

}

:

using(var items = GetItems<string>())
{
    //do something with items
} //This will invoke `Dispose` which will be propagated finally to DeferredResultCollection.Dispose and thus to IAsyncCursor.Dispose
+1

GetItems DeferredResultCollection. IEnumerable<...>.

return fromA.Concat(fromB);

.

DeferredResultCollection API, . IEnumerable<...> .

DeferredResultCollection . .


:

  • DeferredResultCollection
  • :

.

public static IEnumerable<TResult> CreateDeferredIEnumerable(IAsyncCursor<TResult> _asyncCursor)
{
    if (_asyncCursor != null)
    {
        using (_asyncCursor) { //This is key
         for (; _asyncCursor.MoveNextAsync().Result;)
         {
             foreach (var result in _asyncCursor.Current)
             {
                 yield return result;
             }
         }
        } //The Dispose is always triggered!
    }
}

, :

1. ((IDisposable)CreateDeferredIEnumerable(...)).Dispose();
1. ((IDisposable)CreateDeferredIEnumerable(...).GetEnumerator()).Dispose();
2. CreateDeferredIEnumerable(...).ToList();
3. CreateDeferredIEnumerable(...).Take(1).ToList();
4. foreach (var x in CreateDeferredIEnumerable(...)) break;

concat, :

tatic IEnumerable<TSource> ConcatIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second)
{
    using (first as IDisposable) {
    using (secondas IDisposable) {
    foreach (TSource iteratorVariable0 in first)
    {
        yield return iteratorVariable0;
    }
    foreach (TSource iteratorVariable1 in second)
    {
        yield return iteratorVariable1;
    }
    }
    }
}

, , . , , .

+2

Source: https://habr.com/ru/post/1616950/


All Articles