【问题标题】:IoC - WindsorContainer - Asp.Net null after Application_StartIoC - WindsorContainer - Application_Start 后的 Asp.Net null
【发布时间】:2010-08-03 04:31:19
【问题描述】:

我有一种情况,我在 .Net Web 应用程序中使用 IoC (WindsorContainer),并在 Global.asax 中注册了我的容器,但是在我注册了 WindsorContainer 之后,我还需要在其中实例化另一个类 (Oauth) Global.asax。

但是,因为我在 IIS7 上使用 Sharp 架构和 Nhibernate,所以情况非常棘手,因为 webSessionStorage 在 Global.asax 文件中的 Init() 方法期间注册,并且我必须在 NhibernateSession 之后实例化 OauthInit 类已初始化,但是此时 WindsorContainer 已经为空,因为 Init 发生在 Application_Start 之后。代码如下:

  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));
    }


}

所以我现在真的处于第 22 个问题中。当我在 Application_Start 请求期间创建 WindsorContainer 时,NHibernateSession 尚未初始化,因此我无法调用 _container.Resolve&lt;IInitOAuthProvider&gt;("initOauth").OAuthProvider 并且当 NHibernateSession 已初始化时,_container对象为空。

任何帮助将不胜感激,谢谢。

【问题讨论】:

标签: .net nhibernate s#arp-architecture


【解决方案1】:

我认为主要问题(我认为 Mauricio Scheffer 的评论是 暗示)是HttpApplication对象可以有多个实例,因此可以创建IWindsorContainer _containerWebSessionStorage _webSessionStorage的多个副本,当(如果我正确理解代码)你只想要一个实例.还请记住,您的 HttpApplication 的 Init() 方法也可能因此被多次调用。

这基本上是对 HttpApplication 生命周期的根本误解。当传入的 HTTP 请求进入应用程序时,ASP.NET 工作进程将启动多个 HttpApplication 实例来处理这些请求,完成后会将它们放入一个池中,准备再次使用(它不会破坏它们) .这类似于数据库连接池。

但从根本上讲,您必须知道 HttpApplication 不是单例,可以有多个实例。这是一个很常见的错误,也让我感到困惑,which is why I wrote a blog post on it

尝试将您的 IWindsorContainer 和 WebSessionStorage 设置为静态。


编辑:好的,更仔细地研究了代码后得到了更详细的答案。

查看您的 Application_Start 事件,在其中您正在初始化一个实例

private IWindsorContainer _container;

...但是因为它不是静态变量,它只会为第一个实例化的 HttpApplication 对象初始化。随着其他 HttpApplication 对象被实例化,它们的 _container 变量副本将为 NULL。为什么?因为 _container 变量仅在 Application_Start 事件中初始化,该事件已被触发。所以 _container 将被设置为第一个 HttpApplication 实例的对象,但之后的每个 HttpApplication 实例都将为 NULL。

希望这是有道理的。

【讨论】:

  • 谢谢您,非常有用且很好的答案,是的,可以解决它。非常感谢。
猜你喜欢
  • 2011-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-07
  • 1970-01-01
  • 1970-01-01
  • 2011-02-14
  • 2011-05-31
相关资源
最近更新 更多