3

我阅读了这些(++++)页面,但我不知道该怎么做。

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

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 实例在创建时被释放在同一个线程上。Dispose 在 ManagedThreadId 28 的线程上调用,但在 id 为 29 的线程上创建。

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

4

1 回答 1

2

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

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

于 2013-05-19T22:20:46.303 回答