代码之家  ›  专栏  ›  技术社区  ›  Matthew Vines

当位掩码(标志)枚举变得太大时该怎么办

  •  96
  • Matthew Vines  · 技术社区  · 17 年前

    还有其他人遇到过这个问题吗?你是怎么过去的?一般的例子很好,但如果有任何特定于语言的技巧可以用来完成工作,我最感兴趣的是c#特定的例子。

    //Subgroup WebAgent
    [Flags]
    public enum WebAgentPermission : long
    {
        [DescriptionAttribute("View Rule Group")]
        ViewRuleGroup = 1,
        [DescriptionAttribute("Add Rule Group")]
        AddRuleGroup = 2,
        [DescriptionAttribute("Edit Rule Group")]
        EditRuleGroup = 4,
        [DescriptionAttribute("Delete Rule Group")]
        DeleteRuleGroup = 8,
        [DescriptionAttribute("View Rule")]
        ViewRule = 16,
        [DescriptionAttribute("Add Rule")]
        AddRule = 32,
        [DescriptionAttribute("Edit Rule")]
        EditRule = 64,
        [DescriptionAttribute("Delete Rule")]
        DeleteRule = 128,
        [DescriptionAttribute("View Location")]
        ViewLocation = 256,
        [DescriptionAttribute("Add Location")]
        AddLocation = 512,
        [DescriptionAttribute("Edit Location")]
        EditLocation = 1024,
        [DescriptionAttribute("Delete Location")]
        DeleteLocation = 2048,
        [DescriptionAttribute("View Volume Statistics")]
        ViewVolumeStatistics = 4096,
        [DescriptionAttribute("Edit Volume Statistics")]
        EditVolumeStatistics = 8192,
        [DescriptionAttribute("Upload Volume Statistics")]
        UploadVolumeStatistics = 16384,
        [DescriptionAttribute("View Role")]
        ViewRole = 32768,
        [DescriptionAttribute("Add Role")]
        AddRole = 65536,
        [DescriptionAttribute("Edit Role")]
        EditRole = 131072,
        [DescriptionAttribute("Delete Role")]
        DeleteRole = 262144,
        [DescriptionAttribute("View User")]
        ViewUser = 524288,
        [DescriptionAttribute("Add User")]
        AddUser = 1048576,
        [DescriptionAttribute("Edit User")]
        EditUser = 2097152,
        [DescriptionAttribute("Delete User")]
        DeleteUser = 4194304,
        [DescriptionAttribute("Assign Permissions To User")]
        AssignPermissionsToUser = 8388608,
        [DescriptionAttribute("Change User Password")]
        ChangeUserPassword = 16777216,
        [DescriptionAttribute("View Audit Logs")]
        ViewAuditLogs = 33554432,
        [DescriptionAttribute("View Team")]
        ViewTeam = 67108864,
        [DescriptionAttribute("Add Team")]
        AddTeam = 134217728,
        [DescriptionAttribute("Edit Team")]
        EditTeam = 268435456,
        [DescriptionAttribute("Delete Team")]
        DeleteTeam = 536870912,
        [DescriptionAttribute("View Web Agent Reports")]
        ViewWebAgentReports = 1073741824,
        [DescriptionAttribute("View All Locations")]
        ViewAllLocations = 2147483648,
        [DescriptionAttribute("Access to My Search")]
        AccessToMySearch = 4294967296,
        [DescriptionAttribute("Access to Pespective Search")]
        AccessToPespectiveSearch = 8589934592,
        [DescriptionAttribute("Add Pespective Search")]
        AddPespectiveSearch = 17179869184,
        [DescriptionAttribute("Edit Pespective Search")]
        EditPespectiveSearch = 34359738368,
        [DescriptionAttribute("Delete Pespective Search")]
        DeletePespectiveSearch = 68719476736,
        [DescriptionAttribute("Access to Search")]
        AccessToSearch = 137438953472,
        [DescriptionAttribute("View Form Roles")]
        ViewFormRole = 274877906944,
        [DescriptionAttribute("Add / Edit Form Roles")]
        AddFormRole = 549755813888,
        [DescriptionAttribute("Delete UserFormRolesDifferenceMasks")]
        DeleteFormRole = 1099511627776,
        [DescriptionAttribute("Export Locations")]
        ExportLocations = 2199023255552,
        [DescriptionAttribute("Import Locations")]
        ImportLocations = 4398046511104,
        [DescriptionAttribute("Manage Location Levels")]
        ManageLocationLevels = 8796093022208,
        [DescriptionAttribute("View Job Title")]
        ViewJobTitle = 17592186044416,
        [DescriptionAttribute("Add Job Title")]
        AddJobTitle = 35184372088832,
        [DescriptionAttribute("Edit Job Title")]
        EditJobTitle = 70368744177664,
        [DescriptionAttribute("Delete Job Title")]
        DeleteJobTitle = 140737488355328,
        [DescriptionAttribute("View Dictionary Manager")]
        ViewDictionaryManager = 281474976710656,
        [DescriptionAttribute("Add Dictionary Manager")]
        AddDictionaryManager = 562949953421312,
        [DescriptionAttribute("Edit Dictionary Manager")]
        EditDictionaryManager = 1125899906842624,
        [DescriptionAttribute("Delete Dictionary Manager")]
        DeleteDictionaryManager = 2251799813685248,
        [DescriptionAttribute("View Choice Manager")]
        ViewChoiceManager = 4503599627370496,
        [DescriptionAttribute("Add Choice Manager")]
        AddChoiceManager = 9007199254740992,
        [DescriptionAttribute("Edit Chioce Manager")]
        EditChoiceManager = 18014398509481984,
        [DescriptionAttribute("Delete Choice Manager")]
        DeleteChoiceManager = 36028797018963968,
        [DescriptionAttribute("Import Export Choices")] //57
        ImportExportChoices = 72057594037927936
    }
    
    10 回复  |  直到 17 年前
        1
  •  47
  •   mayo    6 年前

    我在那里看到了至少几个不同枚举的值。..

    RuleGroupPermissions RulePermissions LocationPermissions WebAgentPermissions

    [Flags]
    public enum Permissions
    {
        View = 1,
        Add = 2,
        Edit = 4,
        Delete = 8
    }
    

    class WebAgentPermissions
    {
        public Permissions RuleGroup { get; set; }
        public Permissions Rule { get; set; }
        public Permissions Location { get; set; }
        // and so on...
    }
    
        3
  •  15
  •   DavidMoksha    6 年前

    [Flags]
    public enum MyEnumFlags : Int64
    {
        None = 0,
        A = 1 << 0,
        B = 1 << 1,
        C = 1 << 2,
        D = 1 << 3,
        E = 1 << 4,
        F = 1 << 5,
        ...etc...
    

        4
  •  14
  •   Bruce Pierson    10 年前

    BigFlags BigInteger System.Numerics BitArray NUMERICS 预处理器指令。

    Flags HasFlag(...) , GetNames() , GetValues() , TryParse(...) TypeConverter , IConvertible

    public static readonly

    TODO 部分并添加您的值。

    #define NUMERICS
    
    using System;
    using System.Collections;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Globalization;
    using System.Linq;
    #if NUMERICS
    using System.Numerics;
    #endif
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    
    
    namespace Aim
    {
        /// <summary>
        /// The BigFlags struct behaves like a Flags enumerated type.
        /// <para>
        /// Note that if this struct will be stored in some type of data
        /// store, it should be stored as a string type. There are two
        /// reasons for this:
        /// </para>
        /// <para>
        /// 1. Presumably, this pattern is being used because the number
        /// of values will exceed 64 (max positions in a long flags enum).
        /// Since this is so, there is in any case no numeric type which
        /// can store all the possible combinations of flags.
        /// </para>
        /// <para>
        /// 2. The "enum" values are assigned based on the order that the
        /// static public fields are defined. It is much safer to store
        /// these fields by name in case the fields are rearranged. This
        /// is particularly important if this represents a permission set!
        /// </para>
        /// </summary>
        [
        TypeConverter( typeof( BigFlagsConverter ) )
        ]
        public struct BigFlags : IEquatable<BigFlags>,
            IComparable<BigFlags>, IComparable, IConvertible
        {
            #region State...
    
            private static readonly List<FieldInfo> Fields;
            private static readonly List<BigFlags> FieldValues;
    #if NUMERICS
            private static readonly bool ZeroInit = true;
            private BigInteger Value;
    
            /// <summary>
            /// Creates a value taking ZeroInit into consideration.
            /// </summary>
            /// <param name="index"></param>
            /// <returns></returns>
            private static BigInteger CreateValue( int index )
            {
                if( ZeroInit && index == 0 )
                {
                    return 0;
                }
                int idx = ZeroInit ? index - 1 : index;
    
                return new BigInteger( 1 ) << idx;
            }
    #else
            private BitArray Array;
    
            /// <summary>
            /// Lazy-initialized BitArray.
            /// </summary>
            private BitArray Bits
            {
                get
                {
                    if( null == Array )
                    {
                        Array = new BitArray( Fields.Count );
                    }
                    return Array;
                }
            }
    #endif
            #endregion ...State
    
            #region Construction...
    
            /// <summary>
            /// Static constructor. Sets the static public fields.
            /// </summary>
            static BigFlags()
            {
                Fields = typeof( BigFlags ).GetFields(
                    BindingFlags.Public | BindingFlags.Static ).ToList();
                FieldValues = new List<BigFlags>();
                for( int i = 0; i < Fields.Count; i++ )
                {
                    var field = Fields[i];
                    var fieldVal = new BigFlags();
    #if NUMERICS
                    fieldVal.Value = CreateValue( i );
    #else
                    fieldVal.Bits.Set( i, true );
    #endif
                    field.SetValue( null, fieldVal );
                    FieldValues.Add( fieldVal );
                }
            }
            #endregion ...Construction
    
            #region Operators...
    
            /// <summary>
            /// OR operator. Or together BigFlags instances.
            /// </summary>
            /// <param name="lhs"></param>
            /// <param name="rhs"></param>
            /// <returns></returns>
            public static BigFlags operator |( BigFlags lhs, BigFlags rhs )
            {
                var result = new BigFlags();
    #if NUMERICS
                result.Value = lhs.Value | rhs.Value;
    #else
                // BitArray is modified in place - always copy!
                result.Array = new BitArray( lhs.Bits ).Or( rhs.Bits );
    #endif
    
                return result;
            }
    
            /// <summary>
            /// AND operator. And together BigFlags instances.
            /// </summary>
            /// <param name="lhs"></param>
            /// <param name="rhs"></param>
            /// <returns></returns>
            public static BigFlags operator &( BigFlags lhs, BigFlags rhs )
            {
                var result = new BigFlags();
    #if NUMERICS
                result.Value = lhs.Value & rhs.Value;
    #else
                // BitArray is modified in place - always copy!
                result.Array = new BitArray( lhs.Bits ).And( rhs.Bits );
    #endif
    
                return result;
            }
    
            /// <summary>
            /// XOR operator. Xor together BigFlags instances.
            /// </summary>
            /// <param name="lhs"></param>
            /// <param name="rhs"></param>
            /// <returns></returns>
            public static BigFlags operator ^( BigFlags lhs, BigFlags rhs )
            {
                var result = new BigFlags();
    #if NUMERICS
                result.Value = lhs.Value ^ rhs.Value;
    #else
                // BitArray is modified in place - always copy!
                result.Array = new BitArray( lhs.Bits ).Xor( rhs.Bits );
    #endif
    
                return result;
            }
    
            /// <summary>
            /// Equality operator.
            /// </summary>
            /// <param name="lhs"></param>
            /// <param name="rhs"></param>
            /// <returns></returns>
            public static bool operator ==( BigFlags lhs, BigFlags rhs )
            {
                return lhs.Equals( rhs );
            }
    
            /// <summary>
            /// Inequality operator.
            /// </summary>
            /// <param name="lhs"></param>
            /// <param name="rhs"></param>
            /// <returns></returns>
            public static bool operator !=( BigFlags lhs, BigFlags rhs )
            {
                return !( lhs == rhs );
            }
            #endregion ...Operators
    
            #region System.Object Overrides...
    
            /// <summary>
            /// Overridden. Returns a comma-separated string.
            /// </summary>
            /// <returns></returns>
            public override string ToString()
            {
    #if NUMERICS
                if( ZeroInit && Value == 0 )
                {
                    return Fields[0].Name;
                }
    #endif
                var names = new List<string>();
                for( int i = 0; i < Fields.Count; i++ )
                {
    #if NUMERICS
                    if( ZeroInit && i == 0 )
                        continue;
    
                    var bi = CreateValue( i );
                    if( ( Value & bi ) ==  bi )
                        names.Add( Fields[i].Name );
    #else
                    if( Bits[i] )
                        names.Add( Fields[i].Name );
    #endif
                }
    
                return String.Join( ", ", names );
            }
    
            /// <summary>
            /// Overridden. Compares equality with another object.
            /// </summary>
            /// <param name="obj"></param>
            /// <returns></returns>
            public override bool Equals( object obj )
            {
                if( obj is BigFlags )
                {
                    return Equals( (BigFlags)obj );
                }
    
                return false;
            }
    
            /// <summary>
            /// Overridden. Gets the hash code of the internal BitArray.
            /// </summary>
            /// <returns></returns>
            public override int GetHashCode()
            {
    #if NUMERICS
                return Value.GetHashCode();
    #else
                int hash = 17;
                for( int i = 0; i < Bits.Length; i++ )
                {
                    if( Bits[i] )
                        hash ^= i;
                }
    
                return hash;
    #endif
            }
            #endregion ...System.Object Overrides
    
            #region IEquatable<BigFlags> Members...
    
            /// <summary>
            /// Strongly-typed equality method.
            /// </summary>
            /// <param name="other"></param>
            /// <returns></returns>
            public bool Equals( BigFlags other )
            {
    #if NUMERICS
                return Value == other.Value;
    #else
                for( int i = 0; i < Bits.Length; i++ )
                {
                    if( Bits[i] != other.Bits[i] )
                        return false;
                }
    
                return true;
    #endif
            }
            #endregion ...IEquatable<BigFlags> Members
    
            #region IComparable<BigFlags> Members...
    
            /// <summary>
            /// Compares based on highest bit set. Instance with higher
            /// bit set is bigger.
            /// </summary>
            /// <param name="other"></param>
            /// <returns></returns>
            public int CompareTo( BigFlags other )
            {
    #if NUMERICS
                return Value.CompareTo( other.Value );
    #else
                for( int i = Bits.Length - 1; i >= 0; i-- )
                {
                    bool thisVal = Bits[i];
                    bool otherVal = other.Bits[i];
                    if( thisVal && !otherVal )
                        return 1;
                    else if( !thisVal && otherVal )
                        return -1;
                }
    
                return 0;
    #endif
            }
            #endregion ...IComparable<BigFlags> Members
    
            #region IComparable Members...
    
            int IComparable.CompareTo( object obj )
            {
                if( obj is BigFlags )
                {
                    return CompareTo( (BigFlags)obj );
                }
    
                return -1;
            }
            #endregion ...IComparable Members
    
            #region IConvertible Members...
    
            /// <summary>
            /// Returns TypeCode.Object.
            /// </summary>
            /// <returns></returns>
            public TypeCode GetTypeCode()
            {
                return TypeCode.Object;
            }
    
            bool IConvertible.ToBoolean( IFormatProvider provider )
            {
                throw new NotSupportedException();
            }
    
            byte IConvertible.ToByte( IFormatProvider provider )
            {
    #if NUMERICS
                return Convert.ToByte( Value );
    #else
                throw new NotSupportedException();
    #endif
            }
    
            char IConvertible.ToChar( IFormatProvider provider )
            {
                throw new NotSupportedException();
            }
    
            DateTime IConvertible.ToDateTime( IFormatProvider provider )
            {
                throw new NotSupportedException();
            }
    
            decimal IConvertible.ToDecimal( IFormatProvider provider )
            {
    #if NUMERICS
                return Convert.ToDecimal( Value );
    #else
                throw new NotSupportedException();
    #endif
            }
    
            double IConvertible.ToDouble( IFormatProvider provider )
            {
    #if NUMERICS
                return Convert.ToDouble( Value );
    #else
                throw new NotSupportedException();
    #endif
            }
    
            short IConvertible.ToInt16( IFormatProvider provider )
            {
    #if NUMERICS
                return Convert.ToInt16( Value );
    #else
                throw new NotSupportedException();
    #endif
            }
    
            int IConvertible.ToInt32( IFormatProvider provider )
            {
    #if NUMERICS
                return Convert.ToInt32( Value );
    #else
                throw new NotSupportedException();
    #endif
            }
    
            long IConvertible.ToInt64( IFormatProvider provider )
            {
    #if NUMERICS
                return Convert.ToInt64( Value );
    #else
                throw new NotSupportedException();
    #endif
            }
    
            sbyte IConvertible.ToSByte( IFormatProvider provider )
            {
    #if NUMERICS
                return Convert.ToSByte( Value );
    #else
                throw new NotSupportedException();
    #endif
            }
    
            float IConvertible.ToSingle( IFormatProvider provider )
            {
    #if NUMERICS
                return Convert.ToSingle( Value );
    #else
                throw new NotSupportedException();
    #endif
            }
    
            string IConvertible.ToString( IFormatProvider provider )
            {
                return ToString();
            }
    
            object IConvertible.ToType( Type conversionType, IFormatProvider provider )
            {
                var tc = TypeDescriptor.GetConverter( this );
    
                return tc.ConvertTo( this, conversionType );
            }
    
            ushort IConvertible.ToUInt16( IFormatProvider provider )
            {
    #if NUMERICS
                return Convert.ToUInt16( Value );
    #else
                throw new NotSupportedException();
    #endif
            }
    
            uint IConvertible.ToUInt32( IFormatProvider provider )
            {
    #if NUMERICS
                return Convert.ToUInt32( Value );
    #else
                throw new NotSupportedException();
    #endif
            }
    
            ulong IConvertible.ToUInt64( IFormatProvider provider )
            {
    #if NUMERICS
                return Convert.ToUInt64( Value );
    #else
                throw new NotSupportedException();
    #endif
            }
            #endregion ...IConvertible Members
    
            #region Public Interface...
    
            /// <summary>
            /// Checks <paramref name="flags"/> to see if all the bits set in
            /// that flags are also set in this flags.
            /// </summary>
            /// <param name="flags"></param>
            /// <returns></returns>
            public bool HasFlag( BigFlags flags )
            {
                return ( this & flags ) == flags;
            }
    
            /// <summary>
            /// Gets the names of this BigFlags enumerated type.
            /// </summary>
            /// <returns></returns>
            public static string[] GetNames()
            {
                return Fields.Select( x => x.Name ).ToArray();
            }
    
            /// <summary>
            /// Gets all the values of this BigFlags enumerated type.
            /// </summary>
            /// <returns></returns>
            public static BigFlags[] GetValues()
            {
                return FieldValues.ToArray();
            }
    
            /// <summary>
            /// Standard TryParse pattern. Parses a BigFlags result from a string.
            /// </summary>
            /// <param name="s"></param>
            /// <param name="result"></param>
            /// <returns></returns>
            public static bool TryParse( string s, out BigFlags result )
            {
                result = new BigFlags();
                if( String.IsNullOrEmpty( s ) )
                    return true;
    
                var fieldNames = s.Split( ',' );
                foreach( var f in fieldNames )
                {
                    var field = Fields.FirstOrDefault( x =>
                        String.Equals( x.Name, f.Trim(),
                        StringComparison.OrdinalIgnoreCase ) );
                    if( null == field )
                    {
                        result = new BigFlags();
                        return false;
                    }
    #if NUMERICS
                    int i = Fields.IndexOf( field );
                    result.Value |= CreateValue( i );
    #else
                    result.Bits.Set( Fields.IndexOf( field ), true );
    #endif
                }
    
                return true;
            }
    
            //
            // Expose "enums" as public static readonly fields.
            // TODO: Replace this section with your "enum" values.
            //
            public static readonly BigFlags None;
            public static readonly BigFlags FirstValue;
            public static readonly BigFlags ValueTwo;
            public static readonly BigFlags ValueThree;
            public static readonly BigFlags ValueFour;
            public static readonly BigFlags ValueFive;
            public static readonly BigFlags ValueSix;
            public static readonly BigFlags LastValue;
    
            /// <summary>
            /// Expose flagged combinations as get-only properties.
            /// </summary>
            public static BigFlags FirstLast
            {
                get
                {
                    return BigFlags.FirstValue | BigFlags.LastValue;
                }
            }
            #endregion ...Public Interface
        }
    
        /// <summary>
        /// Converts objects to and from BigFlags instances.
        /// </summary>
        public class BigFlagsConverter : TypeConverter
        {
            /// <summary>
            /// Can convert to string only.
            /// </summary>
            /// <param name="context"></param>
            /// <param name="destinationType"></param>
            /// <returns></returns>
            public override bool CanConvertTo( ITypeDescriptorContext context,
                Type destinationType )
            {
                return destinationType == typeof( String );
            }
    
            /// <summary>
            /// Can convert from any object.
            /// </summary>
            /// <param name="context"></param>
            /// <param name="sourceType"></param>
            /// <returns></returns>
            public override bool CanConvertFrom( ITypeDescriptorContext context,
                Type sourceType )
            {
                return true;
            }
    
            /// <summary>
            /// Converts BigFlags to a string.
            /// </summary>
            /// <param name="context"></param>
            /// <param name="culture"></param>
            /// <param name="value"></param>
            /// <param name="destinationType"></param>
            /// <returns></returns>
            public override object ConvertTo( ITypeDescriptorContext context,
                CultureInfo culture, object value, Type destinationType )
            {
                if( value is BigFlags && CanConvertTo( destinationType ) )
                    return value.ToString();
    
                return null;
            }
    
            /// <summary>
            /// Attempts to parse <paramref name="value"/> and create and
            /// return a new BigFlags instance.
            /// </summary>
            /// <param name="context"></param>
            /// <param name="culture"></param>
            /// <param name="value"></param>
            /// <returns></returns>
            public override object ConvertFrom( ITypeDescriptorContext context,
                CultureInfo culture, object value )
            {
                var s = Convert.ToString( value );
                BigFlags result;
                BigFlags.TryParse( s, out result );
    
                return result;
            }
        }
    }
    
        5
  •  13
  •   arbiter    17 年前
        6
  •  5
  •   mqp    17 年前

    public sealed class WebAgentPermission
    {
        private long ID;
    
        public static readonly WebAgentPermission
            ViewRuleGroup = new WebAgentPermission { ID = 1 };
        public static readonly WebAgentPermission
            AddRuleGroup  = new WebAgentPermission { ID = 2 };
    
        private WebAgentPermission() { } 
    
        // considerations: override equals/gethashcode, probably override tostring,
        // maybe implicit cast to/from long, maybe other stuff
    }
    

        7
  •  4
  •   Talljoe    17 年前

    Permissions perms = agent.GetPermissions(ResourceType.User);
    if((perms & Permissions.View) == Permissions.View) { /* do work */ }
    

    Permissions perms = agent.Permissions[ResourceType.User];
    if((perms & Permissions.View) == Permissions.View) { /* do work */ }
    

    if(agent.IsAuthorized(ResourceType.User, Permissions.View)) { /* do work */ }
    

        8
  •  2
  •   shahkalpesh    17 年前

    RuleGroupPermission
        None = 0
        ViewRuleGroup = 1,
        AddRuleGroup = 2,
        EditRuleGroup = 4,
        DeleteRuleGroup = 8,
    
    LocationOperations
        None = 0
        Add = 1
        View = 2
        Delete = 4
    
    void setPermission(RuleGroupPermission ruleGroupOpsAllowed, LocationOperations locationOptions)
    {
       ...
    }
    

        9
  •  1
  •   AliReza Sabouri    3 年前
        10
  •  0
  •   Graham Laight    4 年前

    public class Permission
    {
        public string Description;
        public string Code;
        public bool IsSet;
    }
    
    List<Permission> permissions;