2015-10-18 55 views
0

是否可以通過PostSharp和Contracts實現類似的功能?PostSharp合同範圍

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

C#編譯器不會讓你以這種方式應用[Range]屬性 - 您將收到一個編譯錯誤,指出「的屬性參數必須是常量表達式的typeof表達式或數組創建表達式」。

解決方法是創建一個接受字段名稱作爲參數的方面。然後將該字段導入到該方面,以便讀取當前的最大值。

[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; 
    } 
}