2016-12-13 5 views
2

.Net Coreが発生しましたが、現在はDIエンジンに直面しています。IServiceProviderはシングルトンインスタンスを返しません

マイプロジェクトはクラスライブラリなので、aspのバインディングはここでは無関係です。

DI作業を行うためにthis articleのヒントに従っています。

今、ジューシーな部分へ:

私はこのようになり、サービスプロバイダをした:

public static class ServiceProvider 
    { 
     public static IServiceProvider GetServiceProvider() 
     { 
      var services = new ServiceCollection(); 

      //Singletons 
      services.AddSingleton<IInstance, Instance>(); 

      //Transients 
      services.AddTransient<IDate, Date>(); 
      services.AddTransient<IMath, Math>(); 
      services.AddTransient<INumber, Number>(); 
      return services.BuildServiceProvider(); 
     } 
    } 

私は、このようになります静的クラスでそれを実行しようとしている:

public static class MySingleton 
    { 
     public static IInstance Instance 
      => ServiceProvider.GetServiceProvider().GetService<IInstance>(); 
    } 

とシングルトン動作をテストするために、私はこのようにそれをテストしています

テスト結果がネガティブに戻ってきて、個別の参照の後に単一の参照を持つ代わりに(私はシングルトンなので)、まだ100個のインスタンスが残っています。

私は何か間違っていますか?

設定に何か不足しましたか?

+1

( 'ServiceProvider.GetServiceProvider()'を呼び出して) 'MySingleton.Instance'にアクセスするたびに、' IServiceProvider'の新しいインスタンスを作成しています。 – kiziu

+0

私は 'BuildServiceProvider()'が自分の設定をシングルトンとして保持していると仮定していました...そういう場合は、レイジーの読み込みやプロバイダの静的インスタンスの保守が必要ですか? – shirbr510

+1

ソースコードに基づいて、私は 'ServiceProvider'を共有するDIに関与するクラスには' static'修飾子を見ません。はい、あなたのアプリケーションに 'ServiceProvider'の単一のインスタンスを保持するのはあなたに任されています。 – kiziu

答えて

2

あなたの問題は、このコードブロックである:

public static class MySingleton 
{ 
    public static IInstance Instance 
     => ServiceProvider.GetServiceProvider().GetService<IInstance>(); 
} 

あなたはここで何をしているServiceProvider.GetServiceProvider().GetService<IInstance>()あなたが財産にアクセスするたびに呼び出すことです。つまり、実際にはにはシングルトンがありません。何がやりたいことは一度シングルトンインスタンスを設定することです。また

public static class MySingleton 
{ 
    public static IInstance Instance 
    { 
     get; 
    } = ServiceProvider.GetServiceProvider().GetService<IInstance>(); 
} 

、あなたのサービスを作成するときに同様の問題を抱えています。 GetServiceProvider()と呼ぶたびに、新しいServiceCollectionを作成します。あなたはおそらくそれを望んでいません。あなたは、おそらくこのような何かをしたい:

public static class ServiceProvider 
{ 
    private static IServiceProvider serviceProvider = null; 

    public static IServiceProvider GetServiceProvider() 
    { 
     if (serviceProvider == null) 
     { 
      var services = new ServiceCollection(); 

      //Singletons 
      services.AddSingleton<IInstance, Instance>(); 

      //Transients 
      services.AddTransient<IDate, Date>(); 
      services.AddTransient<IMath, Math>(); 
      services.AddTransient<INumber, Number>(); 

      serviceProvider = services.BuildServiceProvider(); 
     } 
     return serviceProvider; 
    } 
} 
+0

'AddSingleton ()の全体的なポイントは、私が自分自身を管理すべきではないシングルトンを追加することです.. – shirbr510

+0

とkiziuが既に述べたように' return services.BuildServiceProvider(); 'が私の問題でした – shirbr510

+0

@ shirbr510:それでは、 'GetServiceProvider'に新しいサービスコレクションを作成するべきではないでしょう。それは私のポストにもあります。 – Sefe

0

問題:

私の問題は

ソリューションMySingletonで私IserviceProviderインスタンスを保持していないに敷設

TL; DR

静的インスタンスがIserviceProvider

012である

コードのリファクタリング、次のように見えるように

リファクタリングServiceProvider

パブリッククラスLodashServiceProvider { プライベート静的読み取り専用レイジーLazyServiceProvider。

static LodashServiceProvider() 
    { 
     LazyServiceProvider = new Lazy<IServiceProvider>(InitializeServiceProvider); 
    } 

    public static IServiceProvider GetServiceProvider() => LazyServiceProvider.Value; 

    private static IServiceProvider InitializeServiceProvider() 
    { 
     var services = new ServiceCollection(); 

     //Singletons 
     services.AddSingleton<ILodashInstance, LodashInstance>(); 

     //Transients 
     services.AddTransient<ILodashDate, LodashDate>(); 
     services.AddTransient<ILodashMath, LodashMath>(); 
     services.AddTransient<ILodashNumber, LodashNumber>(); 
     return services.BuildServiceProvider(); 
    } 
} 

私は質問にその解決策についてKiziu & Sefeに感謝したいと思います。

関連する問題