2016-07-12 1 views
0

私はコントローラにサービスを注入しようとしていますが、いくつかのパラメータに応じてサービスの異なるインスタンスを注入したいのです。実際にこの部分については機能していますが、私はそれを行うことができます。ASP.NETコア依存性注入:実行時にFuncデリゲートを使用して実行時にサービスが解決される

私が希望するのは、コンフィギュレーションファイルから取得したDRYルールを尊重して(自分自身を繰り返さないで)、IRepository<Database>という特定のインスタンスをロードすることです。

public abstract class FooServicesProvider 
{ 
    public Func<IServiceProvider, IRepository<Database>> DatabaseRepository = provider => 
    { 
     return null; 
    }; 
} 

public class FooFileSystemServicesProvider : FooServicesProvider 
{ 
    public new Func<IServiceProvider, IRepository<Database>> DatabaseRepository = provider => 
    { 
     //Specific code determining which database to use and create a new one if needed 
     //our databases are FOLDERS containing some files 
     //knowing how chosenDb.FullName is set is not important here 
     //[...] 
     var databaseRepository = new DatabaseFileSystemRepository(chosenDb.FullName); 
     databaseRepository.testProperty = "Foo value"; 
     return databaseRepository; 
    }; 
} 

お知らせ私のFuncのコードを再定義するために使用さ新しいキーワード:

は、私はこれらの2つのクラスを持っています。これはFuncデリゲートのために私が見つけた最良の方法です、私は非常に限られています、私はInterfaceでそれをオーバーライドすることはできません。

は今Startup.csの私ConfigureServices方法で私はこのコード

var fakeConfiguration = "File"; 
FooServicesProvider servicesProvider = null; 
if(fakeConfiguration == "File") 
{ 
    servicesProvider = new FooFileSystemServicesProvider(); 
} 
else 
{ 
    servicesProvider = new AnotherFooServicesProvider(); 
} 
//Here is the tricky part 
//This should call FooFileSystemServicesProvider.DatabaseRepository because of the "new" keyword, but it's NOT 
services.AddScoped<IRepository<Database>>(servicesProvider.DatabaseRepository); 

を持っている私の問題は、新しいキーワードは実行時に無視され、実行さfuncがで宣言されたものですされていることです派生クラスの代わりに私の基本クラス。

私はこれを行う場合は、

services.AddScoped<IRepository<Database>>((servicesProvider as FooFileSystemServicesProvider).DatabaseRepository); 

を働いているしかし、私は私のservicesProviderが最終的にされるタイプで知ることができないように私はそれをキャストする必要はありません。

私はサービスプロバイダのタイプを取得しようとしましたが、独自のタイプでキャストしましたが、タイプ変数とクラスが異なるため、コンパイラエラーが発生します。

実行時に良いFuncを実行するにはどうすればよいですか?ありがとう

+0

基本クラス 'virtual'の' DatabaseRepository'を作成し、派生型で 'override'を使用する必要があります。 – Steven

+0

デリゲートプロパティ宣言でoverrideによって新しいキーワードを置き換えます。それは動作しますか? –

+0

もちろん 'new'は基本クラスのメソッド/プロパティを隠し、それを置き換えたり上書きしたりしないので、' new'キーワードは無視されています... – Tseng

答えて

1

私は最終的に私が欲しいことをすることができた、実際にはそれほど難しくなかった、私の主な問題は、私のFuncは方法ではなく、代議員であったという事実を処理することでした。私はこの可変型を扱うのに慣れていない。

Startup.csで私のコードは変わらないが、ここで私のカスタムServicesProvider

public abstract class FooServicesProvider 
{ 
    public Func<IServiceProvider, IRepository<Database>> DatabaseRepository { get; protected set; } 
} 

public class FooFileSystemServicesProvider : FooServicesProvider 
{ 
    public FooFileSystemServicesProvider() 
    { 
     base.DatabaseRepository = GetDatabaseRepository; 
    } 

    private DatabaseFileSystemRepository GetDatabaseRepository(IServiceProvider serviceProvider) 
    { 
     //Specific code determining which database to use and create a new one if needed 
     //our databases are FOLDERS containing some files 
     //knowing how chosenDb.FullName is set is not important here 
     //[...] 
     var databaseRepository = new DatabaseFileSystemRepository(chosenDb.FullName); 
     databaseRepository.testProperty = "Foo value"; 
     return databaseRepository; 
    }   
} 

の新しいコードは、念のために、人々は不思議に思っているされていますDatabaseFileSystemRepositoryが場合インタフェースIRepository<Database>>

を実装するクラスです誰かが別の解決策を思いつき、私はそれを知ることが非常に不思議です。

関連する問題