2017-05-24 35 views
0

我目前正在尝试从温莎城堡迁移到简单喷油器。从温莎迁移到简单的喷油器,HttpContext.Current.Session为空

内的服务我在试图注入HttpSessionStateBase所示下面的构造函数的服务:

public UserSession(IResourceRepository resourceRepository, IUser user, 
    IRoleResolver roleResolver, IApproverRepository approverRepository, 
    IActiveDirectory activeDirectory, HttpSessionStateBase httpSession, 
    Settings appSettings) 
{ 
    _resourceRepository = resourceRepository; 
    _user = user; 
    _roleResolver = roleResolver; 
    _approverRepository = approverRepository; 
    _activeDirectory = activeDirectory; 
    _httpSession = httpSession; 
    _allowedUsernamePostfixes = appSettings.AuthenticationAllowedUsernamePostfixes; 
} 

要与温莎做到这一点我可以使用一个FactoryMethod注入HttpSessionStateBase作为新HttpSessionStateWrapper。

private static IWindsorContainer BuildWindsorContainer() 
{ 
    var container = new WindsorContainer(); 
    container.Kernel.Resolver.AddSubResolver(
     new CollectionResolver(container.Kernel, true)); 

    container.Register(
     Component.For<IWindsorContainer>().Instance(container) 
     ); 

    container.Install(FromAssembly.This()); 

    container.Register(
     Component.For<HttpRequestBase>() 
      .UsingFactoryMethod(() => new HttpRequestWrapper(HttpContext.Current.Request)) 
      .LifestyleTransient(), 
     Component.For<HttpSessionStateBase>() 
      .UsingFactoryMethod(() => new HttpSessionStateWrapper(HttpContext.Current.Session)) 
      .LifestyleTransient(), 


    return container; 
} 

该方法在Global.asax.cs文件中的ASP.NET MVC 4项目的Application_Start方法中被调用时将工作。

我现在已经尝试通过将两个温莎FactoryMethods如下简单的代码注入到其转换为简单的进样:

container.Register<HttpRequestBase>(
    () => new HttpRequestWrapper(HttpContext.Current.Request), 
    Lifestyle.Transient); 

container.Register<HttpSessionStateBase>(
    () => new HttpSessionStateWrapper(HttpContext.Current.Session), 
    Lifestyle.Transient); 

的问题是,当我把在Application_Start方法这种方法则的HttpContext。 Simple Inject调用容器验证方法时,Current.Session将为null。

任何人都有这个解决方案吗?

回答

0

问题是,当我在Application_Start方法中调用此方法时,当Simple Inject调用容器验证方法时,HttpContext.Current.Session将为null。

与温莎城堡,你会有同样的问题,如果它包含像简单注射器那样的验证功能。如果您删除对container.Verify()的呼叫,您将获得与Castle Winsdor相同的行为,即您没有得到任何验证。

显然,这并不理想,这可能是您希望迁移到Simple Injector的原因之一。

这个问题归结为使用运行时状态构建应用程序组件的问题,这是一种代码异味,如expressed here。所以在一个理想的情况下,你应该减轻这一点,并确保HttpContext.Current不叫做suring object construction,而只是之后的对象构造。

尽管您应该真的努力做到这一点,但我可以理解,这可能是重构应用程序的一项艰巨任务,并且比仅更改DI容器花费的时间要多得多。不管怎样,你都应该记住(近)将来的事情。

也就是说,实际的(和时间)解决初始化过程中,以制造假HttpRequestHttpSession对象,如下图所示:

container.Register<HttpRequestBase>(
    () => HttpContext.Current != null 
     ? new HttpRequestWrapper(HttpContext.Current.Request) 
     : new HttpRequestWrapper(new HttpRequest("", "http://fake", "")), 
    Lifestyle.Scoped); 

container.Register<HttpSessionStateBase>(
    () => HttpContext.Current != null 
     ? new HttpSessionStateWrapper(HttpContext.Current.Session) 
     : (HttpSessionState)typeof(HttpSessionState) 
      .GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic) 
      .First() 
      .Invoke(new object[] { null }), 
    Lifestyle.Scoped); 

这是相当难看,尤其是HttpSessionState创建(有一个内部构造函数),但它保证了其他配置的可验证性。

+0

嗨,你是正确的代码与使用运行时数据的气味。令人遗憾的是,应用程序的创始人基于使用运行时数据的服务进行身份验证...... 我已经尝试了一些代码,但无法使HttpSessionStateBase工作,因为HttpSessionStateWrapper和HttpSessionState之间没有隐式类型。 – McBoman

+0

对不起,我没有时间测试代码,希望这会给你一些关于如何解决这个问题的指导。 – Steven

+0

当然,感谢您的帮助。 – McBoman