PostSharp 合同范围
PostSharp Contracts Range
是否可以使用 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;
}
}
C# 编译器不允许您以这种方式应用 [Range]
属性 - 您将收到一个构建错误,指出 "an attribute argument must be a constant expression, typeof expression or array creation expression".
解决方法是创建一个接受字段名称作为参数的方面。然后将该字段导入方面,这样您就可以读取当前的最大值。
[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;
}
}
是否可以使用 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;
}
}
C# 编译器不允许您以这种方式应用 [Range]
属性 - 您将收到一个构建错误,指出 "an attribute argument must be a constant expression, typeof expression or array creation expression".
解决方法是创建一个接受字段名称作为参数的方面。然后将该字段导入方面,这样您就可以读取当前的最大值。
[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;
}
}