【发布时间】:2014-03-17 05:52:41
【问题描述】:
正如标题所说,我正在尝试使用 StructureMap、Web Api 和 RavenDB 会话的 HybridHttpOrThreadLocalScoped 实例来使用依赖注入。
为此,我使用的是IHttpControllerActivator,请参见下面的代码。
public class StructureMapControllerActivator : IHttpControllerActivator
{
private readonly IContainer _container;
public StructureMapControllerActivator(IContainer container)
{
if (container == null) throw new ArgumentNullException("container");
_container = container;
}
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
try
{
var scopedContainer = _container.GetNestedContainer();
scopedContainer.Inject(typeof(HttpRequestMessage), request);
request.RegisterForDispose(scopedContainer);
return (IHttpController)scopedContainer.GetInstance(controllerType);
}
catch (Exception e)
{
// TODO : Logging
throw e;
}
}
}
在我的 global.asax 中,我像这样连接 IHttpControllerActivator:
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new StructureMapControllerActivator(ApplicationContainer));
这是我对 StructureMap 的配置:
expression.For<IDocumentStore>().Use(documentStore);
expression.For<IDocumentSession>()
.HybridHttpOrThreadLocalScoped()
.Use(container =>
{
var store = container.GetInstance<IDocumentStore>();
return store.OpenSession();
});
在我的ApiController 中,我有一个这样的构造函数:
public MyApiController(IDocumentSession session) {
_session = session;
}
当我创建第一个 Request 时,我得到了一个 DocumentSession 的实例,但第二个 Request 在这一行 return store.OpenSession() 上抛出了一个 HttpError 异常。异常表明该对象已被释放并且无法使用。这是完全的例外:
{
"$type": "System.Web.Http.HttpError, System.Web.Http",
"message": "An error has occurred.",
"exceptionMessage": "StructureMap Exception Code: 207\nInternal exception while creating Instance '6d9a72a3-3044-495a-909c-dd9fe7527c80' of PluginType Raven.Client.IDocumentSession, Raven.Client.Lightweight, Version=2.5.0.0, Culture=neutral, PublicKeyToken=37f41c7f99471593. Check the inner exception for more details.",
"exceptionType": "StructureMap.StructureMapException",
"stackTrace": " at BrickPile.Mvc.StructureMapControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) in c:\\Users\\maqe\\Documents\\Visual Studio 2013\\Projects\\brickpile\\BrickPile\\Mvc\\StructureMapWebApiDependencyResolver.cs:line 61\r\n at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()",
"innerException": {
"$type": "System.Web.Http.HttpError, System.Web.Http",
"message": "An error has occurred.",
"exceptionMessage": "The document store has already been disposed and cannot be used\r\nObject name: 'EmbeddableDocumentStore'.",
"exceptionType": "System.ObjectDisposedException",
"stackTrace": " at Raven.Client.Document.DocumentStore.OpenSession(OpenSessionOptions options) in c:\\Builds\\RavenDB-Stable\\Raven.Client.Lightweight\\Document\\DocumentStore.cs:line 355\r\n at BrickPile.DefaultBrickPileBootstrapper.<>c__DisplayClassc.<ConfigureApplicationContainerInternal>b__a(IContext container) in c:\\Users\\maqe\\Documents\\Visual Studio 2013\\Projects\\brickpile\\BrickPile\\DefaultBrickPileBootstrapper.cs:line 294\r\n at StructureMap.Pipeline.LambdaInstance`1.build(Type pluginType, BuildSession session) in c:\\BuildAgent\\work\\767273992e840853\\src\\StructureMap\\Pipeline\\LambdaInstance.cs:line 25"
}
}
谁能帮我解决我在这里缺少的东西?
我忘了提到我使用IHttpModule 来释放和处置Application_EndRequest 中的所有http 作用域对象。
【问题讨论】:
-
我将
.Singleton()添加到expression.For<IDocumentStore>().Use(documentStore);,现在它似乎可以使用我在问题中发布的完全相同的代码。任何人都可以确认解决方案吗? -
没错。
IDocumentStore实例应该是单例,IDocumentSession实例应该是 HTTP 范围的。默认情况下,StructureMap 每次都会创建一个新的类实例。 -
确定要
throw e;?大多数时候,它应该只是throw;,因为你正在丢失你的调用堆栈。
标签: c# dependency-injection asp.net-web-api ravendb structuremap