IOC 反转控制容器,保留同时实现不同时间段价格计算的理解,不知对否

来源:6-8 【操作】反转控制与依赖注入

六拉克

2023-01-09

老师你好
纯接口思路
ICalculate putong = new ShippingCalculator();// 普通时间段计算运费类
ICalculate doubleEleven = new DoubleElevenShippingCalculator();//双十一时间段计算运费类
OrderProcessor orderProcessor;
//模拟今天日期是否是双十一的比较
if (DateTime.Now.Month == new DateTime(2023, 11, 11).Month && DateTime.Now.Day == new DateTime(2023, 11, 11).Day)
{
orderProcessor = new OrderProcessor(doubleEleven);
}
else
{
orderProcessor = new OrderProcessor(putong);
}
orderProcessor.Process(order);

以上是没有使用 IOC 反转控制容器 的,通过 一个日期比较,实例化不同 价格计算器对象。

// 配置 IOC 反转控制容器
var collection = new ServiceCollection();
collection.AddScoped<IOrderProcessor, OrderProcessor>();
//模拟今天日期是否是双十一的比较
if (DateTime.Now.Month == new DateTime(2023, 11, 11).Month && DateTime.Now.Day == new DateTime(2023, 11, 11).Day)
{
collection.AddScoped<ICalculate, DoubleElevenShippingCalculator>();
}
else
{
collection.AddScoped<ICalculate, ShippingCalculator>();
}

IServiceProvider serviceProvider = collection.BuildServiceProvider();
var orderProcessor = serviceProvider.GetService();

// 处理订单
orderProcessor.Process(order);
这段是模仿老师,使用 IOC 反转控制容器

我目前有点困惑的地方是,如果要实现不改代码情况下,是不是 也要加个 if 条件判断(通过时间比较后),注册不同的价格计算器到容器中。像这段
if (DateTime.Now.Month == new DateTime(2023, 11, 11).Month && DateTime.Now.Day == new DateTime(2023, 11, 11).Day)
{
collection.AddScoped<ICalculate, DoubleElevenShippingCalculator>();
}
else
{
collection.AddScoped<ICalculate, ShippingCalculator>();
}
这样经过时间比较判断后,后面调用的时候,出现不同计算。因为例子只有一个价格容器计算,我想保留2种都能针对不同情况的价格计算,这样改造运行和上面一样,实现了不同时间段的价格计算,但自己心里没底,不知是不是这样的思路。

写回答

1回答

阿莱克斯刘

2023-01-11

实际上IOC不仅可以注册单一的实现,它也同样可以注册接口的多重实现。所以,我们并不需要通过if...else...来按需注册,只需要把所有的实现全部丢进IOC就好了。

// 配置 IOC 反转控制容器
var collection = new ServiceCollection();
collection.AddScoped<IOrderProcessor, OrderProcessor>();
collection.AddScoped<ICalculate, DoubleElevenShippingCalculator>();
collection.AddScoped<ICalculate, ShippingCalculator>();

而在controler使用的时候,我们需要提取的是ICalculate服务列表而不是单独的ICalculate。使用操作符“is”,我们可以在if...else...通过对比类型来获得对应的计算服务。

public class xxxController
{
    private readonly IEnumerable<ICalculate> _calculators;
    public xxxController(IEnumerable<ICalculate> calculators)
    {
        _calculators = calculators;
    }
    public void Action()
    {
        ICalculate calculator;
        if (DateTime.Now.Month == new DateTime(2023, 11, 11).Month && DateTime.Now.Day == new DateTime(2023, 11, 11).Day) 
        {
            calculator = _calculators.FirstOrDefault(c => c is DoubleElevenShippingCalculator);
        }
        else 
        {
            calculator = _calculators.FirstOrDefault(c => c is ShippingCalculator);
        }
        // 其他业务逻辑....
    }
}
1
2
六拉克
谢谢老师 通过在 class xxxController 类里面 Action() 封装 不同的价格计算,让外面使用时,只关注IOC容器本身的注册
2023-01-11
共2条回复

C#速成指南--从入门到进阶,实战WPF与Unity3D开发

系统掌握C#核心和应用,获得全行业适配的技能

839 学习 · 198 问题

查看课程