3

現在、ServiceStack Web サービス アプリの DI コンテナーとして AutoFac を使用しています。配線とすべてを構成できますが、スコープのセクションを読んだ後、コンポーネントを登録するときにどのスコープを使用するのが最適かわかりません。私たちの特定のケースでは、リクエストが終了したらすぐに依存関係を破棄したいので (間違っている場合は修正してください)、PerHttpRequest スコープで問題ないと思います。

私の質問は、コンテナにこれをどのように設定するのですか? autofac に含まれているメソッド内に「PerHttpRequest」の有効期間スコープが見つからないようです。また、ServiceStack が舞台裏でこれを行うために何らかの自動魔法を行っているかどうかもわかりません。

.Net 4 の ServiceStack 3.9.35 で Autofac 3.0.1 を使用しています (MVC ではなく、通常の ASP ホストとして実行しています)。また、ここで説明するクラスをIContainer アダプターとして使用しています。

4

4 に答える 4

5

MVC への依存のオーバーヘッドを避けたかったので、最初の答えはうまくいきませんでした。

代わりに、Funq を使用して PerRequest ILifetimeScope を登録し、依存関係を解決する前に ConatinerAdaptor で ILifetimeScope を解決しました。

public class AutofacLifetimeScopeIocAdapter : IContainerAdapter
{
    private readonly Container _requestContainer;

    public AutofacLifetimeScopeIocAdapter(Funq.Container requestContainer)
    {
        _requestContainer = requestContainer;
    }


    public T Resolve<T>()
    {
        var currentContainer = _requestContainer.Resolve<ILifetimeScope>();

        return currentContainer.Resolve<T>();
    }

    public T TryResolve<T>()
    {
        var currentContainer = _requestContainer.Resolve<ILifetimeScope>();

        T result;

        if (currentContainer.TryResolve<T>(out result))
        {
            return result;
        }

        return default(T);
    }

}

次に、これで初期化します

_autofacContainerRoot = builder.Build();
        IContainerAdapter adapter = new AutofacLifetimeScopeIocAdapter(container);

        container.Register<ILifetimeScope>((c) => _autofacContainerRoot.BeginLifetimeScope())
            .ReusedWithin(ReuseScope.Request);

        container.Adapter = adapter;

次に、クリーンアップ

public override void OnEndRequest()
    {
        var currentContainer = _container.Resolve<ILifetimeScope>();
        currentContainer.Dispose();

        base.OnEndRequest();
    } 

これは、Autofac - SingleInstance、InstancePerDependency、そして現在は perRequest である InstancePerLifetimeScope に必要なように動作するようです。

HostContext.Instance.Items コレクションに対する Mythz の応答を使用して、

var currentContainer = _container.Resolve<ILifetimeScope>();

これにより、パフォーマンスが向上します。

于 2013-11-11T12:34:30.750 に答える
4

これを機能させる方法を理解したと思います (Autofac 2.6 を使用して、現在行き詰まっています)。次のアダプターと Autofac.Mvc3 パッケージを使用する必要があります。

public class AutofacIocAdapter : IContainerAdapter
{
    private readonly IContainer _autofacRootContainer;
    private readonly Container _funqContainer;

    public AutofacIocAdapter(IContainer autofacRootContainer, Container funqContainer)
    {
        // Register a RequestLifetimeScopeProvider (from Autofac.Integration.Mvc) with Funq
        var lifetimeScopeProvider = new RequestLifetimeScopeProvider(autofacRootContainer,null);
        funqContainer.Register<ILifetimeScopeProvider>(x => lifetimeScopeProvider);
        // Store the autofac application (root) container, and the funq container for later use
        _autofacRootContainer = autofacRootContainer;
        _funqContainer = funqContainer;
    }

    public T Resolve<T>()
    {           
        return ActiveScope.Resolve<T>();
    }

    public T TryResolve<T>()
    {
        T result;
        if (ActiveScope.TryResolve(out result))
        {
            return result;
        }
        return default(T);
    }

    private ILifetimeScope ActiveScope
    {
        get
        {
            // If there is an active HttpContext, retrieve the lifetime scope by resolving
            // the ILifetimeScopeProvider from Funq.  Otherwise, use the application (root) container.
            return HttpContext.Current == null
                        ? _autofacRootContainer
                        : _funqContainer.Resolve<ILifetimeScopeProvider>().GetLifetimeScope();
        }
    }
}

実装手順:

  1. Autofac.Mvc3 NuGet パッケージを Web プロジェクトに追加します (注: プロジェクトが MVC を使用していなくてもかまいませ。Mvc3 統合を使用できない Autofac 3 では、ソリューションが若干異なる場合があります)。
  2. 次の実装を使用して、Autofac 用のカスタム IContainerAdapter をフックするServiceStack IoCページに従います。
于 2013-03-15T15:32:21.820 に答える
2

2015 年 11 月 25 日更新: グローバル リクエストおよびレスポンス フィルターを使用して実装を変更しました。ServiceStack V3 と V4 の両方のソリューションをこのリポジトリに入れました。どちらのバージョンもnuget パッケージとして入手できます。

Application_BeginRequest で新しいスコープを開き、Application_EndRequest で破棄することで、この問題を解決しました。コンテナー アダプターでは、このスコープが存在するかどうかを確認して使用し、存在しない場合はコンテナーを使用します。これにより、.InstancePerRequest() 登録スコープを使用できます。

ここで要点を説明します。

于 2015-04-15T09:34:28.427 に答える
2

ServiceStack の IOC のRequestScope は、ServiceStack の組み込み Funq IOCのみを参照することに注意してください。

AutoFac のような別の IOC コンテナで RequestScope を使用するには、通常、リクエストの最後に AutoFac に通知して、リクエスト スコープのインスタンスをすべてクリーンアップできるようにする必要があります。これを行うために、ServiceStack は、AppHostBase.OnEndRequest()各リクエストの最後にカスタム ロジックを実行するためにオーバーライドできるフックを提供します。

AutoFac のカスタム ライフタイム スコープがどのように機能するかはよくわかりませんが、詳細については次を参照してください。

ServiceStack でインスタンスを管理するのに役立つその他の情報は、HostContext.Instance.Itemsディクショナリに入れられたすべてのインスタンスまたは追加された使い捨て のすべてのインスタンスが、各リクエストの最後に自動的に破棄されるHostContext.Instance.TrackDisposableことです。

于 2013-02-12T16:43:31.477 に答える