【问题标题】:.NET Core dependency injection to inject multiple dependencies.NET Core 依赖注入以注入多个依赖项
【发布时间】:2020-12-20 05:17:35
【问题描述】:

我正在尝试使用 .NET 核心依赖注入,但不明白如何为我的场景注入依赖。我有一个界面

   public interface IDataProvider()
   {
     public int GetData()
    }

这个接口由两个类实现

   public class GoldCustomer:IDataProvider
     {
      public int  GetData()
          {
               //implementation for gold customer
          }
       }

另一个类

     public class SilverCustomer:IDataProvider
     {
      public int  GetData()
          {
               //implementation for silver customer
          }
       }

现在我正在尝试配置依赖项

   public void ConfigureServices(IServiceCollection services)
     {
       //here i want to inject either gold customer or silver customer based on the scenario
        services.AddTransient<IDataProvider, GoldCustomer>();
     }

是否可以根据某些条件注入依赖?

【问题讨论】:

  • 条件是什么?该条件是配置值(启动后不会更改)还是可以在运行时更改的东西?如果它在运行时发生变化,请描述该条件的来源(帖子、会话、数据库等)。请用代码示例演示。您的问题的正确答案取决于此信息。

标签: .net asp.net-core .net-core dependency-injection


【解决方案1】:

为 GoldCustomer 和 SilverCustomer 创建新界面。不需要在 IGoldCustomer 和 ISilverCustomer 中添加 GetData,因为它已经有 IDataProvider 的 GetData()。

public interface ISilverCustomer : IDataProvider
{
}

public interface IGoldCustomer : IDataProvider
{
}

然后在 Startup.cs 中注入依赖

services.AddTransient<IGoldCustomer, GoldCustomer>();
services.AddTransient<ISilverCustomer, SilverCustomer>();

【讨论】:

    【解决方案2】:

    我希望您在应用依赖注入后尝试实现@Asherguru 答案所证明的目标,或者您可以应用下图所示的策略模式示例

    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;
            }
        }
    }
    

    开课时

      // 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();
            }
    

    在控制器上

    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();
            }
        }
    }
    

    使用偶数调用 CheckOperation 将导致 Silver 调用,而 Diamond 调用 else

    【讨论】:

    • 策略模式允许您的代码更加抽象,但在您确定了您希望它执行的用户或场景之后
    • 就像你已经识别了用户,然后将策略接口传递给你的服务方法,实际的实现将被调用。
    【解决方案3】:

    你可以将这两个类的依赖注入到项目中,然后你可以把你当前项目需要用到的参数GoldCustomer或者SilverCustomer放到appsetting.json文件中,然后通过获取appsetting的参数来决定哪个类获取返回的数据。

    在 appsetting.json 文件中:

      "AppSettings": {
        "CurrentCustomer": "SilverCustomer"
      }
    

    创建此类以从 appsetting.json 文件中获取值:

     public class AppSettings
            {
                public string CurrentCustomer { get; set; }
            }
    

    在 startup.cs 中注入 IDataProvider 和 AppSettings :

      services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
                services.AddScoped<IDataProvider, GoldCustomer>();
                services.AddScoped<IDataProvider, SilverCustomer>();
    

    这是课程:

    public interface IDataProvider
        {
            public int GetData();
        }
        public class GoldCustomer : IDataProvider
        {
            public int GetData()
            {
                return 100;
            }
        }
        public class SilverCustomer : IDataProvider
        {
            public int GetData()
            {
                return 200;
            }
        }
    

    控制器:

          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();
    
                }
        }
    

    更多详情,也可以参考this

    这是测试结果:

    【讨论】:

      猜你喜欢
      • 2017-07-23
      • 2016-05-22
      • 1970-01-01
      • 2018-03-03
      • 2021-10-23
      • 1970-01-01
      • 2021-02-02
      • 1970-01-01
      • 2020-11-09
      相关资源
      最近更新 更多