Typically with a tool like Castle Windsor you have to setup the container in the Global handlers. For instance:
public class GlobalApplication : HttpApplication, IContainerAccessor
{
private static IWindsorContainer container;
/// <summary>
/// Provides a globally available access to the <see cref="IWindsorContainer" /> instance.
/// </summary>
public static IWindsorContainer WindsorContainer
{
get { return container; }
}
#region IContainerAccessor
public IWindsorContainer Container
{
get { return container; }
}
#endregion
public void Application_OnStart()
{
container = new WindsorContainer(new XmlInterpreter());
}
Then on any corresponding page, you can retrieve the container, for example, I tend to create a basepage and access the factory, something like this:
public abstract class BasePage : Page
{
/// <summary>
/// Exposes accessor for the <see cref="IDaoFactory" /> used by all pages.
/// </summary>
public IDaoFactory DaoFactory
{
get { return GlobalApplication.WindsorContainer.Resolve<IDaoFactory>(); }
}
This pulls from the config to get the IDaoFactory, ie.
<components>
<component id="primaryDaoFactory"
type="FSData.DaoFactory, FSData"
service="FSData.IDaoFactory, FSData">
<parameters>
<connectionString>#{connString}</connectionString>
</parameters>
</component>
</components>
Inside the page, I would then use that factory:
IMissionDao dao = DaoFactory.GetMissionDao();
With Spring.NET’s Spring.Web this is all diverted into the configuration with no code required:
First, you setup the correct context – notice I’ve commented out the default context to instead using the webcontext:
<sectionGroup name="spring">
<!--<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>-->
<section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
</sectionGroup>
A description of this can be found in the Spring.NET help:
"The instantiation and configuration of the Spring.NET IoC container by the Spring.Web infrastructure is wholly transparent to application developers, who will typically never have to explicitly instatiate and configure an IoC container manually (by for example using the new operator in C#). In order to effect the transparent bootstrapping of the IoC container, the Spring.Web infrastructure requires the insertion of the following configuration snippet into each and every Spring.Web-enabled web application’s root Web.config file"
Next, you add the HttpHandler:
<httpHandlers>
<add verb="*" path="*.aspx" type="Spring.Web.Support.PageHandlerFactory, Spring.Web"/>
</httpHandlers>
and HttpModule:
<httpModules>
<add name="SpringModule" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
</httpModules>
(Both of these are in the web.config)
Once these are setup once, you don’t have to worry about it again.
Now we need to actually use our DaoFactory in our page:
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<description>An example that demonstrates simple IoC features.</description>
<object type="Default.aspx">
<property name="DaoFactory" ref="primaryDaoFactory"/>
</object>
<object name="primaryDaoFactory"
type="FSData.DaoFactory, FSData">
<constructor-arg name="connectionString" value="server=.SQLEXPRESS;database=dbFW;Integrated Security=true"/>
</object>
</objects>
</spring>
This shows that the Default.aspx page has a dependency on ‘DaoFactory’ that will be injected into the page. I setup a property on the page:
public partial class _Default : System.Web.UI.Page
{
private IDaoFactory daoFactory;
public IDaoFactory DaoFactory
{
set { daoFactory = value; }
get { return daoFactory; }
}
protected void Page_Load(object sender, EventArgs e)
{
IAircraftDao acDao = daoFactory.GetAircraftDao();
List<Aircrafts> ac = acDao.SelectAllAircraft();
}
}
* Update:
If you notice, I did have to add the ‘object type=Default.aspx’ above. Well, let’s say you had a ton of pages and didn’t want to add every page in order to inject this daoFactory. An alternative is to use a basepage class that inherits from Spring.Web.UI.Page with the following:
private IDaoFactory daoFactory;
public IDaoFactory DaoFactory
{
get
{
//return this.ApplicationContext.ConfigureObject(this, typeof(IDaoFactory).FullName);
return daoFactory;
}
}
protected override void OnInit(EventArgs e)
{
daoFactory = (IDaoFactory)this.ApplicationContext.GetObject("primaryDaoFactory");
base.OnInit(e);
}
Since i want the DaoFactory to be a singleton and it’s scope to be the application, I updated the config as well:
<object name="primaryDaoFactory"
type="FSData.DaoFactory, FSData" scope="application" singleton="true">
<constructor-arg name="connectionString" value="server=.\SQLEXPRESS;database=dbFW;Integrated Security=true"/>
This allows me to inject the DaoFactory into every page that uses the base class (granted I’ve probably not want this code in my code behind but that is another topic…)
So there you have it – the daoFactory is injected into the page, and is accessible. I find this to be a better approach than Castle Windsor once you get through the configuration aspects. Both however, are very powerful, so if anything, this shows an alternative way of handling DI in webforms.
Side note: Curious about Spring.NET with MS MVC ? Here is an approach one programmer has used…
also http://fredrik.nsquared2.com/ViewPost.aspx?PostID=465