想象一下,我有一个名为MyValue
的类,其构造函数为(int value)
。它是通用类,我可以将任何int
值添加到它的构造函数中。但有时候我需要使用这个具有更多约束的类。例如,我需要强制用户只输入正值。我可以做一个继承自MyValue
的新类,但对于结构,这是不可能的。
也许有可能用属性实现这种行为?
// pseudo code
[Constraint(Min=0)]
public MyValue MyProperty { get; set; }
MyProperty可以以某种方式读取此属性,并在构造函数中使用此约束进行检查 有效值。但我认为这是不可能的。
你能给我一些建议来实现类似的行为吗?
编辑:PostSharp看起来像这里有这个功能:http://www.postsharp.net/model/code-contracts 属性用[EmailAddress]等属性进行修饰,然后在setter中注入IL代码,用于检查输入值。难道从头开始实施吗?
答案 0 :(得分:3)
怎么样,
public class MyValue<T>
{
private T value;
private readonly Func<T, bool>[] contraints;
public MyValue(
T value,
params Func<T, bool>[] contraints)
{
this.value = value;
this.constraints = constraints;
this.Validate();
}
public T Value
{
get
{
return this.value;
}
set
{
this.value = value;
this.Validate();
}
}
private Validate()
{
if (!this.constriants.All(c => c(this.value))
{
// throw some exception.
}
}
}
所以你这样使用它,
var myValue = new MyValue(1, value => value >= 0);
即。初始值为1
,值必须始终大于或等于0
。
或者,如果您愿意,可以在构造函数中读取自定义属性,而不是第二个参数。
最快的是,您可能希望使用uint
而不是int
,尽管这在公共接口上不会是CLSCompliant。
答案 1 :(得分:1)
不要使用自动属性。
MyValue _myProperty;
public MyValue MyProperty
{
get { return _myProperty; }
set
{
// check constraints in setter
if(value != null && ... )
... // do something
_myProperty = value;
}
}
如果您有许多类似的约束,那么以类似的方式处理它们是有意义的(例如,在构造MyValue
时,将约束作为参数传递给不同的构造函数重载)以使代码更多干。重载比较和使用类型MyValue
的常量是另一种解决方案,应该更多。