Reputation: 679
I have the following problem and I currently have a solution using conditional dependency injection. I have read that this is a bad idea, such as here in the SimpleInjector docs. I have read a large number of posts now and have seen various things suggesting using Strategy, Factory patterns, etc. What I am really looking for is some specifics - i.e. an example of some code - about how to solve without conditional injection. I need more that "use a factory". Here's a simplified version of my code. This is in an MVC web app, thus the controllers.
public abstract class QAControllerBase : Controller
{
protected readonly QABusinessLayer _blQA;
public QAControllerBase(QABusinessLayer bl)
{
_blQA = bl;
}
[HttpGet]
public ActionResult PPR(string accession, string site)
{
var m = _blQA.popPPRViewModel(accession);
return View(m);
}
}
public class QASouthController : QAControllerBase
{
public QASouthController([QASouthBinding] QABusinessLayer bl) : base(bl)
{
}
// some actions that are specific to South
}
public class QANorthController : QAControllerBase
{
public QANorthController([QANorthBinding] QABusinessLayer bl) : base(bl)
{
}
// some actions that are specific to North
}
public abstract class QABusinessLayer
{
protected readonly IFullBaseRepo _repo;
public QABusinessLayer(IFullBaseRepo repo)
{
_repo = repo;
}
public abstract PPRViewModel popPPRViewModel(string accession);
protected PPRViewModel DoSomeCommonStuff(PPRViewModel model)
{
...
return model;
}
}
public class SouthBusinessLayer: QABusinessLayer
{
public SouthBusinessLayer([QASouthBinding] IFullBaseRepo repo) : base(repo)
{
}
public override PPRViewModel popPPRViewModel(string accession)
{
var m = new PPRViewModel();
// do some stuff that is specific to South
DoSomeCommonStuff(m);
return m;
}
}
public class NorthBusinessLayer : QABusinessLayer
{
public NorthBusinessLayer([QANorthBinding] IFullBaseRepo repo) : base(repo)
{
}
public override PPRViewModel popPPRViewModel(string accession)
{
var m = new PPRViewModel();
// do some stuff that is specific to North
DoSomeCommonStuff(m);
return m;
}
}
and here is the Ninject binding code that is pertinent:
kernel.Bind<QABusinessLayer>()
.To<SouthBusinessLayer>()
.WhenTargetHas<QASouthBinding>()
.InRequestScope();
kernel.Bind<QABusinessLayer>()
.To<NorthBusinessLayer>()
.WhenTargetHas<QANorthBinding>()
.InRequestScope();
The QASouthBinding and QANorthBinding are just simple attributes. I am not asking for Ninject specific example. Any code sample as to how this might be handled without using conditional or context based injection as I am now.
Upvotes: 0
Views: 451
Reputation: 526
Make your QABusinessLayer class abstract.
Change your startup configuration to:
kernel
.Bind<SouthBusinessLayer>()
.To<SouthBusinessLayer>()
.InRequestScope();
kernel
.Bind<NorthBusinessLayer>()
.To<NorthBusinessLayer>()
.InRequestScope();
Change your controller constructors to accept a concrete business layer type:
public class QANorthController : QAControllerBase
{
public QANorthController(NorthBusinessLayer businessLayer) : base(businessLayer)
{
}
}
public class QASouthController : QAControllerBase
{
public QASouthController(SouthBusinessLayer businessLayer) : base(businessLayer)
{
}
}
Few things:
Upvotes: 1