尝试管理对网站的访问我创建了一些必要的实体
目标是为我的MVC应用程序的某些控制器的操作方法使用自定义权限属性。
[Permissions(PermissionType.SomePermissionName, CrudType.CanDelete)]
public ActionResult SomeAction()
{
}
对于此操作,我有两个枚举
[Flags]
public enum CrudType
{
CanCreate = 0x1,
CanRead = 0x2,
CanUpdate = 0x4,
CanDelete = 0x8,
}
[Flags]
public enum PermissionType
{
SomePermissionName = 0x1,
//...
}
现在我希望下面的方法检查权限
public static bool CanAccess(RolePermissions rp, CrudType crudType)
{
var pInfo = rp.GetType().GetProperties();
var res = pInfo.FirstOrDefault(x => x.Name == crudType.ToString());
if(res != null)
{
return Convert.ToBoolean(res.GetValue(rp, null));
}
return false;
}
它运作良好,但在这里使用反射是否安全?这是一种好风格吗?
还有一个问题是关于这样的代码
var permission = PermissionService.GetByName(permissionType.ToString());
这里我试图使用PermissionType
枚举中的一些命名常量从数据库中获取权限对象。
在这两种情况下,正确的工作取决于枚举与某些表字段或记录之间的关系。另一方面,我有一个很好的控制逻辑机制(在我看来)。
这是一个好方法吗?
答案 0 :(得分:3)
另一个编辑
在您的情况下,为ExistingPermissions
类创建只读属性RolePermissions
是有意义的,并在该属性获取器中将四个布尔值合并为一个CrudType
。然后你就可以rp.ExistingPermissions.HasFlag(permissionToCheck)
。
<强> EDITED 强>
感谢@DevDelivery指出了这个问题 - 很好的捕获。不幸的是,固定的解决方案并不像我希望的那样漂亮,所以在这种情况下,使用@DevDelivery的方法可能是有意义的。
由于您将CrudType
作为“位域”,因此您可以使用更简洁的方法(更少的代码和更好的可读性):
public static bool CanAccess(RolePermissions rp, CrudType permissionToCheck)
{
CrudType existingPermissions =
SetPermissionFlag(CrudType.CanCreate, rp.CanCreate) |
SetPermissionFlag(CrudType.CanRead, rp.CanRead) |
SetPermissionFlag(CrudType.CanUpdate, rp.CanUpdate) |
SetPermissionFlag(CrudType.CanDelete, rp.CanDelete);
return existingPermissions.HasFlag(permissionToCheck);
}
public static CrudType SetPermissionFlag(CrudType crudType, bool permission)
{
return (CrudType)((int)crudType * Convert.ToInt32(permission));
}
与您的解决方案相比,缺点是您必须修改此方法,以防您添加更多操作(对于现有的CanRead
等)。
答案 1 :(得分:1)
使用反射会影响性能,而后期绑定意味着更改枚举的名称 或者属性不会被编译器捕获。
另外,这段代码很难理解,因此难以维护。
这里只有4个选项需要检查。一个简单的switch语句更容易,更快速,更清晰。
如果您尝试允许更改数据库或第三方组件引入新权限,则使用反射是有意义的。