Reputation: 41
I'm trying to use .NET core dependency injection but can't understand how to inject dependency for my scenario. I've an interface
public interface IDataProvider()
{
public int GetData()
}
This interface was implemented by two classes
public class GoldCustomer:IDataProvider
{
public int GetData()
{
//implementation for gold customer
}
}
another class
public class SilverCustomer:IDataProvider
{
public int GetData()
{
//implementation for silver customer
}
}
Now I'm trying to configure dependency
public void ConfigureServices(IServiceCollection services)
{
//here i want to inject either gold customer or silver customer based on the scenario
services.AddTransient<IDataProvider, GoldCustomer>();
}
Is it possible to inject dependency based on some condition?
Upvotes: 0
Views: 844
Reputation: 6881
You can inject the dependencies of both classes into the project, and then you can put the parameters GoldCustomer
or SilverCustomer
that your current project needs to use in the appsetting.json file, and then decide which class to get the data returned by obtaining the parameters of the appsetting.
In appsetting.json file:
"AppSettings": {
"CurrentCustomer": "SilverCustomer"
}
Create this class to get value from appsetting.json file:
public class AppSettings
{
public string CurrentCustomer { get; set; }
}
Inject IDataProvider and AppSettings in startup.cs :
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
services.AddScoped<IDataProvider, GoldCustomer>();
services.AddScoped<IDataProvider, SilverCustomer>();
Here is the class:
public interface IDataProvider
{
public int GetData();
}
public class GoldCustomer : IDataProvider
{
public int GetData()
{
return 100;
}
}
public class SilverCustomer : IDataProvider
{
public int GetData()
{
return 200;
}
}
Controller:
public class HomeController : Controller
{
private readonly IEnumerable<IDataProvider> _dataProviders;
private AppSettings AppSettings { get; set; }
public HomeController(MyDbContext context, IEnumerable<IDataProvider> dataProviders, IOptions<AppSettings> settings)
{
_dataProviders = dataProviders;
AppSettings = settings.Value;
}
public IActionResult Index()
{
// this will get the data 200 which returned by SilverCustomer because the AppSettings.CurrentCustomer is SilverCustomer
var message = _dataProviders.FirstOrDefault(h => h.GetType().Name == AppSettings.CurrentCustomer)?.GetData();
}
}
More details, you can also refer to this.
Here is the test result:
Upvotes: 1
Reputation: 11
I hope what you are trying achieve after applying dependency injection as demonstrated by @Asherguru Answer Or you can apply Strategy pattern example illustrated below
namespace DemoInject.Services
{
public interface IStrategy
{
public int GetData();
}
}
namespace DemoInject.Services
{
public interface IDiamondCustomer: IStrategy
{
}
public class DiamondCustomer : IDiamondCustomer
{
public int GetData()
{
return 5000;
}
}
}
namespace DemoInject.Services
{
public interface ISilverCustomer: IStrategy
{
}
public class SilverCustomer : ISilverCustomer
{
public int GetData()
{
return 2000;
}
}
}
On Start up class
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IDiamondCustomer, DiamondCustomer>();
services.AddTransient<ISilverCustomer, SilverCustomer>();
services.AddControllers();
}
And On Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DemoInject.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace DemoInject.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
private IStrategy strategy;
private IDiamondCustomer diamondCustomer;
private ISilverCustomer silverCustomer;
public WeatherForecastController(ILogger<WeatherForecastController> logger, IDiamondCustomer diamondCustomer, ISilverCustomer silverCustomer)
{
_logger = logger;
this.diamondCustomer = diamondCustomer;
this.silverCustomer = silverCustomer;
}
[HttpGet("CheckOperation/{Id}")]
public int CheckOperation(int Id)
{
//Basically identify customer if a is even then silver else diamond
if (Id % 2 == 0)
{
this.strategy = this.silverCustomer;
}
else
{
this.strategy = this.diamondCustomer;
}
return this.strategy.GetData();
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
}
Call to CheckOperation with number even will result to Silver call and Diamond to else
Upvotes: 1
Reputation: 1741
Create new interface for GoldCustomer and SilverCustomer. Don't need to add GetData in IGoldCustomer and ISilverCustomer as it has IDataProvider's GetData() already.
public interface ISilverCustomer : IDataProvider
{
}
public interface IGoldCustomer : IDataProvider
{
}
Then inject dependency in Startup.cs
services.AddTransient<IGoldCustomer, GoldCustomer>();
services.AddTransient<ISilverCustomer, SilverCustomer>();
Upvotes: 1