How can I inject different implementation of object for a specific class?
For example, in Unity, I can define two implementations of IRepository
container.RegisterType<IRepository, TestSuiteRepositor("TestSuiteRepository"); container.RegisterType<IRepository, BaseRepository>();
and call the needed implementation
public BaselineManager([Dependency("TestSuiteRepository")]IRepository repository)
Resolve dependencies using IServiceProvider You can use the IServiceCollection interface to create a dependency injection container. Once the container has been created, the IServiceCollection instance is composed into an IServiceProvider instance. You can use this instance to resolve services.
When you make it explicit, you've got basically two options: 1. Configure the DI to return transient objects and dispose these objects yourself. 2. Configure a factory and instruct the factory to create new instances.
In addition to @adem-caglin answer I'd like to post here some reusable code I've created for name-based registrations.
UPDATE Now it's available as nuget package.
In order to register your services you'll need to add following code to your Startup
class:
services.AddTransient<ServiceA>(); services.AddTransient<ServiceB>(); services.AddTransient<ServiceC>(); services.AddByName<IService>() .Add<ServiceA>("key1") .Add<ServiceB>("key2") .Add<ServiceC>("key3") .Build();
Then you can use it via IServiceByNameFactory
interface:
public AccountController(IServiceByNameFactory<IService> factory) { _service = factory.GetByName("key2"); }
Or you can use factory registration to keep the client code clean (which I prefer)
_container.AddScoped<AccountController>(s => new AccountController(s.GetByName<IService>("key2")));
Full code of the extension is in github.
As @Tseng pointed, there is no built-in solution for named binding. However using factory method may be helpful for your case. Example should be something like below:
Create a repository resolver:
public interface IRepositoryResolver { IRepository GetRepositoryByName(string name); } public class RepositoryResolver : IRepositoryResolver { private readonly IServiceProvider _serviceProvider; public RepositoryResolver(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public IRepository GetRepositoryByName(string name) { if(name == "TestSuiteRepository") return _serviceProvider.GetService<TestSuiteRepositor>(); //... other condition else return _serviceProvider.GetService<BaseRepositor>(); } }
Register needed services in ConfigureServices.cs
services.AddSingleton<IRepositoryResolver, RepositoryResolver>(); services.AddTransient<TestSuiteRepository>(); services.AddTransient<BaseRepository>();
Finally use it in any class:
public class BaselineManager { private readonly IRepository _repository; public BaselineManager(IRepositoryResolver repositoryResolver) { _repository = repositoryResolver.GetRepositoryByName("TestSuiteRepository"); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With