ASP.NET Core 如何使用 DI 注入特定接口实现
How to inject specific interface implementation using DI in ASP NET Core
我有以下问题。我有一个由 2 类 实现的接口。其中一个 类 完成实际工作,而另一个使用提到的第一个。
在实例化一种类型的对象时,如何告诉框架使用接口的特定实现?
我希望控制器获得外观实现而不是真正的实现:
public interface IDependency
{
void Method();
}
public class Real : IDependency
{
public void Method()
{
}
}
public class Facade : IDependency
{
private IDependency dependency;
Facade(IDependency dependency) //I want a Real here
{
this.dependency=dependency;
}
public void Method()=>dependency.Method();
}
public MyController : Controller
{
private IDependency dependency;
MyController(IDependency dependency) //I want the `Facade` here not the `Real`
{
this.dependency=dependency;
}
[HttpGet]
[Route("[some route]")]
public async Task CallMethod()
{
await this.dependency.Method();
}
}
正如你在上面的例子中看到的,我需要一个 Real
类型的 IDependency
注入到我的 Facade
中,而我需要一个 Facade
类型的IDependency
注入了我的 MyController
。
这怎么可能?
Microsoft.Extensions.DependencyInjection 没有办法做到这一点。你所能做的就是注入 all 实现,即通过 List<IDependency>
。然后,您可以实现您想要选择的任何手动逻辑,并从那里的可用选项中进行选择。
如果您对这些 class 有任何控制权,最好简单地实现一个不同的接口,以区分两者。例如,您可以创建一个继承自 IDependency
的 IFacadeDependency
接口,然后让 Facade
class 实现它。然后,你可以注入 IFacadeDependency
并得到你想要的。
按如下方式注册您的依赖项:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddTransient<IDependency>(_ => new Facade(new Real()));
}
如果您有其他控制器需要不同的 IDependency 实现,您将希望将您的控制器注册为服务,从而允许覆盖注册。例如,如果您希望大多数控制器将 IDependency 解析为 Real,但只有 MyController 将 IDependency 解析为 Facade,您可以这样做:
public void ConfigureServices(IServiceCollection services)
{
// Adds controllers as services, allowing their registrations to be overwritten.
services.AddMvc().AddControllersAsServices();
//services.AddControllers(); REMOVE THIS
// Makes Real the default implementation of IDependency
services.AddTransient<IDependency, Real>();
// Overwrite the default registration of MyController to instantiate using Facade.
services.AddTransient<MyController>(sp =>
new MyController(new Facade(sp.GetService<IDependency>())));
}
我有以下问题。我有一个由 2 类 实现的接口。其中一个 类 完成实际工作,而另一个使用提到的第一个。 在实例化一种类型的对象时,如何告诉框架使用接口的特定实现? 我希望控制器获得外观实现而不是真正的实现:
public interface IDependency
{
void Method();
}
public class Real : IDependency
{
public void Method()
{
}
}
public class Facade : IDependency
{
private IDependency dependency;
Facade(IDependency dependency) //I want a Real here
{
this.dependency=dependency;
}
public void Method()=>dependency.Method();
}
public MyController : Controller
{
private IDependency dependency;
MyController(IDependency dependency) //I want the `Facade` here not the `Real`
{
this.dependency=dependency;
}
[HttpGet]
[Route("[some route]")]
public async Task CallMethod()
{
await this.dependency.Method();
}
}
正如你在上面的例子中看到的,我需要一个 Real
类型的 IDependency
注入到我的 Facade
中,而我需要一个 Facade
类型的IDependency
注入了我的 MyController
。
这怎么可能?
Microsoft.Extensions.DependencyInjection 没有办法做到这一点。你所能做的就是注入 all 实现,即通过 List<IDependency>
。然后,您可以实现您想要选择的任何手动逻辑,并从那里的可用选项中进行选择。
如果您对这些 class 有任何控制权,最好简单地实现一个不同的接口,以区分两者。例如,您可以创建一个继承自 IDependency
的 IFacadeDependency
接口,然后让 Facade
class 实现它。然后,你可以注入 IFacadeDependency
并得到你想要的。
按如下方式注册您的依赖项:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddTransient<IDependency>(_ => new Facade(new Real()));
}
如果您有其他控制器需要不同的 IDependency 实现,您将希望将您的控制器注册为服务,从而允许覆盖注册。例如,如果您希望大多数控制器将 IDependency 解析为 Real,但只有 MyController 将 IDependency 解析为 Facade,您可以这样做:
public void ConfigureServices(IServiceCollection services)
{
// Adds controllers as services, allowing their registrations to be overwritten.
services.AddMvc().AddControllersAsServices();
//services.AddControllers(); REMOVE THIS
// Makes Real the default implementation of IDependency
services.AddTransient<IDependency, Real>();
// Overwrite the default registration of MyController to instantiate using Facade.
services.AddTransient<MyController>(sp =>
new MyController(new Facade(sp.GetService<IDependency>())));
}