Jay
Jay

Reputation: 41

.NET Core dependency injection to inject multiple dependencies

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

Answers (3)

LouraQ
LouraQ

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:

enter image description here

Upvotes: 1

Denis
Denis

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

Asherguru
Asherguru

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

Related Questions