7
votes

I looked at this and it answers half my questions:

Castle Windsor: Register class with internal constructor?

But can you use Windsor to use internal constructors/class along with dependency injection? (so constructor parameters get injected too)? I'd like to keep the class/constructor internal to allow for optimal encapsulation (these classes should not be exposed to the public).

I need this to support Silverlight, so I don't think this is an option:

Castle Windsor: How to register internal implementations

Thanks.

1
IMHO this is not optimal encapsulation. If you need Windsor to access these classes then they are not properly encapsulated. Either write a facade or make them public.Mauricio Scheffer
I'm not sure I understand. I have a service public interface IMyService. I do not want the implementation to be visible to the consumers of the service. So I have the implementation internal class MyService : IMyService. How does this scenario not represent optimal encapsulation?Jeff
you're confusing internal types with interfaces. These are orthogonal issues.Mauricio Scheffer
I don't think I'm confusing the two... I have public interface IMyService and internal class MyService : IMyService. What am I confusing here?Jeff

1 Answers

8
votes

This may not be a satisfying answer, but it is a best practice to make all classes that you need to instantiate via Castle public, with public constructors. Your design should allow a downstream dependency to instantiate your objects without relying on Castle or InternalsVisibleTo.

To your question, Castle will only search for public constructors to instantiate an object. I don't believe there is a way to make it search for internal or private constructors. However, if your class is internal, you can make your internal constructors public without changing the encapsulation at all. See the following test case:

[TestFixture]
public class InternalConstructorTests
{
    [Test]
    public void Test()
    {
        using (var container = new WindsorContainer())
        {
            container.Register(
                Component.For<IFoo>().ImplementedBy<Foo>(),
                Component.For<IBar>().ImplementedBy<Bar>(),
                Component.For<IBaz>().ImplementedBy<Baz>()
                );
            // fails because Castle can't find, and won't call, the internal constructor
            Assert.Throws<ComponentActivatorException>(()=>container.Resolve<IFoo>());
            // passes because the Baz constructor is public, but the "real" encapsulation
            // level is the same because the class is internal, effectively making the 
            // public constructor internal as well
            container.Resolve<IBaz>();
        }
    }
}
internal interface IBar{}
internal class Bar : IBar{}
internal interface IFoo{}
internal class Foo : IFoo
{
    internal Foo(IBar bar)
    {
    }
}
internal interface IBaz { }
internal class Baz : IBaz
{
    public Baz(IBar bar)
    {
    }
}