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);
    }
}

ここで、アクション メソッドを呼び出すと、次のエラーが発生します。

スレッド間で 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 に答える