我正在使用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
};
}
}
}
}
答案 0 :(得分:7)
Ninject故意不提供会话范围,因为在几乎所有情况下,会话状态中的服务都是错误的。你应该非常谨慎地使用会话状态,因为它带来了许多缺点。
尝试首先使用无状态应用程序。
如果有足够的理由在会话范围内拥有数据,那么将该数据(而不是服务)放入会话状态,并使用单例,瞬态或请求范围内的服务进行处理(数据和功能的分离)
答案 1 :(得分:2)
我最终使用自定义Provider来创建实例,并在自定义提供程序中检查它是否存在于会话中。
绑定完成如下
Bind<IRepository>().ToProvider(new 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;
}
}
答案 2 :(得分:0)
好的,您可以在应用程序中缓存/存储用户信息,如果您没有(最近的)用户信息,则只能调用外部服务。在您的用户信息检索“层”中,您只需编写这两种可能性。
你缓存的地方,完全取决于你。您可以将此信息存储在本地数据库中。
显然我理解你错了,道歉(低于我原来的答案)。
您可以使用例如包含静态的(抽象)工厂 您的服务成员(例如),因此它将被重用。
虽然取决于您的服务,但这可能会有一些不必要的方面 效果(我曾经使用Data Services和ASP.NET MVC3做过一次 应用程序我的数据上下文因为一些魔法而有点紧张 发生过)。我想说的就是:小心并测试它 好。