2016-06-28 1 views
0

.NETのAPIコントローラプロジェクトでは、私が使用しているサービス、たとえばSomeServiceが必要です(要求ごとまたはSomeServiceインスタンスごとではありません)(ただし、関連性はないと思いますが、この初期化部分:それはSomeServiceのすべてのインスタンスに対してこれを行うと、unnecessarely高価であるAPIが作成された後のためAzureストレージにいくつかのセットアップを行いますのでGlobal.asaxのAutofac - DependencyResolver.Current.GetService <>()から作成されたInstancePerRequest - いつ解放されますか?

new SomeService().Init(); 

に次の行があった、私は。依存関係注入のためにAutofacを使用します。SomeServiceISomeServiceInstancePerRequestと登録します(SomeServiceはスレッドセーフではないため)。したがって、今度はSomeSerを初期化します。コンテナからのインスタンスを経由してGlobal.asaxの副。私はそれがこのエラーに

An exception of type 'Autofac.Core.DependencyResolutionException' occurred in Autofac.dll but was not handled in user code 

Additional information: No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself. 

を与える

container.Resolve<ISomeService>().Init(); 

に、容器からインスタンスを取得しようとすると、エラーの説明で提案されているようしかし、そのためGlobal.asaxの中、私はインスタンスを取得します。私が知りたいのは何

DependencyResolver.Current.GetService<ISomeService>().Init(); 

は私がCurrentから取得SomeServiceインスタンスを解放またはされていないということでしょうか?実際のリクエストはないので、わかりません。最悪の場合、newでコンクリートからインスタンスを取得できます。

答えて

1

Single Responsibility Principleを破る1つのコンポーネントに2つの責任をマージしようとしています。

これを解決するには、紺色の記憶域を初期化するコンポーネント(たとえばIStorageProvider)とそのジョブを実行する別のコンポーネントでコンポーネントを分割できます。 IStorageProviderSingleInstanceと宣言され(必要に応じてIStartableを実装します)、もう1つのコンポーネントはこのコンポーネントを使用します。

public class AzureStorageProvider : IStorageProvider, IStartable 
{ 
    public void Start() 
    { 
     // initialize storage 
     this._storage = new ... 
    } 
} 


public class SomeService : ISomeService 
{ 
    public SomeService(IStorageProvider storageProvider) 
    { 
     this._storageProvider = storageProvider; 
    } 

    private readonly IStorageProvider _storageProvider; 

    public void Do() 
    { 
     // do things with storage 
     this._storageProvider.Storage.ExecuteX(); 
    } 
} 

および登録:

builder.RegisterType<AzureStorageProvider>().As<IStorageProvider>().SingleInstance(); 
builder.RegisterType<SomeService>().As<ISomeService>().InstancePerRequest(); 

あなたもIStorageを登録しSomeServiceがIStorageに直接依存し、工場とし​​てIStorageProviderを使用させることができます。

builder.Register(c => c.Resolve<IStorageProvider>().Storage).As<IStorage>(); 
+0

あなたにはいくつかの点があります。 IStartableは良い解決策に見えますが、サービスを含むdllに特定のコンテナ(IStartableなど)に関連するものを追加したくありません。オートファックを使用できるものもあれば、他のものを使用するものもあります。また、私が初期化のために別のサービスを構築してシングルトンとして登録する場合、そのインスタンスも解放されません。それは本のほうが多いです、私は同意します。しかし、実際には何も変わりません。私は正しい? –

+0

シングルトンとしてイニシャライザを登録すると、アプリケーションが停止するとインスタンスが破棄されます。しかし、私はあなたがそれを処分する必要がないので本当の問題だとは思わない、私が理解するように、あなたは 'SomeService' –

関連する問題