#c# #enums #compilation
#c# #перечисления #корпоративная библиотека #проверка
Вопрос:
Возможно ли указать, что свойство перечисления может иметь только диапазон значений?
enum Type
{
None,
One,
Two,
Three
}
class Object
{
[AllowedTypes(Type.One,Type.Three)]
Type objType { get; set; }
}
Что-то вроде этого? Может быть, какой-то валидатор в корпоративной библиотеке, о котором я не знаю ?!
Ty
Комментарии:
1. Это сводит на нет всю цель перечисления. Это набор допустимых значений.
2. Перечисление уже должно быть диапазоном допустимых значений.
3. … и вы бы никогда не захотели ограничить это подмножеством для определенного свойства, ребята?
4. Нет, я бы создал второе (или третье) перечисление. @роулинг
5. @CodyGray но это делает экземпляры значений разных типов, что может быть очень неудобно.
Ответ №1:
Вы могли бы выполнить проверку в логике установки.
РЕДАКТИРОВАТЬ: некоторый пример:
class Object
{
private Type _value;
public Type objType{
get{ return _value; }
set{
if(value != Type.One amp;amp; value != Type.Three)
throw new ArgumentOutOfRangeException();
else
_value = value;
}
}
}
Комментарии:
1. Я поддерживаю этот вариант, прежде чем записывать его в поле поддержки, вы могли бы добавить некоторую проверку. Это действительно отвечает на вопрос, но я бы не рекомендовал такую логику…
2. @MrMichael что бы вы порекомендовали вместо этого?
Ответ №2:
Вы могли бы сделать обходной путь следующим образом:
static MyEnumType[] allowedEnumTypes = {MyEnumType.One, MyEnumType.Two};
MyEnumType _myEnumObject = allowedEnumTypes.First();
MyEnumType MyEnumObject
{
get
{
return _myEnumObject;
}
set
{
if(!allowedEnumTypes.Any (et => et == value))
{
throw new Exception("Enum value not allowed.");
}
_myEnumObject = value;
}
}
Ответ №3:
То же, что и решение st4hoo, только с отражением. Вы можете сделать это настолько безумным, насколько вам хотелось бы.
using System;
using System.Linq;
namespace ConceptApplication
{
static class Program
{
static void Main(string[] args)
{
var foobar = new Foobar
{
SomeProperty = Numbers.Five
};
}
}
public class Foobar
{
private static Numbers _someProperty;
[NumberRestriction(Allowed = new[] {Numbers.One, Numbers.Two})]
public Numbers SomeProperty
{
get { return _someProperty; }
set
{
RestrictionValidator.Validate(this, "SomeProperty", value);
_someProperty = value;
}
}
}
public class NumberRestriction : Attribute
{
public Numbers[] Allowed { get; set; }
}
public static class RestrictionValidator
{
public static void Validate<T>(T sender, string propertyName, Numbers number)
{
var attrs = sender.GetType().GetProperty(propertyName).GetCustomAttributes(typeof(NumberRestriction), true);
if (attrs.OfType<NumberRestriction>().Any(attr => !(attr).Allowed.Contains(number)))
throw new ArgumentOutOfRangeException();
}
}
public enum Numbers
{
One,
Two,
Three,
Four,
Five
}
}
Ответ №4:
Другой способ приблизиться к этому — с помощью проверки / фильтрации интерфейса. Я столкнулся со сценарием, когда на уровне базы данных мне нужно было разрешить базе данных сохранять поле для любого из значений перечисления, но я не хотел, чтобы конечный пользователь видел недопустимые параметры. Итак, я создал атрибут для значений перечисления, указывающий, какой пользователь может видеть эти значения перечисления.
public class FieldAttribute : Attribute
{
public int FilterProperty { get; set; }
}
Затем я украсил значения перечисления этим атрибутом.
public enum myEnum{
ZeroValue,
[Field(FilterProperty = 0)]
FirstValue,
[Field(FilterProperty = 1)]
SecondValue,
[Field(FilterProperty = 0)]
ThirdValue,
[Field(FilterProperty = 1)]
FourthValue,
}
затем я создал метод расширения, который предоставлял словарь только тех значений, которые мог видеть тип пользователя.
public static IDictionary<int, string> PrepareAcceptableValues(int filterVal) {
var values = Enum.GetValues(typeof(myEnum));
var retval = new List<myEnum>();
foreach (var value in values) {
try { //if enum value has an attribute type...
var assignedFilterProp = value.GetType().GetMember(value.ToString()).First().GetCustomAttribute<FieldAttribute>().FilterProperty;
if (assignedFilterProp.Equals(filterVal)) //if enum value has the correct filter property
retval.Add((myEnum)value); //add it in
}
catch (Exception e) {
retval.Add((myEnum)value); //if enum value has no attribute, add it in
}
}
return retval.ToDictionary(i => (int)i, i => i.toString());
Затем, когда данные поступают во внешний интерфейс, до тех пор, пока все, что они выбирают, является частью базового перечисления, база данных может сохранить это.
На самом деле это не прямой ответ на ваш вопрос, а косвенный путь, который может помочь вам получить то, что вам нужно.