推奨される方法は、オプションパターンを使用することであることに注意してください。ただし、実用的でない場合(パラメーターが実行時にのみ認識され、起動/コンパイル時には認識されない場合)、または依存関係を動的に置き換える必要があるユースケースがあります。
単一の依存関係(文字列、整数、または別のタイプの依存関係)を置き換える必要がある場合、または文字列/整数パラメーターのみを受け入れるサードパーティライブラリを使用していてランタイムパラメーターが必要な場合に非常に便利です。
CreateInstance(IServiceProvider、Object [])をショートカットとして試すことができます(文字列パラメーター/値型/プリミティブ(int、float、string)、未テストで動作するかどうかは わかりません)(試してみて、動作を確認しただけです。複数の文字列パラメータ)すべての依存関係を手動で解決するのではなく:
_serviceCollection.AddSingleton<IService>(x =>
ActivatorUtilities.CreateInstance<Service>(x, "");
);
パラメーター(CreateInstance<T>
/の最後のパラメーターCreateInstance
)は、置き換える必要のあるパラメーターを定義します(プロバイダーから解決されません)。それらは、表示されるとおりに左から右に適用されます(つまり、最初の文字列は、インスタンス化されるタイプの最初の文字列型パラメーターに置き換えられます)。
ActivatorUtilities.CreateInstance<Service>
サービスを解決し、この単一のアクティベーションのデフォルト登録の1つを置き換えるために、多くの場所で使用されます。
たとえば、という名前のクラスMyService
がIOtherService
ありILogger<MyService>
、依存関係としてがあり、サービスを解決したいが、デフォルトのサービスIOtherService
(たとえばOtherServiceA
)をOtherServiceB
に置き換えたい場合は、次のようにすることができます。
myService = ActivatorUtilities.CreateInstance<Service>(serviceProvider, new OtherServiceB())
次に、の最初のパラメータが注入されますが、残りのパラメータはコンテナからIOtherService
取得OtherServiceB
さOtherServiceA
れます。
これは、依存関係が多く、単一の依存関係を特別に扱いたい場合に役立ちます(つまり、データベース固有のプロバイダーを、要求中または特定のユーザー用に構成された値に置き換えます。これは、実行時および要求中にのみ認識され、アプリケーションのビルド/起動時ではありません)。
代わりに、ActivatorUtilities.CreateFactory(Type、Type [])メソッドを使用してファクトリメソッドを作成することもできます。これは、GitHubリファレンスとベンチマークのパフォーマンスが向上するためです。
後者は、タイプが非常に頻繁に解決される場合(SignalRやその他の要求の高いシナリオなど)に役立ちます。基本的に、ObjectFactory
ビアを作成します
var myServiceFactory = ActivatorUtilities.CreateFactory(typeof(MyService), new[] { typeof(IOtherService) });
次に、それを(変数などとして)キャッシュし、必要に応じて呼び出します
MyService myService = myServiceFactory(serviceProvider, myServiceOrParameterTypeToReplace);
##更新:文字列と整数でも機能することを確認するために自分で試してみましたが、実際に機能します。ここに私がテストした具体的な例があります:
class Program
{
static void Main(string[] args)
{
var services = new ServiceCollection();
services.AddTransient<HelloWorldService>();
services.AddTransient(p => p.ResolveWith<DemoService>("Tseng", "Stackoverflow"));
var provider = services.BuildServiceProvider();
var demoService = provider.GetRequiredService<DemoService>();
Console.WriteLine($"Output: {demoService.HelloWorld()}");
Console.ReadKey();
}
}
public class DemoService
{
private readonly HelloWorldService helloWorldService;
private readonly string firstname;
private readonly string lastname;
public DemoService(HelloWorldService helloWorldService, string firstname, string lastname)
{
this.helloWorldService = helloWorldService ?? throw new ArgumentNullException(nameof(helloWorldService));
this.firstname = firstname ?? throw new ArgumentNullException(nameof(firstname));
this.lastname = lastname ?? throw new ArgumentNullException(nameof(lastname));
}
public string HelloWorld()
{
return this.helloWorldService.Hello(firstName, lastName);
}
}
public class HelloWorldService
{
public string Hello(string name) => $"Hello {name}";
public string Hello(string firstname, string lastname) => $"Hello {firstname} {lastname}";
}
static class ServiceProviderExtensions
{
public static T ResolveWith<T>(this IServiceProvider provider, params object[] parameters) where T : class =>
ActivatorUtilities.CreateInstance<T>(provider, parameters);
}
プリント
Output: Hello Tseng Stackoverflow