C# 自动插入呼叫

C# 自动插入呼叫,c#,solid-principles,open-closed-principle,C#,Solid Principles,Open Closed Principle,我有一个基于开闭原理的场景。我有一个Cart类,它有一个方法CalculateTotal()。此方法将模式和数量作为参数 根据模式,计算金额 public class Cart { ICalculator calculator; public Cart() { calculator = new Calculator(); } public decimal CalculateTotal(string MODE,decimal QTY)

我有一个基于开闭原理的场景。我有一个
Cart
类,它有一个方法
CalculateTotal()
。此方法将
模式
数量
作为参数

根据
模式
,计算金额

public class Cart
{
    ICalculator calculator;
    public Cart()
    {
        calculator = new Calculator();
    }
    public decimal CalculateTotal(string MODE,decimal QTY)
    {
        return calculator.CalculateTotal(MODE, QTY);
    }
}

public interface ICalculator
{
    decimal CalculateTotal(string MODE, decimal QTY);
}

public class Calculator : ICalculator
{
    private readonly List<IRule> rules;

    public Calculator()
    {
        rules = new List<IRule>();
        rules.Add(new OrdinaryRule());
        rules.Add(new SpecialRule());
        rules.Add(new OfferRule());
    }

    public decimal CalculateTotal(string MODE, decimal QTY)
    {
        return rules.First(x => x.IsMatch(MODE)).CalculateTotal(QTY);
    }
}

public interface IRule
{
    bool IsMatch(string MODE);
    decimal CalculateTotal(decimal QTY);
}

public class OrdinaryRule : IRule
{
    public decimal CalculateTotal(decimal QTY)
    {
        return QTY * 2m;
    }

    public bool IsMatch(string MODE)
    {
        return MODE.StartsWith("ORD");
    }
}
公共类购物车
{
计算器;
公共购物车()
{
计算器=新计算器();
}
公共十进制计算器总计(字符串模式,十进制数量)
{
返回计算器.CalculateTotal(模式、数量);
}
}
公共接口计算器
{
十进制计算器总计(字符串模式,十进制数量);
}
公共类计算器:ICalculator
{
私有只读列表规则;
公共计算器()
{
规则=新列表();
添加(新的OrdinaryRule());
添加(新的SpecialRule());
添加(新要约());
}
公共十进制计算器总计(字符串模式,十进制数量)
{
返回规则.First(x=>x.IsMatch(MODE)).CalculateTotal(数量);
}
}
公共接口病毒
{
布尔IsMatch(字符串模式);
十进制计算器总计(十进制数量);
}
公共类普通规则:IRule
{
公共十进制计算器总计(十进制数量)
{
退货数量*2m;
}
公共布尔IsMatch(字符串模式)
{
返回模式。使用“ORD”启动;
}
}
如果我需要添加一个新规则,比如说
FestivalRule
,那么我可以实现接口并创建一个新规则,然后将该规则添加到
Calculator()
构造函数中

我仍然觉得我在修改
计算器


有没有什么方法可以让我不必添加/修改
计算器
类,而新规则仍然适用

当前的设计仍然将类与实现问题紧密结合在一起


使用策略模式和显式依赖原则注入依赖项

public class Cart {
    private readonly ICalculator calculator;

    public Cart(ICalculator calculator) {
        this.calculator = calculator;
    }

    public decimal CalculateTotal(string MODE, decimal QTY) {
        return calculator.CalculateTotal(MODE, QTY);
    }
}

public class Calculator : ICalculator {
    private readonly List<IRule> rules;

    public Calculator(IEnumerable<IRule> rules) {
        this.rules = new List<IRule>(rules);
    }

    public decimal CalculateTotal(string MODE, decimal QTY) {
        return rules.First(x => x.IsMatch(MODE)).CalculateTotal(QTY);
    }
}
公共类购物车{
专用只读计算器;
公共购物车(ICalculator计算器){
this.calculator=计算器;
}
公共十进制计算器总计(字符串模式,十进制数量){
返回计算器.CalculateTotal(模式、数量);
}
}
公共类计算器:ICalculator{
私有只读列表规则;
公共计算器(IEnumerable规则){
this.rules=新列表(规则);
}
公共十进制计算器总计(字符串模式,十进制数量){
返回规则.First(x=>x.IsMatch(MODE)).CalculateTotal(数量);
}
}
因此,现在无论是使用纯DI还是容器,这些类都与实现问题解耦,可以允许在不修改源代码(OCP)的情况下扩展它们的行为

列表规则=新建列表();
添加(新的OrdinaryRule());
添加(新的SpecialRule());
添加(新要约());

添加(新的节日规则())//你需要的是一个。IOC容器使用策略模式和显式依赖原则注入规则集合。当前的设计仍然将计算器与实现问题紧密结合。
List<IRule> rules = new List<IRule>();
rules.Add(new OrdinaryRule());
rules.Add(new SpecialRule());
rules.Add(new OfferRule());
rules.Add(new FestivalRule()); //<<<

var calculator = new Calculator(rules);

var cart = new Cart(calculator);

//...