我使用这个接受的答案来创建一个指南枚举。
public enum AccessRoles
{
[EnumGuid("2ED3164-BB48-499B-86C4-A2B1114BF1")]
SysAdmin =1,
[EnumGuid("A5690E7-1111-4AFB-B44D-1DF3AD66D435")]
Admin = 2,
[EnumGuid("30558C7-66D9-4189-9BD9-2B87D11190")]
OrgAdmin = 3,
}
class EnumGuid : Attribute
{
public Guid Guid;
public EnumGuid(string guid)
{
Guid = new Guid(guid);
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试检查 Guid 是否是枚举的一部分,即使 userId = 2ED3164-BB48-499B-86C4-A2B1114BF1 是有效的 guid,它也会引发异常 System.InvalidOperationException。
if(Enum.IsDefined(typeof(AccessRoles), userId))
{
}
Run Code Online (Sandbox Code Playgroud)
我尝试将其转换为字符串并进行检查,但这次它不会抛出错误,但不会进入 if 循环。
if(Enum.IsDefined(typeof(AccessRoles), userId.ToString().ToUpper()))
{
}
Run Code Online (Sandbox Code Playgroud)
那么我该如何修复它呢?或者,还有更好的方法?我想避免使用多个 if 语句或 case 语句,因此将其用作枚举,以便它们可以重用。
我将用不可变的结构替换您的枚举,并添加一个静态类来保存应用程序中所有可能的角色:
public struct AccessRole
{
public AccessRole(Guid guid, int number, string name) : this()
{
Uuid = guid;
Number = number;
Name = name;
}
public Guid Uuid {get;}
public int Number {get;}
public string Name {get;}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以为AccessRoles添加一个静态类:
public static class AccessRoles
{
private static List<AccessRole> _roles;
static AccessRoles()
{
_roles = new List<AccessRole>();
// Here I populate it hard coded for the sample,
// but it should be populated from your database or config file
_roles.Add(new AccessRole(new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1"), 1, "SysAdmin"));
_roles.Add(new AccessRole(new Guid("A5690E7-1111-4AFB-B44D-1DF3AD66D435"), 2, "Admin"));
_roles.Add(new AccessRole(new Guid("30558C7-66D9-4189-9BD9-2B87D11190"), 3, "OrgAdmin"));
}
public static AccessRole GetRole(Guid uuid)
{
return _roles.Find(r => r.Uuid == uuid);
}
public static AccessRole GetRole(int number)
{
return _roles.Find(r => r.Number == number);
}
public static AccessRole GetRole(string name)
{
return _roles.Find(r => r.Name == name);
}
}
Run Code Online (Sandbox Code Playgroud)
现在您所要做的就是将_roles静态构造函数中的列表填充方式更改为配置文件的数据库,然后就可以开始了。请注意,AccessRoles 提供静态方法来通过任一属性搜索角色。它可以替换为单个获得谓词的方法,但我认为这种方式更具可读性。
在使用固定用户角色时,我建议采用完全不同的方法。
使用枚举,您可以实现相同的目的甚至更多:
public abstract class UserRoleType : Enumeration<UserRoleType>
{
protected UserRoleType(int value, string displayName)
: base(value, displayName)
{}
public static readonly UserRoleType Unknown = new UnknownRoleType();
public static readonly UserRoleType Administrator = new AdministratorRoleType();
public static readonly UserRoleType System = new SystemRoleType();
public static readonly UserRoleType Moderator = new ModeratorRoleType();
public virtual bool CanCreateUser => false;
public virtual bool CanBlockUser => false;
public virtual bool CanResetUserPassword => false;
}
public sealed class UnknownRoleType : UserRoleType
{
public UnknownRoleType()
: base(0, "Unknown")
{ }
}
public sealed class AdministratorRoleType : UserRoleType
{
public AdministratorRoleType()
: base(10, "Administrator")
{}
public override bool CanCreateUser => true;
public override bool CanBlockUser => true;
public override bool CanResetUserPassword => true;
}
public sealed class SystemRoleType : UserRoleType
{
public SystemRoleType()
: base(20, "System")
{ }
public override bool CanBlockUser => true;
public override bool CanResetUserPassword => true;
}
public sealed class ModeratorRoleType : UserRoleType
{
public ModeratorRoleType()
: base(40, "Moderator")
{ }
public override bool CanBlockUser => true;
}
Run Code Online (Sandbox Code Playgroud)
通过在抽象 UserRoleType 上设置抽象/虚拟属性,您的系统只能对抽象类进行操作。
当您的用户上下文被初始化(登录时)时,您只需通过以下方式找到用户角色
var roleTypeValueFromDatabase = 10;
var roleType = UserRoleType.FromValueOrDefault(roleTypeValueFromDatabase, UserRoleType.Unknown);
if (roleType.CanCreateUser)
{
// create user..
}
// Find roles with specific rights
var rolesThatCanResetPassword = UserRoleType.GetAll().Where(urt => urt.CanResetUserPassword);
Run Code Online (Sandbox Code Playgroud)
关于Enumeration类,github/nuget上有几种实现。
我的是.Net core v2 - https://github.com/microknights/Collections with Nuget:Install-Package MicroKnights.Collections
Headspring -仅https://github.com/HeadspringLabs/Enumeration 源文件。