Specify allowed enum values in a property

后端 未结 4 1822
一个人的身影
一个人的身影 2021-01-11 17:24

Is it possible to specify that a enum property can only have a range of values?

enum Type
{
    None,
    One,
    Two,
    Three
}

class Object
{
    [Allo         


        
相关标签:
4条回答
  • 2021-01-11 17:29

    You could do a workaround like this:

    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;
        }
    }
    
    0 讨论(0)
  • 2021-01-11 17:30

    Another way to approach this is through front-end validation / filtering. I encountered a scenario where, on the db level, I needed to allow the db to save a field to any of the enum values, but I didn't want the end user to see invalid options. So, I created an attribute for the enum values specifying what kind of user could see those enum values.

    public class FieldAttribute : Attribute
    {
        public int FilterProperty { get; set; }
    }
    

    Then I decorated the enum values with that attribute.

    public enum myEnum{
    
        ZeroValue,
    
        [Field(FilterProperty = 0)]
        FirstValue,
    
        [Field(FilterProperty = 1)]
        SecondValue,
    
        [Field(FilterProperty = 0)]
        ThirdValue,
    
        [Field(FilterProperty = 1)]
        FourthValue,
    }
    

    then i created an extension method that provided a dictionary of only the values that type of user could see.

            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());
    

    Then, when the data came in on the front end, as long as whatever they pick is part of the base enum, the DB can save it.

    Not really answering your question directly, but an indirect route that might help you get what you're after.

    0 讨论(0)
  • 2021-01-11 17:32

    Same as st4hoo's solution, only with reflection. You can make it as crazy as you would like.

    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
        }
    }
    
    0 讨论(0)
  • 2021-01-11 17:46

    You could do the validation in setter logic.

    EDIT: some example:

    class Object
    {
        private Type _value;
    
        public Type objType{ 
    
            get{ return _value; }
            set{
                if(value != Type.One && value != Type.Three)
                    throw new ArgumentOutOfRangeException();
                else
                    _value = value;
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题