你好,我有以下问题,我有一个接口是由2个类实现的,其中一个类做真正的工作,而其他使用第一个提到的,我如何告诉框架在实例化一个类型的对象时,使用一个特定的接口实现?我希望控制器得到的是facaded实现,而不是真正的实现。
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没有任何方法可以做到这一点。你能做的就是注入 都 实现,即通过 List<IDependency>
. 然后,你可以实现任何你喜欢的手动逻辑,从那里的可用选项中挑选。
如果你对这些类有任何控制,最好是简单地实现一个不同的接口,以区分两者。例如,你可以创建一个 IFacadeDependency
接口,继承自 IDependency
然后让你的 Facade
类来实现这个功能。然后,你可以注入 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>())));
}