I have a situation where I user IoC (WindsorContainer) in a .Net web application, and in the Global.asax I register my container, but straight after I register my WindsorContainer I also need to Instantiate another Class (Oauth) in the Global.asax.
However because I use the Sharp Architecture and Nhibernate on IIS7 it makes the situation very tricky because the webSessionStorage gets registered during the Init() method in the Global.asax file, and I have to Instantiate the OauthInit class after the NhibernateSession has been initialised, however by this time the WindsorContainer is already null, since the Init occurs after the Application_Start. Here is the code:
public class Global : HttpApplication, IOAuthServices
{
static ITokenRepository<AccessToken> _accessTokenRepository;
static ITokenRepository<RequestToken> _requestTokenRepository;
private IWindsorContainer _container;
private WebSessionStorage _webSessionStorage;
private IOAuthProvider _provider;
public ITokenRepository<AccessToken> AccessTokenRepository
{
get { return _accessTokenRepository; }
}
public ITokenRepository<RequestToken> RequestTokenRepository
{
get { return _requestTokenRepository; }
}
public IOAuthProvider Provider
{
get { return _provider; }
}
void Application_Start(object sender, EventArgs e)
{
_requestTokenRepository = new InMemoryTokenRepository<RequestToken>();
_accessTokenRepository = new InMemoryTokenRepository<AccessToken>();
CreateWindsorContainer();
}
public override void Init()
{
base.Init();
// The WebSessionStorage must be created during the Init() to tie in HttpApplication events
_webSessionStorage = new WebSessionStorage(this);
}
/// <summary>
/// Due to issues on IIS7, the NHibernate initialization cannot reside in Init() but
/// must only be called once. Consequently, we invoke a thread-safe singleton class to
/// ensure it's only initialized once.
/// </summary>
protected void Application_BeginRequest(object sender, EventArgs e)
{
NHibernateInitializer.Instance().InitializeNHibernateOnce(InitializeNHibernateSession);
_provider = _container.Resolve<IInitOAuthProvider>("initOauth").OAuthProvider); // <-- THIS IS THE ISSUE HERE
}
/// <summary>
/// If you need to communicate to multiple databases, you'd add a line to this method to
/// initialize the other database as well.
/// </summary>
private void InitializeNHibernateSession()
{
NHibernateSession.Init(
_webSessionStorage,
new[] { Server.MapPath("~/bin/MyAppSuite.Data.dll") },
new AutoPersistenceModelGenerator().Generate(),
Server.MapPath("~/NHibernate.config"));
}
private void CreateWindsorContainer()
{
_container = new WindsorContainer();
ComponentRegistrar.AddComponentsTo(_container);
ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(_container));
}
}
So I am really at the moment in a catch 22. When I am creating my WindsorContainer during the Application_Start request, the NHibernateSession has not been initialised, so I cannot call _container.Resolve<IInitOAuthProvider>("initOauth").OAuthProvider
and when the NHibernateSession has been initialised, the _container object is null.
Any help would be appreciated, thanks.