Is it possible to make attribute which can limit minimum or maximum value of numbers.
Example:
[MinValue(1), MaxValue(50)]
public int Size { get; set
create an extension
public static class Extensions
{
public static int FixedValue(this int value, int min, int max)
{
if (value >= min && value <= max)
return value;
else if (value > max)
return max;
else if (value < min)
return min;
else return 1;
}
}
And then:
private int size;
public int Size { get { return size.FixedValue(1, 50); }
set { size = value.FixedValue(1, 50); } }
You can elegantly solve this problem by using PostSharp by writing simple aspect, free version will be enough for this purpose:
[Serializable]
class RangeAttribute : LocationInterceptionAspect
{
private int min;
private int max;
public RangeAttribute(int min, int max)
{
this.min = min;
this.max = max;
}
public override void OnSetValue(LocationInterceptionArgs args)
{
int value = (int)args.Value;
if (value < min) value = min;
if (value > max) value = max;
args.SetNewValue(value);
}
}
and then exacly as you want:
class SomeClass
{
[Range(1, 50)]
public int Size { get; set; }
}
with normal usage:
var c = new SomeClass();
c.Size = -3;
Console.Output(c.Size);
will output 1.
Yes, it is possible with (already pointed) CustomAttributes, but mind, that you will loose the comfort of the auto-properties - because you need to apply resp. check the attribute restriction somewhere and in this case an appropriate place would be the getter of the property, so the interesting part of the problem is the application of the attributes. You can read how to access custom attributes in this MSDN article.
A possible solution for the MaxValue custom attribute can look like this:
// simple class for the example
public class DataHolder
{
private int a;
[MaxValue(10)]
public int A
{
get
{
var memberInfo = this.GetType().GetMember("A");
if (memberInfo.Length > 0)
{
// name of property could be retrieved via reflection
var mia = this.GetType().GetMember("A")[0];
var attributes = System.Attribute.GetCustomAttributes(mia);
if (attributes.Length > 0)
{
// TODO: iterate over all attributes and check attribute name
var maxValueAttribute = (MaxValue)attributes[0];
if (a > maxValueAttribute.Max) { a = maxValueAttribute.Max; }
}
}
return a;
}
set
{
a = value;
}
}
}
// max attribute
public class MaxValue : Attribute
{
public int Max;
public MaxValue(int max)
{
Max = max;
}
}
The sample usage:
var data = new DataHolder();
data.A = 12;
Console.WriteLine(data.A);
creates the output:
10
The code for the MinValue will look the same as for the MaxValue but the if condition will be less than instead of greater than.
Although it is possible to create a custom attribute, attributes are just metadata for the member they annotate, and cannot change its behavior.
So, you won't get the behavior you want with a plain attribute. You need something to process the attributes in order to enact the desired behavior.
Take a look at TypeConverters for a possibility.
Yes, it is possible. Read about custom attributes at MSDN.
And by the way, there is already a solution you can use. It is the RangeAttribute
which lets you specify the numeric range constraints for the value of a data field. Read more about it on MSDN.