我有一个数据结构,我试图通过一些类(windows 窗体)来表示,但我担心我是否可以限制要输入的字符串的长度。
现在,我所代表的示例类如下:
public class RipsAF
{
public string CodigoPrestador { get; set; }
public string NombreProveedor { get; set; }
public string TipoIdentificacion { get; set; }
public string NumeIdentificacion { get; set; }
public string NumFactura { get; set; }
}
但是,例如,我想限制CodigoPrestador
不支持超过 10 个字符的字符串的属性。
如果你想在你的类的属性中实现一些逻辑,你不应该使用自动实现的属性。你必须定义一个字段(field)然后写你的属性。之后在设置器中设置您需要的逻辑(在您的情况下验证大小)并引发异常或丢弃无效值。我只将示例放在属性中
CodigoPrestador
您可以通过
Substring()
定义最大长度来限制对象属性的长度,这是一个示例:适合您的代码的示例,例如,如果您
NumFactura
在以下任一位置定义将属性限制为 10 个字符get
:或在
set
:要检查类的实例,请存储该值,然后将其限制为 10 个字符:
您将有一个输出值:
尽管可以按照其他答案中提出的方式进行验证,但如果您有多个类和每个类的多个属性,则需要大量重复代码来检查每个字符串的长度。这很快就变得非常乏味。
例如,如果我们参加
RipsAF
您问题中的课程:...并决定对每个字符串应用长度约束,代码会导致更冗长的结果(基于@Sergio Parra 的回答,但对每个属性应用验证并进行调整,以便在值为 时它不会失败
null
):也许这只是我的意见,但我真的不喜欢这个结果。
解决方法:使用动态代理
如果我们可以提取检查字符串长度的逻辑并将其集中起来以防止类被重复代码污染怎么办?这可以使用属性和动态代理来实现。
基本思想如下:
一些流行的框架使用这种技术,但我们通常没有意识到它们是如何做到的(例如:实体框架)。
使用这种技术,我们可以
RipsAF
用这种更简单、更清晰的方式来表达类:如您所见,只需将属性添加
MaxLength
到需要验证最大长度的属性即可。另一个细节是您必须使用关键字标记属性
virtual
。原因是,为了验证字符串,代理需要拦截属性调用。实现这种拦截的方式是从相关类继承并自动修改属性的实现。但这只能通过检查属性来实现virtual
。现在,这很容易。最棘手的部分是编写创建动态代理和拦截属性调用的代码。
但作为礼物,我将处理该部分的代码留在这里,它可以为任何类创建代理。(我无法解释这段代码的每一个细节,因为我的答案已经太长了。但是对于那些有兴趣的人来说,值得仔细看看代码。)为了让代码工作,你需要在你的项目中包含Castle 库。核心可以在NuGet上免费找到:
一旦你将这个类
EntityBuilder<T>
包含在你的项目中,将它与 classRipsAF
或任何其他类一起使用是非常容易的:对该属性的第二次分配
CodigoPrestador
导致以下异常:最后的笔记
认识到编写创建自动拦截属性的动态代理的代码的复杂性。该类的实现
EntityBuilder<T>
就是证明。但是使用这种技术有一些有趣的优势: