Использование карты:
var map = new[]
{
new { Rule = (Func<Oobject, bool>) (x => x.Time > 0 && x.Something <= 499),
Value = .75m },
new { Rule = (Func<Oobject, bool>) (x => x.Time >= 500 && x.Something <= 999),
Value = .85m },
new { Rule = (Func<Oobject, bool>) (x => true),
Value = 0m }
};
var date = new Oobject { Time = 1, Something = 1 };
var rate = map.First(x => x.Rule(date)).Value;
Assert.That(rate, Is.EqualTo(.75m));
Мне нравится идея Rules Pattern
ответ @ LLL, но у него есть недостаток.
Рассмотрим следующий тест (NUnit):
[Test]
public void TestRulesUsingList()
var rules = new IRules[]{ new RuleNumberOne(), new RuleNumberTwo() };
var date = new Oobject { Time = 1, Something = 1 };
var rate = 0m;
foreach(var rule in rules)
rate = rule.Execute(date);
Assert.That(rate, Is.EqualTo(.75m));
}
тест не пройден. Хотя было вызвано RuleNumberOne
и возвращено ненулевое значение, впоследствии было вызвано RuleNumberTwo
и возвращено ноль, чтобы перезаписать правильное значение.
Чтобы воспроизвести логику if..else..else, она должна иметь возможность короткого замыкания.
Вот быстрое решение: изменить Execute
метод Интерфейс для возврата bool
, чтобы указать, следует ли исключить должны стрелять и добавить Value
свойство, чтобы получить decimal
ценность правила. Также добавьте правило defulat, которое alwasys оценивает true
и возвращает ноль. Затем измените реализацию (тест), чтобы получить значение первого правила для оценки истины:
[Test]
public void TestRulesUsingList2()
{
var rules = new IRules[]{ new RuleNumberOne(), new RuleNumberTwo(),
new DefaultRule() };
var date = new Oobject { Time = 1, Something = 1 };
var rate = rules.First(x => x.Execute(date)).Value;
Assert.That(rate, Is.EqualTo(.75m));
}
public class Oobject
{
public int Time { get; set; }
public int Something { get; set; }
}
public interface IRules
{
bool Execute(Oobject date);
decimal Value { get; }
}
public class RuleNumberOne : IRules
{
public bool Execute(Oobject date)
{
return date.Time > 0 && date.Something <= 499;
}
public decimal Value
{
get { return .75m; }
}
}
public class RuleNumberTwo : IRules
{
public bool Execute(Oobject date)
{
return date.Time >= 500 && date.Something <= 999;
}
public decimal Value
{
get { return .85m; }
}
}
public class DefaultRule : IRules
{
public bool Execute(Oobject date)
{
return true;
}
public decimal Value
{
get { return 0; }
}
}
Desing pattern? –
Это не скомпилирует –
@SriramSakthivel Вы можете четко сказать, что это код-макет, ight? –