2011-03-17 102 views
1

我使用的是MVC 3,根据不同的存储库我有一系列控制器,我的存储库中有一个依赖于http上下文会话。 为了使用Windsor-Castle IoC,我为每个存储库创建了接口。Windsor Castle IoC - Http Session

如何将当前会话对象传递给需要它的存储库?

我曾经是能够做到这一点和“解决”会照顾会话传递给需要它的存储库中,不知何故,我不能在最新版本中做到这一点(2.5.3 2011年2月):

Protected Overrides Function GetControllerInstance(ByVal requestContext As System.Web.Routing.RequestContext, _ 
                ByVal controllerType As System.Type) As System.Web.Mvc.IController 
    Dim match As IController 
    ' 1 or more components may need the session, 
    ' adding it as a (possible) dependency 
    Dim deps As New Hashtable 
    deps.Add("session", HttpContext.Current.Session) 
    match = container.Resolve(controllerType, deps) 
    Return match 
End Function 

谢谢,文森特

回答

2

控制器厂的唯一责任是创建控制器。不处理会话或任何其他依赖项。最好只将会话注册为一个单独的组件,让Windsor自动装配它。从那里取出 'DEPS' Hashtable和注册:

container.Register(Component.For<HttpSessionStateBase>() 
     .LifeStyle.PerWebRequest 
     .UsingFactoryMethod(() => new HttpSessionStateWrapper(HttpContext.Current.Session))); 

然后在你的控制器注入HttpSessionStateBase

顺便说一下:控制器已经可以访问会话,如果您只是将会话注入控制器,则不需要这样做。

4

仔细看看你的设计。当你仔细观察它时,你的存储库根本不依赖于会话,而是存储在会话中的某些数据。针对要从会话中提取的内容创建抽象,并让存储库依赖于这种抽象。例如:

public interface IUserProvider 
{ 
    int GetCurrentUserId(); 
} 

public class SomeRepository : ISomeRepository 
{ 
    private readonly IUserProvider userProvider; 

    public SomeRepository(IUserProvider userProvider) 
    { 
     this.userProvider = userProvider; 
    } 
} 

现在,您可以创建以下实现,抽象的:

private class HttpSessionUserProvider : IUserProvider 
{ 
    public int GetCurrentUserId() 
    { 
     return (int)HttpContext.Current.Session["UserId"]; 
    } 
} 

你可以在你的IoC配置寄存器这个具体类型。

这样好多了,因为您不想让存储库直接依赖HTTP会话。这使测试变得更加困难,并在您的存储库和特定的演示技术之间创建依赖关系。