ninject / Ninject

the ninja of .net dependency injectors
http://ninject.org/
Other
2.67k stars 531 forks source link

How to get kernel back after Rebind ? #382

Open artkpv opened 3 years ago

artkpv commented 3 years ago

Hello,

In our project we run many nunit tests. We use one Ninject kernel per a test fixture. Some tests do Rebind(). Now in our CI tool with Release configuration we see some tests fail which we can not reproduce locally in Release or Debug. This seems to be due to the order in which tests executed. To get back original binding that was before Rebind we save bindings to a local list and then do Bind again. Our tests fail because an object does not have items it expected to have. We bind this object with SingletonScope. The data is cached in the object with SingletonScope but should be cleared in each SetUp.

Questions:

  1. Will Ninject reconstruct this object bound with SingletonScope when we Rebind our other object?
  2. Is it proper way to get bindings back after Rebind

        public new IBindingToSyntax<T> Rebind<T>()
        {
            AddToRebindBack(typeof(T));
            return base.Rebind<T>();
        }

        public new IBindingToSyntax<T1, T2> Rebind<T1, T2>() 
        {
            AddToRebindBack(typeof(T1),typeof(T2));
            return base.Rebind<T1, T2>();
        }

        public new IBindingToSyntax<T1, T2, T3> Rebind<T1, T2, T3>() 
        {
            AddToRebindBack(typeof(T1), typeof(T2), typeof(T3));
            return base.Rebind<T1, T2, T3>();
        }

        public new IBindingToSyntax<T1, T2, T3, T4> Rebind<T1, T2, T3, T4>() 
        {
            AddToRebindBack(typeof(T1), typeof(T2), typeof(T3), typeof(T4));
            return base.Rebind<T1, T2, T3, T4>();
        }

        public new IBindingToSyntax<object> Rebind(params Type[] services)
        {
            AddToRebindBack(services);
            return base.Rebind(services);
        }

        public void RebindBack()
        {
            while (_toRebindBack.Any())
            {
                if (_toRebindBack.TryTake(out IBinding b))
                {
                    Unbind(b.Service);
                    AddBinding(b);
                }
            }
        }

        private void AddToRebindBack(params Type[] services)
        {
            foreach (Type service in services)
            {
                foreach (var b in GetBindings(service))
                {
                    _toRebindBack.Add(b);
                }
            }
        }

In our base class for all TestFixtures:

       [OneTimeSetup]
       public void Onetime()
       {
                 /// Here we create kernel
       }

        [SetUp]
        public void SetUp()
        {
            _testFactory.RebindBack();
            bool result = _testFactory.TryReinitialize(); // Here we remove data from objests that are SignletomScope