ما يجب فعله عندما يصبح تعداد Bit Mask (Flags) كبيرًا جدًا

StackOverflow https://stackoverflow.com/questions/1060760

سؤال

لديّ مجموعة كبيرة جدًا من الأذونات في طلبي التي أمثلها مع تعداد الأعلام. إنه يقترب بسرعة من الحد العلوي العملي لنوع البيانات الطويل. وأنا مجبر على التوصل إلى استراتيجية للانتقال إلى بنية مختلفة قريبًا. الآن ، يمكنني تقسيم هذه القائمة إلى قطع أصغر ، ومع ذلك ، فهذا مجرد مجموعة فرعية من الأذونات الإجمالية لتطبيقنا ، بناءً على تخطيط تطبيقاتنا. نحن نستخدم هذا التمييز بشكل موسع لأغراض العرض عند إدارة الأذونات وأفضل ألا أضطر إلى إعادة النظر في هذا الرمز في هذا الوقت إذا كان بإمكاني تجنب ذلك.

هل واجه أي شخص آخر هذه المسألة؟ كيف تجاوزت ذلك؟ الأمثلة العامة على ما يرام ، لكنني مهتم أكثر بمثال محدد على ذلك إذا كان هناك أي حيل محددة للغة يمكنني استخدامها لإنجاز المهمة.

قد لا تكون ضرورية ، ولكن هنا قائمة الأذونات المحددة حاليًا لجزء التطبيق الذي أتعامل معه.

//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
}
هل كانت مفيدة؟

المحلول

أرى قيمًا من حفنة من التعدادات المختلفة على الأقل ...

كانت فكرتي الأولى هي التعامل مع المشكلة عن طريق تقسيم الأذونات في المجموعات المنطقية (RuleGroupPermissions, RulePermissions, LocationPermissions, ، ...) ثم وجود فصل (WebAgentPermissions) تعريض خاصية لكل نوع من التعداد.

نظرًا لأن قيم الإذن تبدو متكررة ، فمن المحتمل أن تفلت من تعداد واحد في النهاية:

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

ثم لديك WebAgentPermissions الفئة تعرض خاصية لكل منطقة يتم فيها ضبط الأذونات ؛

class WebAgentPermissions
{
    public Permissions RuleGroup { get; set; }
    public Permissions Rule{ get; set; }
    public Permissions Location{ get; set; }
    // and so on...
}

نصائح أخرى

توثيق اللغة تقول:

http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx

"النوع الأساسي هو int32 وبالتالي فإن الحد الأقصى لعلم بت واحد هو 1073741824 ومن الواضح أن هناك ما مجموعه 32 علامة لكل تعداد."

ومع ذلك ... تم تحديثه:

المعلق صحيح. ألق نظرة على هذا:

http://msdn.microsoft.com/en-us/library/MS182147(VS.80).aspx

Int32 هو فقط نوع البيانات الافتراضي! في الواقع يمكنك تحديد int64.

public enum MyEnumType : Int64

... السماح حتى 64 قيم. لكن يبدو أن هذا هو الحد الأقصى ، بعد ذلك ستنظر في إعادة الهندسة. دون معرفة الكثير عن بقية الحل الخاص بك ، لا أستطيع أن أقول بالضبط ما قد يناسب. لكن صفيف (أو خريطة التجزئة) لمعرفات الامتياز ربما يكون النهج الأكثر طبيعية.

يمكنك التحقق Bitarray صف دراسي. ربما سوف تستخدمه في المستقبل.

اتضح أن هذا يمثل مشكلة أكثر شيوعًا مما اعتقدت ، حيث كنت أمثل فصول CSS كنوع أعلام وكان هناك أكثر من 64 إمكانيات. لقد أخذت كل ما تعلمته من هذه العملية وحولته إلى نمط قابل لإعادة الاستخدام ، وإن كان ذلك هو بنية ، إنه نمط نوع النسخ واللصق.

هذا ال BigFlags "نوع مكون". يستخدم أيضًا BigInteger من System.Numerics, ، أو إذا لم تكن هناك طريقة يمكنك الإشارة إلى هذا التجميع ، فهناك احتياطي يستخدم BitArray ببساطة عن طريق إيقاف تشغيل NUMERICS التوجيه المعالج.

يتصرف بشكل ملحوظ مثل أ Flags التعداد ، حتى تحديد أشياء مثل HasFlag(...), GetNames(), GetValues(), TryParse(...), ، أ TypeConverter, IConvertible, ، إلخ. لأنه يحدد أ TypeConverter و IConvertible, ، إنه مناسب أيضًا للتخزين في متجر للبيانات ، وإن كان دائمًا كسلسلة أو نوع بيانات نصية.

أنت تعرض قيم "التعداد" كـ public static readonly أفراد. تتعرض قيم التعداد مجتمعة كخصائص الحصول فقط.

لاستخدامه ، نسخ الكود ولصقه ، ثم قم بالبحث واستبدله BigFlags مع الاسم البني الخاص بك ، ثم احذف التعدادات في 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;
        }
    }
}

في C#، إحدى الطرق المرنة لتمثيل القيمة التي هي نوع من التعداد ولكن أكثر مرونة هي تمثيلها كفئة ثابتة مع قيم مسبقة المطبوخة ، مثل هذا:

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
}

بدلا من ذلك ، فقط تقسيم الشيء. يبدو أنك تستطيع ، إذا حاولت حقًا.

إذا كنت تتحكم في هذا التطبيق ، فمن المحتمل أن أتوصل إلى مجموعة مشتركة من الأذونات (عرض ، إضافة ، تحرير ، حذف ، تحميل/استيراد) ومجموعة من الموارد (المستخدمين ، الأدوار ، القواعد ، إلخ). في صفحة الويب ، ابحث عن نوع المورد المرتبط بهذه الصفحة ثم تحقق من الأذونات. ربما شيء مثل:

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 */ }

لديك بضعة أذونات لا معنى لها مع كل شيء آخر (تعيين permissoins للمستخدم ، لتسمية واحدة). لست متأكدًا من كيفية التعامل مع ذلك بناءً على مدى معرفة المشكلة.

لم أكن في هذا الموقف.

إليك ما أعتقد ، قم بإنشاء التعدادات المنفصلة لكل فئة من الفئة وقبول تلك المعلمات.

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)
{
   ...
}

تحرير: انظر إلى كيفية قيام MessageBox.show بذلك. حسنًا ، منفصل OkCancel عن السؤال والمعلومات والعلامة.

ليس إجابة على سؤالك ، ولكن اقتراحًا ذا صلة: نستخدم bitshifting لتحديد القيم الرقمية ، مثل ذلك:

[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...

ليس مهمًا جدًا للعشرة الأولى ، ولكن بعد ذلك يصبح مفيدًا حقًا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top