I am adding IoC to an already existing web forms project, and I am having a little trouble with getting the dependencies of user controls injected, especially dynamic user controls in a master page.
On the master page, I load some user controls:
protected override void OnLoad(EventArgs e)
{
bool processComplete = false;
var page = Page as BasePage;
if (page != null && HttpContext.Current.User.Identity.IsAuthenticated)
processComplete = page.processComplete ;
var segments = this.Request.Url.Segments;
Control bodyheader = null;
if (processComplete )
{
if (segments.Count() > 1 && segments[1].StartsWith("evaluation", true, System.Globalization.CultureInfo.CurrentCulture))
bodyheader = Page.LoadControl("~/Themes/HWP/HeaderNoSearch.ascx");
else
bodyheader = Page.LoadControl("~/Themes/HWP/Header.ascx");
}
else if (segments.Count() > 1 && segments[1].StartsWith("welcome", true, System.Globalization.CultureInfo.CurrentCulture))
{
bodyheader = Page.LoadControl("~/Themes/HWP/plainHeaderAuth.ascx");
}
else
{
bodyheader = Page.LoadControl("~/Themes/HWP/plainHeaderAuth.ascx");
}
plcBodyHeader.Controls.Add(bodyheader);
Control bodyfooter = Page.LoadControl("~/Themes/HWP/Footer.ascx");
plcBodyFooter.Controls.Add(bodyfooter);
base.OnLoad(e);
}
Each of these user controls has some dependencies. I can manually inject the dependencies in each user control:
protected override void OnInit(EventArgs e)
{
var cpa = (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
var cp = cpa.ContainerProvider;
cp.RequestLifetime.InjectProperties(this);
base.OnInit(e);
}
But that seems like it defeats the purpose of using an IoC. How should the MasterPage -> Page -> UserControls be structured to allow for DI? And how do I inject properties in a dynamic user control? Should I be using constructor injection?
I am using Autofac, but I think this question id IoC agnostic.
You are on the right track. I normally create a BaseUserControl class which inherits from UserControl. Then inherit all UserControls from this BaseUserControl class.
Place all required dependencies inside that BaseUserControl class.
You might think that it is a bit wasted, because not all user controls use all dependencies.
Mark Seemann stated in Dependency Injection in .NET book that dependency injection is quite fast and never been an issue. If you think your application is slow, it will be from other places of your code (not from dependency injection).
If you want to use constructor injection, look at this answer.