我有一个“规则”的概念,我希望能够处理。因此,我创建了以下界面:
public interface IRule<T>
{
Boolean IsSatisfiedBy(T value);
String GetViolationMessage(T value);
}
我曾计划创建一系列“规则”类来表示系统当前支持的各种规则,例如:
public class MatchesPatternRule : IRule<String>
{
private readonly Regex _regex;
private readonly String _pattern;
public MatchesPatternRule(String pattern)
{
Verify.IsFalse(String.IsNullOrWhiteSpace(pattern));
_regex = new Regex(pattern);
_pattern = pattern;
}
public Boolean IsSatisfiedBy(String value)
{
return _regex.IsMatch(value);
}
public String GetViolationMessage(String value)
{
return String.Format(RuleMessage.MatchesPatternViolation, _pattern, value);
}
}
然后规则将通过各种扩展方法消耗,例如:
public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern)
{
context.AddRule(new MatchesPatternRule(pattern));
return context;
}
但是,我目前有20多个规则的计划,并且可以通过将扩展方法写为:
来轻松替换MatchesPatternRule类public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern)
where T : IComparable
{
Verify.IsFalse(String.IsNullOrWhiteSpace(pattern));
Regex regex = new Regex(pattern);
context.AddRule(value => regex.IsMatch(value), value => String.Format(RuleMessage.MatchesPatternViolation, _pattern, value));
return context;
}
好奇什么方法更好,为什么?两者都易于测试并最终达到最终结果。任何见解将不胜感激!
更新
根据汤姆的反馈,我认为我选择采用中间路线。我将创建一个静态类来保存每个“规则”的扩展方法。这将确保任何给定的规则易于查找,并保持我的代码有条理,但也减少整体代码量。
public static class MatchesPatternRule
{
public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern)
{
return MatchesPattern<T>(context, pattern, pattern, RegexOptions.None);
}
public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern, String friendlyPattern)
{
return MatchesPattern<T>(context, pattern, friendlyPattern, RegexOptions.None);
}
public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern, RegexOptions options)
{
return MatchesPattern<T>(context, pattern, pattern, options);
}
public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern, String friendlyPattern, RegexOptions options)
{
Verify.IsFalse(String.IsNullOrWhiteSpace(pattern));
Regex regex = new Regex(pattern);
context.AddRule(value => regex.IsMatch(value), value => String.Format(RuleMessage.MatchesPatternViolation, _pattern, value));
return context;
}
}
答案 0 :(得分:1)
我不是C#用户,但在Ruby和Scala中,有一个类似的选择。在这样的上下文中有一个遵循特定接口的类似乎具有与闭包类似的用途,尽管有更多的样板。因为他们在技术上追求相同的目标,所以当然问题就是在社交环境中最好的问题。
那些应该写这些规则的人是否足够聪明,能够解决问题?如果没有,基于类的解决方案可能是更好的解决方案。如果我让我的Java程序员 - 试图理解所有这个C#-fanciness帽子,基于类的解决方案可能比学习所有这些奇怪的功能更容易 - 我知道奇怪的功能性东西,但我可以想象自己不知道它!只有你可以决定什么是最适合那些将要编写规则的人。如果你是唯一一个必须写规则的人,那就去疯狂吧!选择你喜欢的任何美学。
文档和元数据怎么样?未来的可扩展性?如果您需要在规则中添加额外字段,该怎么办?是否更容易将基于类的解决方案记录在基于闭包的解决方案上?如果您必须查找并更改规则,哪一个更容易实现?
答案 1 :(得分:1)
为什么你们不能同时拥有?对于简单的规则,您可以使用闭包。 ValidationContext.AddRule可以将您的闭包转换为规则。或者也许是将闭包转换为规则的扩展方法。