PostSharp合约范围

时间:2015-10-18 22:57:36

标签: c# postsharp

使用PostSharp和Contracts可以实现这样的效果吗?

public class Something
{
    int number = 10;

    public void Remove([Range(1,this.number)] int remove)
    {
        number -= remove;
    }

    public void Add(int add)
    {
        number += add;
    }
}

1 个答案:

答案 0 :(得分:1)

C#编译器不允许您以这种方式应用[Range]属性 - 您将收到一个构建错误,指出“属性参数必须是常量表达式,类型表达式或数组创建表达式”。

解决方法是创建一个接受字段名称作为参数的方面。然后将该字段导入方面,以便您可以读取当前的最大值。

[Serializable]
public class MyRangeAttribute : LocationContractAttribute,
                                ILocationValidationAspect<int>,
                                IInstanceScopedAspect,
                                IAdviceProvider
{
    [NonSerialized]
    private object instance;
    [NonSerialized]
    private string maxValueFieldName;
    private int minValue;
    public ILocationBinding maxValueFieldBinding;

    public MyRangeAttribute(int minValue, string maxValueFieldName)
    {
        this.minValue = minValue;
        this.maxValueFieldName = maxValueFieldName;
    }

    public Exception ValidateValue(int value, string locationName, LocationKind locationKind)
    {
        int maxValue = (int) this.maxValueFieldBinding.GetValue(ref this.instance, Arguments.Empty);
        if (value < minValue || value > maxValue)
            return new ArgumentOutOfRangeException(locationName);

        return null;
    }

    public IEnumerable<AdviceInstance> ProvideAdvices(object targetElement)
    {
        FieldInfo maxValueField = ((LocationInfo)targetElement).DeclaringType
            .GetField( this.maxValueFieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance );

        yield return new ImportLocationAdviceInstance(
            typeof (MyRangeAttribute).GetField("maxValueFieldBinding"),
            new LocationInfo(maxValueField));
    }

    public object CreateInstance( AdviceArgs adviceArgs )
    {
        MyRangeAttribute clone = (MyRangeAttribute) this.MemberwiseClone();
        clone.instance = adviceArgs.Instance;
        return clone;
    }

    public void RuntimeInitializeInstance()
    {
    }
}

您可以像这样应用此方面:

public class Something
{
    private int number = 10;

    public void Remove([MyRange(1, "number")] int remove)
    {
        number -= remove;
    }

    public void Add(int add)
    {
        number += add;
    }
}