Can Castle.Windsor do automatic resolution of concrete types
Asked Answered
T

1

6

We are evaluating IoC containers for C# projects, and both Unity and Castle.Windsor are standing out. One thing that I like about Unity (NInject and StructureMap also do this) is that types where it is obvious how to construct them do not have to be registered with the IoC Container.

Is there way to do this in Castle.Windsor? Am I being fair to Castle.Windsor to say that it does not do this? Is there a design reason to deliberately not do this, or is it an oversight, or just not seen as important or useful?

I am aware of container.Register(AllTypes... in Windsor but that's not quite the same thing. It's not entirely automatic, and it's very broad.

To illustrate the point, here are two NUnit tests doing the same thing via Unity and Castle.Windsor. The Castle.Windsor one fails. :

namespace SimpleIocDemo
{
    using NUnit.Framework;
    using Castle.Windsor;
    using Microsoft.Practices.Unity;

    public interface ISomeService
    {
        string DoSomething();
    }

    public class ServiceImplementation : ISomeService
    {
        public string DoSomething()
        {
            return "Hello";
        }
    }

    public class RootObject
    {
        public ISomeService SomeService { get; private set; }

        public RootObject(ISomeService service)
        {
            SomeService = service;
        }
    }

    [TestFixture]
    public class IocTests
    {
        [Test]
        public void UnityResolveTest()
        {
            UnityContainer container = new UnityContainer();
            container.RegisterType<ISomeService, ServiceImplementation>();
            // Root object needs no registration in Unity
            RootObject rootObject = container.Resolve<RootObject>();
            Assert.AreEqual("Hello", rootObject.SomeService.DoSomething());
        }

        [Test]
        public void WindsorResolveTest()
        {
            WindsorContainer container = new WindsorContainer();
            container.AddComponent<ISomeService, ServiceImplementation>();

            // fails with exception "Castle.MicroKernel.ComponentNotFoundException: 
            // No component for supporting the service SimpleIocDemo.RootObject was found"
            // I could add
            // container.AddComponent<RootObject>();
            // but that approach does not scale
            RootObject rootObject = container.Resolve<RootObject>();
            Assert.AreEqual("Hello", rootObject.SomeService.DoSomething());
        }
    }
}
Toughminded answered 23/12, 2009 at 22:6 Comment(1)
possible duplicate of Resolving classes without registering them using Castle WindsorEkaterinodar
D
6

Windsor does not support this out of the box, and this is a deliberate decision. See this answer for more details.

However, the later versions can be really easily extended to support this scenario by lazily registering non-registered components, as they are requested. You'll have to implement ILazyComponentLoader interface, which will take up like 5 lines of code. See here for an example.

Despite that my suggestion in 2018 is the same as it was in 2009 - don't do it unless in very specific scenarios where you have a very good reason to choose this approach over alternatives

Drunken answered 24/12, 2009 at 9:32 Comment(1)
Can you discuss the thinking behind the decision? It seems to have benefit, so you must have seen bigger costs. I would assume that the implicit registrations would have a transient lifestyle, but maybe that assumption just an assumption and it's open to confusion.Toughminded

© 2022 - 2024 — McMap. All rights reserved.