권장되는 방법은 옵션 패턴 을 사용하는 것 입니다. 그러나 실용적이지 않거나 (파라미터가 시작 / 컴파일 시간이 아닌 런타임에만 알고있는 경우) 또는 종속성을 동적으로 교체해야하는 사용 사례가 있습니다.
단일 종속성 (문자열, 정수 또는 다른 유형의 종속성)을 교체해야하거나 문자열 / 정수 매개 변수 만 허용하고 런타임 매개 변수가 필요한 타사 라이브러리를 사용할 때 매우 유용합니다.
CreateInstance (IServiceProvider, Object []) 를 바로 가기로 사용해 볼 수 있습니다 ( 문자열 매개 변수 / 값 유형 / 기본 형식 (int, float, string), 테스트되지 않은 상태에서 작동하는지 확실하지 않음) (그냥 시도하고 작동하는지 확인했습니다. 여러 문자열 매개 변수) 모든 단일 종속성을 수동으로 해결하는 대신 :
_serviceCollection.AddSingleton<IService>(x =>
ActivatorUtilities.CreateInstance<Service>(x, "");
);
매개 변수 ( CreateInstance<T>
/의 마지막 매개 변수 CreateInstance
)는 교체해야하는 매개 변수를 정의합니다 (제공자에서 확인되지 않음). 표시되는대로 왼쪽에서 오른쪽으로 적용됩니다 (즉, 첫 번째 문자열은 인스턴스화 할 유형의 첫 번째 문자열 유형 매개 변수로 대체됩니다).
ActivatorUtilities.CreateInstance<Service>
서비스를 해결하고이 단일 활성화에 대한 기본 등록 중 하나를 대체하기 위해 여러 곳에서 사용됩니다.
예를 들어라는 클래스 MyService
가 IOtherService
있고 ILogger<MyService>
종속성으로,이 있고 서비스를 해결하고 싶지만 기본 서비스 IOtherService
(예 : 해당 OtherServiceA
)를로 바꾸려면 OtherServiceB
다음과 같이 할 수 있습니다.
myService = ActivatorUtilities.CreateInstance<Service>(serviceProvider, new OtherServiceB())
다음의 첫 번째 매개 변수는 IOtherService
얻을 것 OtherServiceB
보다는, 주입 OtherServiceA
하지만, 나머지 매개 변수는 컨테이너에서 올 것이다.
이는 종속성이 많고 단일 공급자 만 특별히 처리하려는 경우에 유용합니다 (예 : 데이터베이스 특정 공급자를 요청 중 또는 특정 사용자에 대해 구성된 값으로 교체합니다. 런타임 및 요청 중에 만 알고있는 것). 애플리케이션이 빌드 / 시작될 때가 아닙니다.)
또한 ActivatorUtilities.CreateFactory (Type, Type []) 메서드 를 사용하여 더 나은 성능을 제공하는 GitHub Reference 및 Benchmark를 제공하므로 대신 팩토리 메서드 를 만들 수 있습니다 .
나중에 유형이 매우 자주 확인 될 때 유용합니다 (예 : 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