We have a web api project which references a library that in turn is shared between many different systems.
The library exposes a "RegisterDependancies(IWindsorContainer container)" function that when called will register all of the dependencies for that particular library.
So when the web api application starts it does its own registrations and then calls the shared library, something like the following pseudo code :
public void SetupWindsor(){
IWindsorContainer container = new WindsorContainer();
container.Register(Component.For<iFoo>().ImplementedBy<Foo>());
SharedLibrary.RegisterDependancies(container);
}
The shared library function looks a bit like this:
public void RegisterDependancies(IWindsorContainer container)
{
container.Register(Component.For<iBar>().ImplementedBy<Bar>());
//In this instance Bar is internal so could not be registered by the api project.
}
We now want the web api project to use the PerWebRequest lifestyle but other systems may want to use a different lifestyle (This decision will be down to whoever writes the client app - the shared library will be used in console and windows apps - so perwebrequest isn't suitable for them to use)
We want to change the RegisterDependancies method so that we can pass in the lifestyle.
Is it possible to do this with the PerWebRequest lifestyle? A few of us had a look and couldnt see how to do it - despite having done similar without issues with unity in the past.
We are either looking for a way to resolve the problem in the way described, or if there is a better way to approach this that would also be helpful.
Edit to clarify, the shared library defines the interface IBar as public but the class Bar as internal so the API cannot do the registration - unless there is some magic in windsor that I am unaware of.
Let's examine that design decision for a moment. While no external callers can create a
Barobject, they can create anIBarobject:There can be various reasons to keep the
Barclassinternal, but since you can already run code like the above, why not simply let the shared library expose a factory?That'd be much simpler and decouple the shared library from the container. In general, that's the best advice I can give regarding Dependency Injection and reusable libraries: Use Dependency Injection patterns, not containers. See my article DI-Friendly Library for more details.
If you still want to use a DI Container in your host project (e.g. Wep API project), you can register
IBaragainst that static factory method.Internal classes
There are legitimate reasons why one would want to keep some classes
internal, but I often see code bases where classes areinternalfor no apparent reason. My experience with decades of C# code is that the cases where classes areinternalfor no good reason far outweighs the cases where there's a good reason.Does
Barreally have to be internal? Why?From the OP it's clear that
IBaris implemented byBar. This could be an artefact of reducing the question to essentials (good job doing that, BTW), but I get the impression thatBaris the only class that implementsIBar. Is that the case?If so, the
Barclass must expose the methods defined byIBar. Thus, the API of the class is already public, so why hide the class? The only thing hidden, then, is the constructor...The perfect storm
Sometimes when I give advice like the above, I'm met with a response that that's not what the question was about. The question is about how to change Castle Windsor lifestyles (which, BTW, you can).
This question, on the other hand, is almost the perfect (little) storm that illustrates why reusable libraries shouldn't depend on DI Containers:
This complicates things - hence the question here on Stack Overflow.
My best advice is to keep things simple. Removing the dependency on Castle Windsor will make library development and reuse easier, not harder.
It'd be even easier to use the library if you make most library classes public.