Andrew Stephens
Andrew Stephens

Reputation: 10193

Castle Windsor (or any IoC framework) and internal dependencies

I'm having some trouble getting my head around using dependency injection with internal types. Although I've been using Castle Windsor for a few years, I've never really had to think about visibility too much, so everything typically ended up being public (partly to keep Windsor happy, and partly to facilitate easier mocking in unit tests). However I now have a requirement to design an API.

I appreciate the following example isn't great, but is meant to illustrate the scenario of exposing a type with dependencies that shouldn't be publicly accessible.

Let's say my API tier exposes a GetCustomer() method. This returns a Customer class that exposes a SendEmail() method, which utilises a MailService class to achieve the emailing.

I want to inject the MailService into the Customer, but I don't want the MailService to be accessible to consumers of the API. I believe it can't be internal, as you can't pass an internal type to a public constructor. It therefore makes sense to make the Customer ctr internal (as only the BLL should create them), but Windsor complains because registered types must have a public ctr.

I feel I'm missing something fundamental with all this. How would I go about designing something like this? I guess one solution is interfaces, but it somehow doesn't feel right creating an interface for every internal type when there will (usually) only ever be one implementation.

Upvotes: 1

Views: 146

Answers (1)

Steven
Steven

Reputation: 172606

I believe it can't be internal, as you can't pass an internal type to a public constructor.

C# will not compile your class if the public constructor depends on an internal type, which is obvious. But you actually can pass an internal implementation to a public constructor, as long as the interface the constructor depends on is public as well.

It therefore makes sense to make the Customer ctr internal

That's not a good reason to make the constructor internal, because this will work just fine, but if you're building a reusable library, making constructors internal is very valid, because once you published your library, changing a public constructor is a breaking change. So making it internal is a good way allow the library to change and grow in the future.

but Windsor complains because registered types must have a public ctr.

Most DI libraries allow overriding the default constructor resolution behavior, as does Castle Windsor.

Because you are creating a reusable library, I urge you to read Mark Seemann's DI Friendly Library article.

Upvotes: 1

Related Questions