0

控制器

public class LocationsController : ApiController
{
    private readonly IMediator _mediator;

    public LocationsController(IMediator mediator)
    {
        _mediator = mediator;
    }

    public IEnumerable<Place> Get()
    {
        return _mediator.Send(new GetLatestMapData<Place>());
    }
}

在 Get() 操作的第一次请求中,处理程序由 SimpleInjector 实例化并正确执行。

在第二个请求中(例如浏览器中的 F5),它失败并显示:

未找到类型请求的处理程序 ....

容器或服务定位器未正确配置或处理程序未在您的容器中注册。

和内部例外:

无法访问已处置的对象。

对象名称:'ThreadLocal 对象已被释放。'

欧文启动

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        // SimpleInjector
        var container = CompositionRoot.CreateContainer();

        var config = GlobalConfiguration.Configuration;

        config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

        // Routing
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}",
            new { id = RouteParameter.Optional });

        config.EnsureInitialized();

        app.UseWebApi(config);
    }
}

WebAPI 项目的 SimpleInjector IPackage

public class Installer : IPackage
{
    public void RegisterServices(Container c)
    {
        c.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();

        c.RegisterWebApiControllers(GlobalConfiguration.Configuration);
    }
}

我认为正在发生的事情是正确创建了处理程序,然后在第一次请求后处置。现在,我不知道为什么,但是在后续请求中,不会重新创建处理程序。我知道这一点,因为如果我将 WebApiRequestLifestyle 更改为“范围结束时不处理”,它适用于每个请求:

c.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle(false
/*disposeInstanceWhenScopeEnds*/);

问题

  1. 我应该将disposeInstanceWhenScopeEnds参数设置为 false 吗?
  2. 如果不是,正确的解决方案是什么?
  3. 我看到这已经通过创建 LifetimeScopeDecorator 解决了......但是,这个功能肯定已经由 SimpleInjector WebApi 集成库提供了吗?我错过了什么?

(感谢您的阅读)

4

2 回答 2

0

链接提供了有关依赖关系解析和使用 IDependencyResolver / IDependencyScope 接口的良好指导。

您会立即看到它们涉及到寿命,这往往会变得有些棘手。

这部分特别有趣:

依赖范围和控制器生命周期

控制器是根据请求创建的。为了管理对象生命周期,IDependencyResolver 使用范围的概念。

附加到 HttpConfiguration 对象的依赖解析器具有全局范围。当 Web API 创建控制器时,它会调用 BeginScope。此方法返回一个表示子范围的 IDependencyScope。

Web API 然后在子作用域上调用 GetService 来创建控制器。请求完成后,Web API 会在子作用域上调用 Dispose。使用 Dispose 方法来处理控制器的依赖项。

通常,在应用程序启动期间引导服务会发生一次,并且您知道当时会解决任何依赖关系。只有当工作进程关闭(例如,没有活动)时,才会调用 dispose。

通常,我认为已解决的实例在生命周期中保留是很正常的,除非它们在使用后必须被销毁。但是给出的示例说明,一旦请求完成,我们必须正确处理。因此,我建议您使用作为指导提供的示例正确处理您的实例。

这在使用 IoC 和 WebApi 时帮助了我。我希望这有帮助!

于 2016-09-22T15:08:03.017 回答
0

您需要安排您的 Lifetime 范围

代码:

container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();

container.Options.LifestyleSelectionBehavior = new WebApiInjectionLifestyle();


internal class WebApiInjectionLifestyle : ILifestyleSelectionBehavior
{
    public Lifestyle SelectLifestyle(Type serviceType, Type implementationType)
    {
        return Lifestyle.Scoped;
    }
}

更多详情

https://simpleinjector.readthedocs.io/en/latest/lifetimes.html

于 2016-09-27T13:45:14.857 回答