Ninject, ASP.NET, and User Controls

I am currently using ASP.NET (standard, not MVC) and I am using Ninject as an IOC container.

I already use it to inject dependencies into my pages, however I was wondering if there is a way to embed dependencies in my user controls?

If not, I will continue the Ninject extension :)

+4
source share
2 answers

Ok, so I finished the Ninject extension and added two classes to the Ninject.Framework.Web dll.

Here is a patch for anyone interested in adding it:

Index: src/Framework/Web/Ninject.Framework.Web.csproj =================================================================== --- src/Framework/Web/Ninject.Framework.Web.csproj (revision 158) +++ src/Framework/Web/Ninject.Framework.Web.csproj (working copy) @@ -2,7 +2,7 @@ <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <ProductVersion>9.0.21022</ProductVersion> + <ProductVersion>9.0.30729</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{C46075DB-A0FB-466B-BA76-C093227FA9C7}</ProjectGuid> <OutputType>Library</OutputType> @@ -42,17 +42,24 @@ <Reference Include="System.Core"> <RequiredTargetFramework>3.5</RequiredTargetFramework> </Reference> + <Reference Include="System.Data" /> + <Reference Include="System.Drawing" /> <Reference Include="System.Web" /> <Reference Include="System.Web.Services" /> + <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <Compile Include="..\..\GlobalAssemblyInfo.cs"> <Link>Properties\GlobalAssemblyInfo.cs</Link> </Compile> + <Compile Include="WebControlBase.cs" /> <Compile Include="NinjectHttpApplication.cs" /> <Compile Include="HttpHandlerBase.cs"> </Compile> <Compile Include="NinjectHttpModule.cs" /> + <Compile Include="UserControlBase.cs"> + <SubType>ASPXCodeBehind</SubType> + </Compile> <Compile Include="WebServiceBase.cs"> <SubType>Component</SubType> </Compile> Index: src/Framework/Web/UserControlBase.cs =================================================================== --- src/Framework/Web/UserControlBase.cs (revision 0) +++ src/Framework/Web/UserControlBase.cs (revision 0) @@ -0,0 +1,65 @@ +#region License +// +// Author: Nate Kohari < nkohari@gmail.com >, Nik Radford < nikradford@googlemail.com > +// Copyright (c) 2007-2008, Enkari, Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#endregion +#region Using Directives +using System; +using Ninject.Core.Logging; +using Ninject.Core; +using System.Web.UI; +#endregion + +namespace Ninject.Framework.Web +{ + /// <summary> + /// A <see cref="UserControl"/> that supports injection + /// </summary> + public class UserControlBase : UserControl + { + /*----------------------------------------------------------------------------------------*/ + private ILogger _logger; + /*----------------------------------------------------------------------------------------*/ + /// <summary> + /// Gets or sets the logger associated with the object. + /// </summary> + [Inject] + public ILogger Logger + { + get { return _logger; } + set { _logger = value; } + } + /*----------------------------------------------------------------------------------------*/ + /// <summary> + /// Raises the <see cref="E:System.Web.UI.Control.Init"></see> event to initialize the page. + /// </summary> + /// <param name="e">An <see cref="T:System.EventArgs"></see> that contains the event data.</param> + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + RequestActivation(); + } + /*----------------------------------------------------------------------------------------*/ + /// <summary> + /// Asks the kernel to inject this instance. + /// </summary> + protected virtual void RequestActivation() + { + KernelContainer.Inject(this); + } + /*----------------------------------------------------------------------------------------*/ + } +} Index: src/Framework/Web/WebControlBase.cs =================================================================== --- src/Framework/Web/WebControlBase.cs (revision 0) +++ src/Framework/Web/WebControlBase.cs (revision 0) @@ -0,0 +1,65 @@ +#region License +// +// Author: Nate Kohari < nkohari@gmail.com >, Nik Radford < nikradford@googlemail.com > +// Copyright (c) 2007-2008, Enkari, Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#endregion +#region Using Directives +using System; +using System.Web.UI.WebControls; +using Ninject.Core.Logging; +using Ninject.Core; +#endregion + +namespace Ninject.Framework.Web +{ + /// <summary> + /// A <see cref="WebControl"/> that supports injection + /// </summary> + public class WebControlBase : WebControl + { + /*----------------------------------------------------------------------------------------*/ + ILogger _logger; + /*----------------------------------------------------------------------------------------*/ + /// <summary> + /// Gets or sets the logger associated with the object. + /// </summary> + [Inject] + public ILogger Logger + { + get { return _logger; } + set { _logger = value; } + } + /*----------------------------------------------------------------------------------------*/ + /// <summary> + /// Raises the <see cref="E:System.Web.UI.Control.Init"></see> event to initialize the page. + /// </summary> + /// <param name="e">An <see cref="T:System.EventArgs"></see> that contains the event data.</param> + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + RequestActivation(); + } + /*----------------------------------------------------------------------------------------*/ + /// <summary> + /// Asks the kernel to inject this instance + /// </summary> + protected virtual void RequestActivation() + { + KernelContainer.Inject(this); + } + /*----------------------------------------------------------------------------------------*/ + } +} 
+6
source

I solved this by going through all the controls on the page and introducing those who implement some kind of interface.

The interface is empty:

 public interface INinjectControl { } 

I added a loop to PageBase and MasterPageBase to input all the controls that implement this interface:

 protected virtual void RequestActivation() { KernelContainer.Inject( this ); InjectControls(this.Controls); } private void InjectControls(ControlCollection controls) { foreach (Control control in controls) { if (control is INinjectControl) KernelContainer.Inject(control); this.InjectControls(control.Controls); } } 

There are some disadvantages:

  • This only works for controls that are already on the page when OnInit fires. If you add a control later in this process, it is already running and no dependencies will be entered.
  • This calls CreateChildControls () for some controls because you are requesting a collection of Controls. This can lead to problems, as this method is now called much earlier in the life cycle.
  • It goes through all the controls, so it is not very effective.
0
source

All Articles