我正在尝试在我的WCF应用程序中实现每请求会话模型,并且我已经阅读了关于此主题的无数文档,但看起来没有完整的演示。我实际上遇到过一些非常有用的文章,例如:
NHibernate's ISession, scoped for a single WCF-call
但这些都来自NHibernate和Ninject没有WCF特定实现的旧时代,因此他们通过实现他们的自定义服务提供程序等来实现我所需要的。因为Ninject和NHibernate现在都支持WCF,我想通过使用他们的模块保持一致,但我最终在这里......
基本设置和流程应该是这样的:
我最初的问题是我无法访问wcf生命周期来处理我的绑定。在深入研究ninject代码后,我设法将我的方法挂钩到ServiceHost的Opening / Closing事件而没有太大变化,但后来我无法访问OperationContext,因为它是线程静态的。
后来我尝试启用asp.net兼容性并使用Application_BeginRequest和Application_EndRequest,它看起来非常有前景,但我不认为这是最好的解决方案,因为我应该将东西绑定到服务实例,而不是http请求。
有没有人使用ninject的内置wcf扩展库实现了这一目标?或者对我可能做错的任何想法?
答案 0 :(得分:2)
我已在IDispatchMessageInspector的帮助下实现了每个请求的会话生命周期。 可能您可以为Ninject实现自定义生命周期管理器以实现每个Web请求。
答案 1 :(得分:1)
HY
您可以执行以下操作:
public class DomainModule : NinjectModule
{
private const string RealSessionIndicator = "RealSession";
private readonly ProxyGenerator proxyGenerator = new ProxyGenerator();
public override void Load()
{
this.Bind<ISession>().ToMethod(ctx => ctx.Kernel.Get<ISessionFactory>().OpenSession())
.When(r => r.Parameters.Any(p => p.Name == RealSessionIndicator))
.InRequestScope();
this.Bind<Func<ISession>>().ToMethod(ctx => () => ctx.Kernel.Get<ISession>(new Parameter(RealSessionIndicator, (object)null, true)));
this.Bind<ISession>()
.ToMethod(this.CreateSessionProxy)
.InTransientScope();
this.Bind<ISessionFactory>().ToMethod(ctx => ctx.Kernel.Get<Configuration>().BuildSessionFactory()).InSingletonScope();
}
private ISession CreateSessionProxy(IContext ctx)
{
var session = (ISession)this.proxyGenerator.CreateInterfaceProxyWithoutTarget(typeof(ISession), new[] { typeof(ISessionImplementor) }, ctx.Kernel.Get<SessionInterceptor>());
return session;
}
}
public class SessionInterceptor : IInterceptor
{
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private readonly Func<ISession> sessionProvider;
public SessionInterceptor(Func<ISession> sessionProvider)
{
this.sessionProvider = sessionProvider;
}
public void Intercept(IInvocation invocation)
{
try
{
var session = this.sessionProvider();
invocation.ReturnValue = invocation.Method.Invoke(session, invocation.Arguments);
}
catch (TargetInvocationException exception)
{
Log.Error(exception);
throw;
}
}
}
有了它,您可以在任何地方使用ISession而无需关心细节。您可以使用InScope(ctx =&gt; OperationContext.Current)编辑InRequestScope以使用WCF范围
答案 2 :(得分:0)
您可以使用IInstanceContextProvider界面中提供的扩展点来完成此操作。