结合代码契约和正则表达式
所以我有一个非常简单的类,其中一个字符串作为属性。 该字符串必须具有某种模式。 我正在尝试使用代码合同来强制执行此操作。 该类看起来像这样:
class SimpleClass { public Property { get; set; } public SimpleClass(string prop) { Contract.Requires(IsValid(prop)); this.Property = prop; } [ContractInvariantMethod] void ObjectInvariant() { Contract.Invariant(IsValid(Property)); } bool IsValid(string arg) { // Use regex to check if arg is a valid string } }
非常直截了当。 但是,这会引发一个不可读的exception,另一个说“Member SimpleClass.IsValid的可见性低于封闭方法SimpleClass。#ctor(System.String)”。 为什么这是非法的? 我应该将正则表达式复制/粘贴到两种方法中吗? 这似乎与正确相反。 请帮我理解!
另一种方法是避免“原始的痴迷”,并使用适合您目的的课程,例如:
public SimpleClass(Email address) { // no need to check, it must be valid :) }
…然后将所有validation逻辑封装在Email类中。 你仍然会遇到关于validation的“字符串格式”问题,但我认为更好的习惯是创建一个名为Email.TryParse
的方法,并按照int.TryParse
的方式进行int.TryParse
。
只需将IsValid
标记为public
,你就可以了。 公共表面合同的所有“组成部分”也必须是公开的,否则呼叫者无法检查合同是否满足。
@ AI-CII我理解这一点,但这也是一个设计漏洞,向消费者展示实施细节。
-
公共方法的合同不是实现细节。
Contract.Requires
说“嘿,我要求这对我来说是真实的。” 如果呼叫者看不到“this”,呼叫者如何validation合同是否满足? -
您没有公开方法
IsValid
的实现细节,您只是暴露了被调用者必须满足的工作。
正如Jason已经说过的那样,代码契约要求该方法是公开的,因为您已经通过exception消息自己想出了自己。
但我明白,仅仅公开它并不合适。 也许正则表达式条件可以封装到辅助类的静态全局函数中?
例如,如果要检查字符串是否是有效的URL。
UrlHelper.IsValidUrl( string url )
这让我感兴趣所以我开始做一些谷歌搜索。 有一个解决方案! 虽然我仍然更喜欢使用静态方法的helper类。
它被称为Code Contract Abbreviators 。 但是,您需要自己将源文件包含在项目中。