views:

100

answers:

1

This registration works when all the implementations of IService are public:

AllTypes
    .Of<IService>()
    .FromAssembly(GetType().Assembly)
    .WithService.FirstInterface()

For example:

public interface IService {}
public interface ISomeService : IService {}
public class SomeService : ISomeService {}

Resolving ISomeService returns an instance of SomeService.

But if the SomeService class is internal, the container throws an exception that states that ISomeService is not registered.

So is there any way to register internal implementations for public interfaces?

A: 

UPDATE2: While I consider this not a good idea, you can achieve that with the following code.

AllTypes.FromAssembly(GetType().Assembly)
    .IncludeNonPublicTypes()
    .BasedOn<IService>()
    .WithService.FirstInterface();


UPDATE: This is a very logical behavior and I would consider this a bug if it was otherwise. AllTypes exposes only public type, because it assumes, if you made your type internal, you did it for a reason, and if it exposed it it could be a security issue.

When you register type explicitly on the other hand, it works because Windsor assumes, since you're explicitly asking it to use an internal type, you know better.


Krzysztof Koźmic
I don't understand. If I use Component.For<IPublicInterface>.ImplementedBy<InternalImplementation>(), everything works ok. It's only when I use AllTypes that I have this problem. Note also that the registration in this case is done in the same assembly as the implementation. Shouldn't these two facts be enough for the kernel to find the internal types?
shovavnik
It also seems odd to call Castle a friendly assembly.
shovavnik
When you register with Component.For you're in context of the assembly where this code is. AllTypes.Of execute in the context of Castle assembly.
Krzysztof Koźmic
Doesn't it make more sense for the context to be the assembly in the FromAssembly() specifier, regardless of whether it's public or internal? If the code that does the registration can see the internal members, why does castle assume it should work any different in an AllTypes registration and a Component registration?
shovavnik
Not really. The places where the service is going to be used, may not be in the same assembly. They can't instantiate the internal type, so if Windsor exposed it to them, it would be a security issue.Anyway - why make the type internal? And if you want to keep it that way, be explicit and call IncludeNonPublicTypes()
Krzysztof Koźmic
IncludeNonPublicTypes() is what I was looking for. It works. But you reply gives me pause to consider if what I'm doing is wrong. I have to say I don't understand the security issue, or more exactly, why this isn't just simple encapsulation. I want Windsor to instantiate an internal type and pass that type to any other service that depends on the public interface. This is very standard OO, just using the container to wire them all up. So why is this an issue?
shovavnik
than why do you make that type internal in the first place, if you want to use it in other assemblies anyway? I generally dislike internal and use it almost exclusively for helper classes that I never want to expose to the outside world.
Krzysztof Koźmic

related questions