Some tests that I think should compile and pass

Oct 31, 2012 at 11:05 AM

    public class When_registering_same_in_child_and_parent
    {
        readonly IContainer _container;
        readonly IContainer _childContainer;

        public When_registering_same_in_child_and_parent()
        {
            _container = new MetroContainer();
            _container.Register<S, SImpl>(null, new Singleton());
            _container.Register<Dep, DepImpl>(null, new Singleton());

            _childContainer = _container.CreateChildContainer();
            _childContainer.Register<S, SImpl>(null, new Singleton());
            _container.Register<Dependent>();
        }

        [Fact(Skip = "Fails")]
        public void Should_resolve_indepdendently()
        {
            var sc = _container.Resolve<S>();
            var sp = _childContainer.Resolve<S>();
            Assert.False(ReferenceEquals(sc, sp));
        }

        [Fact]
        public void Should_resolve_from_parent_if_not_found_in_child()
        {
            _childContainer.Resolve<Dependent>();
        }


        interface Dep
        {
            void B();
        }

        class DepImpl : Dep
        {
            public void B()
            {
            }
        }

        class Dependent
        {
            readonly Dep _hep;

            public Dependent(Dep hep)
            {
                _hep = hep;
            }

            public Dep Hep
            {
                get { return _hep; }
            }
        }

        interface S
        {
            void A();
        }

        class SImpl : S
        {
            int called = 0;

            public void A()
            {
                called++;
            }
        }
    }

    public class When_working_with_keyed_dependencies
    {
        readonly MetroContainer _container;

        public When_working_with_keyed_dependencies()
        {
            _container = new MetroContainer();
            const string depKey = "keyed";
            _container.RegisterInstance<Dep>(new DepImpl(depKey), depKey);
            
            // no such API:
            //_container.Register<Dependent>(r => new Dependent(r.Resolve<Dep>(depKey)), "dependent");
        }

        [Fact(Skip = "No API to do this")]
        public void Should_be_able_to_key_dependency()
        {
            var childKey = _container.Resolve<Dependent>("dependent").Hep.K;
            Assert.Equal("keyed", childKey);
        }

        interface Dep
        {
            void B();
            string K { get; }
        }

        class DepImpl : Dep
        {
            readonly string _k;

            public DepImpl()
            {
            }

            public DepImpl(string k)
            {
                _k = k;
            }

            public string K
            {
                get { return _k; }
            }

            public void B()
            {
            }
        }

        class Dependent
        {
            readonly Dep _hep;

            public Dependent(Dep hep)
            {
                _hep = hep;
            }

            public Dep Hep
            {
                get { return _hep; }
            }
        }
    }

Oct 31, 2012 at 11:37 AM
Edited Oct 31, 2012 at 11:44 AM

This test causes an infinite loop:

 

    public class When_overriding_with_registration_in_ChildContainer
    {
        IContainer _container;
        public When_overriding_with_registration_in_ChildContainer()
        {
            _container = new MetroContainer();
            _container.Register<S, B>();
        }

        [Fact]
        public void Should_resolve_B()
        {
            var resolved = _childContainer.Resolve<S>();
            Assert.IsType<B>(resolved);
        }

        interface S
        {
        }

        class B : S
        {
            readonly S _inner;

            public B(S inner)
            {
                _inner = inner;
            }
        }
    }
Oct 31, 2012 at 11:40 AM
Edited Oct 31, 2012 at 11:50 AM

Also, the only failure message is 'Could not locate a constructor for XXX' - but if I'm resolving a hierachy I can't tell what service failed to resolve from that hierachy.

Nov 1, 2012 at 3:10 PM

Another one, resolving params:

    public class When_resolving_class_with_params
    {
        readonly MetroContainer _container;

        public When_resolving_class_with_params()
        {
            _container = new MetroContainer();
            _container.Register<B>();
            _container.Register<A>();

        }

        [Fact(Skip = "This test fails with: 'Could not locate a constructor for System.Int32'")]
        public void Should_resolve_A_easily()
        {
            _container.Resolve<A>();
        }

        class B
        {
        }

        class A
        {
            public A(params B[] bs)
            {
            }
        }
    }

Coordinator
Nov 1, 2012 at 8:04 PM

henke,

 

Thanks so much for putting all this effort in! Something has been needling me about the silly way I'm firing exceptions to say' no, I couldn't resolve' this, and have been contemplating spinning up an experimental branch and re-working the internals. I'm probably going to do that before I do any more work on metroioc, but rest assured I'll be looking at all the bugs you have been raising - keep 'em coming!

 

cheers,

Ian

 

Nov 2, 2012 at 10:08 AM

This test case shows a broken resolve that should throw exception but goes into an infinite loop instead:

    public class When_resolving_semi_primitive
    {
        IContainer _container;

        public When_resolving_semi_primitive()
        {
            _container = new MetroContainer();
            _container.Register<Svc>();
        }

        [Fact(Skip = "Broken - test runner aborts test")]
        public void Should_complain_not_abort()
        {
            Assert.Throws<ResolutionException>(
                () => _container.Resolve<Svc>());
        }

        class Svc
        {
            public Svc(Uri parm)
            {
            }
        }
    }

Nov 2, 2012 at 10:15 AM

Sometimes the resolve is context dependent, on a static variable, such as CultureInfo, so I want to be able to resolve Func<T>.

    public class When_resolving_funcs
    {
        readonly IContainer _container;
        bool _wasResolved;

        public When_resolving_funcs()
        {
            _container = new MetroContainer();
            _container.Register(c =>
                    {
                        _wasResolved = true;
                        return new Serva(c.Resolve<Serv>());
                    });
        }

        [Fact]
        public void Should_successfully_resolve_Serv()
        {
            Assert.NotNull(_container.Resolve<Serv>());
        }

        [Fact(Skip = "Fails with 'Could not locate a constructor for System.Int32'")]
        public void Should_automatically_give_me_resolve_func()
        {
            Assert.NotNull(_container.Resolve<Func<Serv>>());
        }

        [Fact]
        public void It_should_call_func()
        {
            _container.Resolve<Serva>();
            Assert.True(_wasResolved);
        }

        [Fact]
        public void Should_allow_me_to_register_Func_in_lieu_of_core_functionality()
        {
            _container.RegisterInstance<Func<X>>(() => new X());
            var resolve = _container.Resolve<Func<X>>();
            Assert.NotNull(resolve);
            Assert.IsType<Func<X>>(resolve);
            Assert.NotNull(resolve());
        }

        class Serv
        {
            public Serv()
            {
                Debug.WriteLine("serv created");
            }
        }

        class Serva
        {
            readonly Serv _dep;

            public Serva(Serv dep)
            {
                _dep = dep;
            }
        }

        class X
        {
        }
    }

Nov 2, 2012 at 10:26 AM

I use explicit interfaces to keep objects clear, so I need to forward interfaces some times, when implementation details of interfaces intersect the data structures I need to keep those interfaces working:

    public class When_forwarding_interface_should_respect_lifestyle
    {
        IContainer _container;

        public When_forwarding_interface_should_respect_lifestyle()
        {
            _container = new MetroContainer();
            _container.Register<Svc>(null, new Singleton());

            // or: _container.ForwardType<A, Svc>();
            _container.Register<A, Svc>();
        }

        [Fact]
        public void Should_respect_singleton()
        {
            Assert.True(ReferenceEquals(
                _container.Resolve<Svc>(),
                _container.Resolve<A>()));
        }

        interface A
        {
        }

        class Svc
            : A
        {
        }
    }

Nov 2, 2012 at 10:28 AM

I created a new IRegistration (that's the lambda method you see in a previous test). However, when I create a child container, that container is not the same as the one I passed to the IRegistration instance - so I need a way to get the call context's container that was invoked with Resolve<T>(), INSIDE of my IRegistration.

Nov 2, 2012 at 10:38 AM

I would also like the ability to pass in parameters at runtime, into the Resolve<T>( ... ) call.

Nov 2, 2012 at 10:54 AM

Hi Ian,

Thanks for the software. I think you are the only one who has an IoC container for Metro at this point, so bravo to the release. The container has made my life easier despite what it might seem from my above writing - it's because I think the container will benefit from some improvements.

Cheers,
Henrik

IanRandall wrote:

henke,

Thanks so much for putting all this effort in! Something has been needling me about the silly way I'm firing exceptions to say' no, I couldn't resolve' this, and have been contemplating spinning up an experimental branch and re-working the internals. I'm probably going to do that before I do any more work on metroioc, but rest assured I'll be looking at all the bugs you have been raising - keep 'em coming!

cheers,
Ian