내 응용 프로그램에 Flags 열거로 나타내는 매우 큰 권한 집합이 있습니다. long 데이터 유형의 실제 상한에 빠르게 접근하고 있습니다. 그리고 조만간 다른 구조로 전환하기위한 전략을 마련해야합니다. 이제이 목록을 더 작은 조각으로 나눌 수 있지만 이것은 이미 애플리케이션 레이아웃을 기반으로 한 애플리케이션에 대한 전체 권한의 하위 집합에 불과합니다. 우리는 권한을 관리 할 때 표시 목적으로이 구분을 광범위하게 사용하며, 피할 수 있다면 지금 코드를 다시 방문 할 필요가 없습니다.
다른 사람이이 문제를 겪은 적이 있습니까? 어떻게 지나쳤습니까? 일반적인 예제는 괜찮지 만 작업을 수행하기 위해 사용할 수있는 언어 별 트릭이있는 경우 ac # 특정 예제에 가장 관심이 있습니다.
필요하지 않을 수도 있지만 여기에 내가 다루는 앱 부분에 대해 현재 정의 된 권한 목록이 있습니다.
//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는 DEFAULT 데이터 유형일뿐입니다! 실제로 Int64를 지정할 수 있습니다.
public enum MyEnumType : Int64
… 최대 64 개의 값을 허용합니다. 그러나 그것은 확실히 최대 인 것 같습니다. 그 후에는 리엔지니어링을 살펴볼 것입니다. 나머지 솔루션에 대해 너무 많이 알지 못하면 정확히 무엇이 적합할지 말할 수 없습니다. 그러나 권한 식별자의 배열 (또는 해시 맵)은 아마도 가장 자연스러운 접근 방식 일 것입니다.
답변
BitArray 클래스 를 확인할 수 있습니다 . 아마도 당신은 나중에 그것을 사용할 것입니다.
답변
이것은 내가 생각했던 것보다 더 일반적인 문제로 판명되었습니다. CSS 클래스를 플래그 유형으로 표현하고 64 개 이상의 가능성이있었습니다. 나는 그 과정에서 배운 모든 것을 가져 와서 재사용 가능한 패턴으로 바꿨다. 비록 그것이 구조체이기 때문에 복사-붙여 넣기 유형 패턴이긴하지만.
이것이 BigFlags
“열거 형”입니다. BigInteger
from을 사용하거나 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
}
또는 그냥 분할하십시오. 정말 시도했다면 할 수있을 것 같습니다.
답변
귀하의 질문에 대한 답변이 아니라 관련 제안 : 비트 시프 팅을 사용하여 다음과 같이 숫자 값을 지정합니다.
[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...
처음 10 개에게는 그다지 중요하지 않지만 그 후에는 정말 편리해집니다.
답변
이 응용 프로그램을 제어하는 경우 공통 권한 집합 (보기, 추가, 편집, 삭제, 업로드 / 가져 오기)과 리소스 집합 (사용자, 역할, 규칙 등)이있을 것입니다. 웹 페이지에서 해당 페이지와 관련된 리소스 유형을 찾은 다음 권한을 확인합니다. 아마도 다음과 같습니다.
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 */ }
다른 모든 것에는 의미가없는 몇 가지 권한이 있습니다 (사용자에게 권한 할당, 이름 지정). 내가 얼마나 문제를 알지 못 하느냐에 따라 어떻게 처리할지 모르겠다.