【问题标题】:Web Api and dependency injection with StructureMap using http scoped instances使用 http 作用域实例的 StructureMap 的 Web Api 和依赖项注入
【发布时间】: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&lt;IDocumentStore&gt;().Use(documentStore);,现在它似乎可以使用我在问题中发布的完全相同的代码。任何人都可以确认解决方案吗?
  • 没错。 IDocumentStore 实例应该是单例,IDocumentSession 实例应该是 HTTP 范围的。默认情况下,StructureMap 每次都会创建一个新的类实例。
  • 确定要throw e;?大多数时候,它应该只是throw;,因为你正在丢失你的调用堆栈。

标签: c# dependency-injection asp.net-web-api ravendb structuremap


【解决方案1】:

我忘记将.Singleton() 添加到expression.For&lt;IDocumentStore&gt;().Use(documentStore);。上面的代码在此修改后按预期工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多