Я ищу способ создания иерархической структуры классов типа значений. Я знаю, что перечисления не поддерживают наследование, поскольку они являются типами значений и поэтому запечатаны, поэтому я, вероятно, ищу какую-то статическую реализацию класса.
Моя цель - переопределить роли в этом приложении ASP.NET, над которым я работаю. В настоящее время роли представляют собой строковые константы (ROLE_ADMIN, ROLE_USER и т.д.) И помещаются в сеанс и проверяются по всему приложению примерно так: Person.getRole() == ROLE_ADMIN (это фактически сравнение строк). Я бы хотел реорганизовать это, чтобы у меня была безопасность типа, а также какое-то полиморфное поведение, как описано ниже.
Рассмотрим следующую структуру ролей:
user1
Group1
user2
Admin
User3
Если роль человека установлена в Group1, но определенный элемент на странице отображается только пользователем1, тогда я хочу, чтобы выражение Person.getRole() == user1 было истинным.
EDIT:
Размышляя о структуре в качестве дерева, я хотел бы иметь возможность определить пользователя в терминах листа или node и проверить разрешения в терминах листа или node. Однако это порождает дилемму, проверяет ли разрешения в терминах node проверку, принадлежит ли пользователь группе (group1), или IS - группе (Admin). Я считаю, что проблема в том, что имя корня node моего дерева как "Admin" вводит в заблуждение, поскольку узлы должны рассматриваться как группы, а не сами роли. Корень node должен быть чем-то вроде "Все", и когда он определяется как "Все", он наследует все листья дерева и поэтому будет принадлежать всем группам.
Я не уверен, какие типы значений имеют отношение к этому (строка является ссылочным типом). Общим подходом здесь является использование IPrincipal.IsInRole
или что-то подобное.
Ваша "иерархическая" проблема переместится на ту часть, где заполняются роли.
Угадай, что пользователь должен войти в систему? Поэтому, когда они регистрируются, почему вы не добавляете объект пользователя в сеанс?
// Object to represent a user
public class SiteUser
{
public String Name { get; set; }
public UserTypes UserType { get; set; }
}
// Enumeration of user types
public enum UserTypes : int
{
Admin = 1,
General = 2
}
public partial class Home : System.Web.UI.Page
{
private void Login()
{
// Login method here, take username password etc...
// This is for example purposes...
SiteUser user = new SiteUser();
user.UserType = UserTypes.Admin;
user.Name = "Bob";
Session["User"] = user;
}
}
public partial class AdminOnlyPage : System.Web.UI.Page
{
private void Page_Load(object sender, EventArgs e)
{
// On pages where we want to know the user details
// cast the session user object back to our SiteUser object.
SiteUser user = Session["User"] as SiteUser;
// This page is admin only, if our user in session isn't an admin
// then redirect them else where...
if (user.UserType != UserTypes.Admin)
{
Response.Redirect("/LoginPage.aspx");
}
}
}
Один из способов эмулировать семантику значения типа с объектами - это неизменные объекты. Если это незнакомая концепция, то короткая версия: "После того, как они были построены, они не меняют состояние", которые не являются сеттерами, не являются публичными полями (но кто будет делать такую глупость любыми способами; p) и никакими методами с побочными эффектами.
Эрик Липперт написал очень хорошую серию статей о концепции неизменности: неизменяемость первая часть