C# MVC3中的Ninject会话范围概念

C# MVC3中的Ninject会话范围概念,c#,asp.net-mvc,ninject,C#,Asp.net Mvc,Ninject,我正在使用Ninject框架构建一个MVC3应用程序。我有一个初始化很费时的服务,最终该服务将有一个包含用户特定信息的对象,然后只要用户会话处于活动状态,我就需要重新使用该服务,这样我就可以避免一次又一次地初始化该服务 所以我的问题是 当我使用Ninject绑定服务时,我应该选择什么类型的作用域,Ninject中没有每个作用域的会话,那么实现需求的最佳方法是什么?还是我走错了方向 我已经为我的一个服务创建了自定义提供程序,该提供程序将根据从当前Controller.User.Identity.N

我正在使用Ninject框架构建一个MVC3应用程序。我有一个初始化很费时的服务,最终该服务将有一个包含用户特定信息的对象,然后只要用户会话处于活动状态,我就需要重新使用该服务,这样我就可以避免一次又一次地初始化该服务

所以我的问题是

当我使用Ninject绑定服务时,我应该选择什么类型的作用域,Ninject中没有每个作用域的会话,那么实现需求的最佳方法是什么?还是我走错了方向

我已经为我的一个服务创建了自定义提供程序,该提供程序将根据从当前Controller.User.Identity.Name获取的用户名详细信息创建服务。下面的代码无法工作,因为缺少userName局部变量。如何通过Ninject将用户名值传递到自定义提供程序中,以便从IContext中获取它

public class TfsConnectionManagerProvider : Provider<TfsConnectionManager>
    {
        protected override TfsConnectionManager CreateInstance(IContext context)
        {
            Uri serverUri = new Uri(ConfigurationHelper.TfsServerUrl);
            // Connect to the server without impersonation
            using (TfsTeamProjectCollection baseUserConnection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(serverUri))
            {
                // Get the identity management service
                IIdentityManagementService ims = baseUserConnection.GetService<IIdentityManagementService>();

                // Get the identity to impersonate
                TeamFoundationIdentity identity = ims.ReadIdentity
                (
                    IdentitySearchFactor.AccountName,
                    userName,  //NOTE: How can I get user name value from IContext???
                    MembershipQuery.None,
                    ReadIdentityOptions.None
                );

                // Connect using the impersonated identity
                using (TfsTeamProjectCollection impersonatedConnection = new TfsTeamProjectCollection(serverUri, identity.Descriptor))
                {
                    WorkItemStore store = impersonatedConnection.GetService<WorkItemStore>();

                    return new TfsConnectionManager
                    {
                        Store = store
                    };
                }
            }
        }
    }
公共类TfsConnectionManager提供程序:提供程序
{
受保护的覆盖TfsConnectionManager CreateInstance(IContext上下文)
{
Uri serverUri=新Uri(ConfigurationHelper.TfsServerUrl);
//连接到服务器而不进行模拟
使用(tfstreamprojectcollection baseUserConnection=tfstreamprojectcollectionfactory.GetTeamProjectCollection(serverUri))
{
//获取身份管理服务
IIdentialManagementService ims=baseUserConnection.GetService();
//获取要模拟的标识
TeamFoundationIdentity=ims.ReadIdentity
(
IdentitySearchFactor.AccountName,
用户名,//注意:如何从IContext获取用户名值???
MembershipQuery.None,
ReadIdentityOptions。无
);
//使用模拟身份进行连接
使用(TfsatmProjectCollection impersonatedConnection=new TfsatmProjectCollection(serverUri,identity.Descriptor))
{
WorkItemStore=impersonatedConnection.GetService();
返回新的TfsConnectionManager
{
商店
};
}
}
}
}

好的,您可以在应用程序中缓存/存储用户信息,并且只有在没有(最近)用户信息的情况下才能调用外部服务。在您的用户信息检索“层”,您只需编程这两种可能性

缓存在哪里,完全取决于您。例如,您可以将此信息存储在本地数据库中

显然,我理解错了,我的道歉(在我最初的回答下面)

例如,您可以使用保存静态 您的服务的成员(例如),因此它将被重用

尽管这取决于您的服务,但可能会有一些不必要的方面 效果(我曾经在Data Services和ASP.NET MVC3中这样做过一次) 应用程序我的数据上下文是有点搞砸了,因为一些魔法 发生了)。我想说的是:小心并测试它 嗯


Ninject故意不提供会话范围,因为在几乎所有情况下,让服务处于会话状态都是错误的。您应该非常小心地使用会话状态,因为它会带来很多缺点

首先尝试使用无状态应用程序


如果有充分的理由将数据置于会话范围内,则将该数据(而非服务)置于会话状态,并使用处于单例、瞬态或请求范围内的服务进行处理(数据和功能分离).

我使用自定义提供程序创建实例,并在自定义提供程序中检查它是否存在于会话中

绑定如下所示

Bind<IRepository>().ToProvider(new TfsRepositoryProvider());
Bind().ToProvider(新的TfsRepositoryProvider());
自定义提供程序位于下面

public class TfsRepositoryProvider : Provider<TfsRepository>
    {
        private const string SesTfsRepository = "SES_TFS_REPOSITORY";

        protected override TfsRepository CreateInstance(IContext context)
        {
            // Retrieve services from kernel
            HttpContextBase httpContext = context.Kernel.Get<HttpContextBase>();

            if (httpContext == null || httpContext.Session == null)
            {
                throw new Exception("No bind service found in Kernel for HttpContextBase");
            }

            return (httpContext.Session[SesTfsRepository] ?? (
                    httpContext.Session[SesTfsRepository] = new TfsRepository(context.Kernel.Get<IWorkItemStoreWrapper>()))
                ) as TfsRepository;
        }
    }
公共类TfsRepositoryProvider:Provider
{
private const string SesTfsRepository=“SES\u TFS\u REPOSITORY”;
受保护的覆盖TfsRepository CreateInstance(IContext上下文)
{
//从内核检索服务
HttpContextBase httpContext=context.Kernel.Get();
if(httpContext==null | | httpContext.Session==null)
{
抛出新异常(“在HttpContextBase的内核中找不到绑定服务”);
}
返回(httpContext.Session[SesTfsRepository](
httpContext.Session[SesTfsRepository]=新的TfsRepository(context.Kernel.Get())
)反义的;
}
}

抱歉,我可能无法很好地解释我的问题,服务的初始化涉及调用某些web服务,然后这些服务将返回特定于用户的信息。我不能使它成为静态的,因为它是用户特定的,所以我误解了你:)。您可以尝试在应用程序中缓存用户数据(信息),并且只有在您自己没有用户信息的情况下才调用外部服务。是的,这就是我上面真正的问题-我如何通过使用Scope的Ninject binding实现它谢谢您的反馈,我能理解你在上面提出的解决方案,这是一个非常著名的设计,但我真正想要的是如何在Ninject框架下实现它,谢谢你在这里不必对Ninject做任何事情。只需让检索用户信息的类选择是从数据库还是从服务获取信息。ASP.NET MVC 3端没有任何更改。谢谢Remo,我在原始描述中添加会话可能会让人困惑。我不是说我要使用会话来保存数据,目标是重用从会话返回的特定于用户的对象