I have set up Castle Windsor IoC in MVC. I've read through the tutorials, and have done this:
public class HomeController : Controller
{
/////////////////////////////////////////////////////////////
// Attributes
public ISearchService SearchService { get; set; }
public IFeedbackService FeedbackService { get; set; }
The HomeController is responsible for handling searches and storing feedback, so the HomeController has two service references which are created by the IoC.
This isn't really what I want. I don't want to have to construct two service for each request on the Home controller, when most of the time they will not be needed. I want to construct them in the action function, when I know for sure they will be needed.
Previously, I used Microsoft Unity and there was a lot of ServiceLocator.Resolve<thing>()
in my action functions. This is a real pain when it comes to testing, and I have read it is unadvisable (and anti-pattern).
My wish is for this:
[HttpPost]
public ActionResult(FeedbackViewModel vm,IFeedbackService feedbackService)
{
and have the IoC construct the second parameter but not the first. Is that possible?
If not, I will have to find a way to create the members of the service constructor without using a static reference.
Thanks for reading.
Update using Brent Mannering's answer:
I tried creating a ResolveThis parameter but it is impossible to check for the attribute in the BindModel function. So I have stuck with resolving all interfaces:
/// <summary>
///
/// </summary>
public class DependencyModelBinder : DefaultModelBinder
{
/////////////////////////////////////////////////////////////
// Attributes
private IKernel _kernel;
/////////////////////////////////////////////////////////////
// Construction
public DependencyModelBinder(IKernel kernel)
{
// Initialize member variables
_kernel = kernel;
}
/////////////////////////////////////////////////////////////
// Implementation
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
// If this is an interface...
if(bindingContext.ModelType.IsInterface)
{
// Resolve the object and return
return _kernel.Resolve(bindingContext.ModelType);
}
// Call base-class function
return base.BindModel(controllerContext, bindingContext);
}
}