I might be describing this wrong, but here's my dilemma, I have a series of interfaces, like IBreadcrumbRetriever
. Their implementations are radically different depending where on my site they are, which I'm using HttpContext.Current.Request.Path
to determine.
So inside my concrete class I'm right now have several if statements that determine what items to return (for simplicity sake, let's say List<string>
). This is a code smell to me.
What I would really like, is somehow, and I feel as if IoC and Castle Windsor can help me out here, is determine if the user hitting the page meetings the certain conditional and bind the correct container to that. So I'd have something like
if (HttpContext.Current.Request.Path == some condition)
IBreadcrumbRetriever is ImplementedBy IsInProductAreaRetriever
Is this a good idea? If so how would I do this? Or do I create like a breadcrumb factory class and use the ".DependsOn(HttpContext.Current.Request.Path)
" extension to achieve what I'm doing?
It depends on whether your app architecture is fit for dependency injection.
Not familiar with Castle Windsor but generally speaking, if a dependency can't be resolved at the composition root (app startup) I see nothing wrong with injecting a factory implementation that works with current http context.
For example, in an ASP.NET application your composition root would be in global.asax
. There you could bind some IBreadcrumbRetrieverFactory
to a BreadcrumbRetrieverFactory
implementation. new
ing up classes that aren't part of the core framework (and a few that are) is generally a sign of a missed DI opportunity (and of tight coupling).
IoC containers and DI aren't a silver bullet: Depencency Injection is merely a design pattern (think constructor injection, constructors that only assign private readonly
fields - the type's dependencies), and IoC containers (all of them) are nothing but tools to facilitate the wiring-up of dependencies with concrete implementations. With that in mind, there's nothing Castle Windsor will do that you can't achieve with poor man's DI: the key is all about pushing the instantiation of dependencies as early as possible - namely, at the application startup, the composition root.
When a dependency is "dynamic", like, when there's a logic that determines whether the implementation of ISmurf
should be HappySmurf
or GrumpySmurf
, the best thing to do is, IMHO, to inject a ISmurfFactory
dependency instead of a ISmurf
, and push the factory's wiring-up to the composition root.