<commit_before>﻿using System;
using System.Collections.Concurrent;
using static mill5.yocto.Preconditions;
// ReSharper disable InconsistentNaming

namespace mill5.yocto
{
    public class Container
    {
        private readonly ConcurrentBag<Container> _childContainers = new ConcurrentBag<Container>(); 
        private readonly ConcurrentDictionary<Type, IInstanceFactory> _factories =
            new ConcurrentDictionary<Type, IInstanceFactory>();

        private readonly Container _parent;

        private bool _disposed;
        
        private Container()
        {
        }

        protected Container(Container parent)
        {
            CheckIsNotNull(nameof(parent), parent);
            _parent = parent;
        }

        ~Container()
        {
            Dispose(false);
        }

        protected void Dispose(bool dispose)
        {
            if (_disposed)
                return;

            Cleanup.SafeMethod(() =>
            {
                foreach (var c in _childContainers)
                {
                    ((IDisposable)c).Dispose();
                }

                foreach (var f in _factories.Values)
                {
                    (f as IDisposable)?.Dispose();
                }
            });

            _disposed = true;

            if (dispose)
                GC.SuppressFinalize(this);
        }

        public static Container Root { get; } = new Container();

        public Container CreateChild()
        {
            var child = new ChildContainer(this);
            _childContainers.Add(child);
            return child;
        }

        public void Register<T,V>(Lifetime lifetime = Lifetime.MultiInstance) where V : T
        {
            var interfaceType = typeof(T);
            var implementationType = typeof(V);

            _factories.AddOrUpdate(interfaceType,
                t => CreateInstanceFactory(implementationType, lifetime),
                (t, of) =>
                {
                    (of as IDisposable)?.Dispose();
                    return CreateInstanceFactory(implementationType, lifetime);
                });
        }

        public T Resolve<T>() where T : class
        {
            IInstanceFactory instanceFactory;

            if (_factories.TryGetValue(typeof (T), out instanceFactory))
            {
                return instanceFactory.Create<T>();
            }
<commit_msg>Updated Container for Child Removal<commit_after>﻿using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using static mill5.yocto.Preconditions;
// ReSharper disable InconsistentNaming

namespace mill5.yocto
{
    public class Container
    {
        private readonly object _syncLock = new object();
        private readonly List<Container> _children = new List<Container>(); 
   
        private readonly ConcurrentDictionary<Type, IInstanceFactory> _factories =
            new ConcurrentDictionary<Type, IInstanceFactory>();

        private readonly Container _parent;

        private bool _disposed;
        
        private Container()
        {
        }

        protected Container(Container parent)
        {
            CheckIsNotNull(nameof(parent), parent);
            _parent = parent;
        }

        ~Container()
        {
            Dispose(false);
        }

        protected void Dispose(bool dispose)
        {
            if (_disposed)
                return;

            Cleanup.SafeMethod(() =>
            {    
                _parent?.RemoveChild(this);
            
                List<Container> childrenToDispose;

                lock (_syncLock)
                {
                    childrenToDispose = _children.ToList();
                    _children.Clear();
                }

                foreach (var c in childrenToDispose)
                {
                    ((IDisposable)c).Dispose();
                }

                List<IInstanceFactory> factoriesToDispose = _factories.Values.ToList();

                foreach (var f in factoriesToDispose)
                {
                    (f as IDisposable)?.Dispose();
                }

                _factories.Clear();
            });

            _disposed = true;

            if (dispose)
                GC.SuppressFinalize(this);
        }

        public static Container Root { get; } = new Container();

        public Container CreateChild()
        {
            var child = new ChildContainer(this);

            lock (_syncLock)
            {
                _children.Add(child);
            }

            return child;
        }

        private void RemoveChild(Container child)
        {
            lock (_syncLock)
            {
                _children.Remove(child);
            }
        }

        public void Register<T,V>(Lifetime lifetime = Lifetime.MultiInstance) where V : T
        {
            var interfaceType = typeof(T);
            var implementationType = typeof(V);

            _factories.AddOrUpdate(interfaceType,
                t => CreateInstanceFactory(implementationType, lifetime),
                (t, of) =>
                {
                    (of as IDisposable)?.Dispose();
                    return CreateInstanceFactory(implementationType, lifetime);
                });
        }

        public T Resolve<T>() where T : class
        {
            IInstanceFactory instanceFactory;

            if (_factories.TryGetValue(typeof (T), out instanceFactory))
            {
                return instanceFactory.Create<T>();
            }

{'fraction_non_alphanumeric': 0.08184925346285303, 'fraction_numerical': 0.0007195538765965102, 'mean_word_length': 1.4514991181657848, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6932682', 'n_tokens_mistral': 1377, 'n_tokens_neox': 1277, 'n_words': 299}