Атрибут MinValue & MaxValue для свойств
можно ли сделать атрибут, который может ограничить минимальное или максимальное значение чисел.
пример:
[MinValue(1), MaxValue(50)]
public int Size { get; set; }
и когда я делаю Size = -3;
стоимостью Size
должен быть 1.
Я искал в Google и не могу найти ни одного примера об этом поведении, может быть, потому, что это невозможно сделать?
Я собираюсь использовать эти атрибуты в сетке свойств, поэтому автоматическая проверка может быть удобна.
В настоящее время я обходной путь, как это для ограничения минимального значения:
private int size;
[DefaultValue(8)]
public int Size
{
get
{
return size;
}
set
{
size = Math.Max(value, 1);
}
}
таким образом, это действует как MinValue (1)
5 ответов
хотя можно создать пользовательский атрибут, атрибуты являются только метаданными для элемента, который они аннотируют, и не могут изменить его поведение.
таким образом, вы не получите поведение, которое хотите с простым атрибутом. Вам нужно что-то обработать атрибуты, чтобы выполнить желаемое поведение.
посмотри TypeConverters Для возможность.
вы можете элегантно решить эту проблему, используя PostSharp написав простой аспект, бесплатная версия будет достаточно для этой цели:
[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);
}
}
и тогда точно, как вы хотите:
class SomeClass
{
[Range(1, 50)]
public int Size { get; set; }
}
с нормальным использованием:
var c = new SomeClass();
c.Size = -3;
Console.Output(c.Size);
будет выдавать 1.
Да, это возможно с (уже указал) CustomAttributes, но имейте в виду, что вы потеряете комфорт авто-свойства - потому что вам нужно применить resp. проверьте ограничение атрибута где-нибудь, и в этом случае подходящим местом будет геттер свойства, поэтому интересной частью проблемы является применение атрибутов. Вы можете прочитать, Как получить доступ к пользовательским атрибутам в этой статье.
возможное решение для Пользовательский атрибут MaxValue может выглядеть следующим образом:
// 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;
}
}
пример использования:
var data = new DataHolder();
data.A = 12;
Console.WriteLine(data.A);
создает на выходе:
10
код для MinValue будет выглядеть так же, как для MaxValue, но условие if будет меньше вместо больше.
создать расширение
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;
}
}
и затем:
private int size;
public int Size { get { return size.FixedValue(1, 50); }
set { size = value.FixedValue(1, 50); } }