具有创建约束的自定义类

时间:2015-01-05 11:07:41

标签: c#

想象一下,我有一个名为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代码,用于检查输入值。难道从头开始实施吗?

2 个答案:

答案 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的常量是另一种解决方案,应该更多。