Web API自托管应用程序和Simple Injector中的LifetimeScoping错误

时间:2013-05-19 13:10:05

标签: asp.net-web-api simple-injector lifetime-scoping dependency-resolver

我阅读了这些(++++)页面,但我无法弄清楚应该怎么做。

我有这个简单的界面和具体类型:

public interface IIdentifierGenerator {
    long Generate(Type type);
    long Generate<TType>(TType type);
}
public HiloIdentifierGenerator : IIdentifierGenerator { /* implementation... */ }

我创建了这个DependencyResolver

public class SelfHostedSimpleInjectorWebApiDependencyResolver : IDependencyResolver {
    private readonly Container _container;
    private readonly LifetimeScope _lifetimeScope;

    public SelfHostedSimpleInjectorWebApiDependencyResolver(
        Container container)
        : this(container, false) {
    }

    private SelfHostedSimpleInjectorWebApiDependencyResolver(
        Container container, bool createScope) {
        _container = container;

        if (createScope)
            _lifetimeScope = container.BeginLifetimeScope();
    }

    public IDependencyScope BeginScope() {
        return new SelfHostedSimpleInjectorWebApiDependencyResolver(
            _container, true);
    }

    public object GetService(Type serviceType) {
        return ((IServiceProvider)_container).GetService(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType) {
        return _container.GetAllInstances(serviceType);
    }

    public void Dispose() {
        if (_lifetimeScope != null)
            _lifetimeScope.Dispose();
    }
}

我配置了我的服务器:

_config = new HttpSelfHostConfiguration("http://192.168.1.100:20000");
_config.Routes.MapHttpRoute(
    "API Default", "api/{controller}/{id}",
    new { id = RouteParameter.Optional });
_config.DependencyResolver =
    new SelfHostedSimpleInjectorWebApiDependencyResolver(
        IoC.Wrapper.GetService<Container>());
_server = new HttpSelfHostServer(_config);
/* etc. */

这是我的控制者:

public class IdentifierController : ApiController {

    private readonly IIdentifierGenerator _identifierGenerator;

    public IdentifierController(IIdentifierGenerator identifierGenerator) {
        _identifierGenerator = identifierGenerator;
    }

    public long Get(string id) {
        var type = Type.GetType(id, false, true);
        return type == null ? -1 : _identifierGenerator.GetIdentifier(type);
    }
}

现在,当我调用action方法时,我收到此错误:

  

跨线程使用LifetimeScope实例是不安全的。使   确保寿命范围内的完整操作得到   在同一个线程内执行并确保LifetimeScope   实例在创建时放置在同一个线程上。部署   在ManagedThreadId 28的线程上调用,但是创建于   ID为29的线程。

我在哪里做错了?你能帮忙吗?

1 个答案:

答案 0 :(得分:2)

Simple Injector中的Lifetime Scope生活方式旨在用于单个线程。在多个线程上运行它(甚至调用Dispose)不是线程安全的。然而,Web API自托管将创建的作用域部署在不同的线程上,甚至可以将控制器安排在与创建生命周期作用域不同的线程上运行。由于这不安全,Simple Injector会在这种情况下抛出异常。

正如我在this讨论中解释的那样,我不知道在Web API级别有一个很好的解决方案,但是当转向基于消息的架构时,问题就完全消失了,因为你可以注入{控制器中的{1}}并使用装饰器装饰该控制器,该装饰器将Lifetime范围行为添加到命令处理程序。这样,您应该使用不会创建生命周期范围的更简单的解析程序替换ICommandHandler<TCommand>。我在讨论中解释了它,并提到了其他SO答案和博文。我知道你已经读过这篇文章,因为你已经提到了SO答案,但这是我能给你的最好的。