当我需要检查某些值是否满足不同的条件时,我喜欢使用规范模式。规格如下:
public interface ISpecification<T>
{
bool IsSatisfiedBy(T value);
}
对于每组条件,您创建不同的规范类。在这里,您将需要范围规范(我将int
用作泛型类型以简化事情):
public class RangeSpecification : ISpecification<int>
{
private readonly int _from;
private readonly int _to;
public RangeSpecification(int from, int to)
{
_to = to;
_from = from;
}
public bool IsSatisfiedBy(int value)
{
return _from <= value && value <= _to;
}
}
以及值列表的规范(我们也可以将单个值视为列表规范):
public class InSpecification : ISpecification<int>
{
private readonly int[] _values;
public InSpecification(params int[] values)
{
_values = values;
}
public bool IsSatisfiedBy(int value)
{
return _values.Contains(value);
}
}
这已经足以测试以下条件:
var rangeSpec = new RangeSpecification(10, 15);
var is13inRange = rangeSpec.IsSatisfiedBy(13); // true
var is20inRange = rangeSpec.IsSatisfiedBy(20); // false
var inSpec = new InSpecification(1,2,5,8);
var is13inList = inSpec.IsSatisfiedBy(13); // false
但是为了构建更有趣的条件,您需要实现条件逻辑:
public class OrSpecification<T> : ISpecification<T>
{
private readonly ISpecification<T> _left;
private readonly ISpecification<T> _right;
public OrSpecification(ISpecification<T> left, ISpecification<T> right)
{
_right = right;
_left = left;
}
public bool IsSatisfiedBy(T value)
{
return _left.IsSatisfiedBy(value) || _right.IsSatisfiedBy(value);
}
}
该规范将帮助我们构建 OR 条件以检查值是否满足任何提供的规范。我还使用扩展方法来构建规范:
public static class SpecificationExtensions
{
public static ISpecification<T> Or<T>(
this ISpecification<T> left, ISpecification<T> right)
{
return new OrSpecification<T>(left, right);
}
}
现在我们可以构建类似的东西:
var spec = new RangeSpecification(10, 15).Or(new InSpecification(1,2,5,8));
var result = spec.IsSatisfiedBy(8); // true
我们现在需要的是从您的字符串中解析规范:
public class SpecificationParser
{
public static ISpecification<int> Parse(string input)
{
var parts = input.Split(';');
return parts.Aggregate(ParseSpec(parts[0]),
(spec, s) => spec.Or(ParseSpec(s)));
}
private static ISpecification<int> ParseSpec(string s)
{
var match = Regex.Match(s, @"\[(\d+)-(\d+)\]");
if (match.Success)
{
int from = Int32.Parse(match.Groups[1].Value);
int to = Int32.Parse(match.Groups[2].Value);
return new RangeSpecification(from, to);
}
return new InSpecification(s.Split(',').Select(Int32.Parse).ToArray());
}
}
而已。现在您可以从字符串解析规范并检查值是否满足它:
var spec1 = SpecificationParser.Parse("10, 12, 14, 16");
spec1.IsSatisfiedBy(11); // false
var spec2 = SpecificationParser.Parse("[10-20];21;23,25");
spec2.IsSatisfiedBy(9); // false
spec2.IsSatisfiedBy(19); // true
spec2.IsSatisfiedBy(22); // false