tags:

views:

221

answers:

3

I'm looking for a way to create some kind of value type hierarchical class structure. I know that enums do not support inheritence since they are value types and are therefore sealed, so I'm probably looking for some kind of static class implementation.

My purpose for this is to redefine roles in this ASP.NET application I'm working on. Currently the roles are string constants (ROLE_ADMIN, ROLE_USER, etc.) and are put in the session and checked throughout the application something like so: Person.getRole() == ROLE_ADMIN (which is actually a string comparison). I'd like to refactor this so that I can have type safety, as well as some kind of polymorphic behavior as desribed below.

Consider the following role structure:

             user1
      Group1
             user2
Admin
      User3

If a person's role is set to Group1, but a certain element on the page is only visible by user1, then I want the statement Person.getRole() == user1 to be true.

EDIT:

Thinking of the above structure as a tree, I wanted to be able to both define a user in terms of a leaf or a node, and check permissions in terms of a leaf or a node. However that raises a dilemma, does the checking of permissions in terms of a node check if the user belongs to a group (group1), or IS a group (Admin). I think the problem is that naming the root node of my tree as 'Admin' is misleading, since nodes should be thought of as groups and not as roles themselves. The root node should be something like 'All', and when it is defined as 'All' would inherit all the leaves of the tree and would therefore belong to all the groups.

A: 

Am guessing the user has to log in? So when they log in why dont you add a user object to the session?

// 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");
        }
    }
}
Chalkey
Sorry I didn't specify, the users do not have to log in, there is a web service that hands off credentials and the application puts that state into the session.This solution solves the type safety by using an enum, but the hierarchical problem is still unresolved. I would like to not actually define ADMIN as it's own role, but rather an aggregation of other roles. Refering to my example, I would only check in the code against roles that are leaves in the tree, and the nodes in the tree would be allowed based on what roles are contained as leaves in their subtree.
Tom Joynt
+1  A: 

I'm not sure what value types have to do with this (string is a reference type). The common approach here is use IPrincipal.IsInRole, or something similar.

Your 'hierarchical' problem would shift to the part where the roles are filled.

Henk Holterman
I suppose I was looking for objects that don't change state and simply represent a 'value', so I associated that with value types. Someone else has also mentioned immutable objects, which I forgot about.I wasn't aware of the Principal and Identity structure built into .NET, and I will look into it.
Tom Joynt
This solution on it's own does not implement type safety, so I'd have to look into options for wrapping the principal / identity system to use enums. I know there are methods to convert strings and enums back and forth.I would also like to wrap it in such a way that I don't have to perform checks like Principal.IsInRole('user1') || Principal.IsInRole('user2') to determine if they are in group1.
Tom Joynt
Usage is more like `currentPrinicpal.IsInRole("group1")`
Henk Holterman
A: 

One way to emulate value type semantics with objects would be immutable objects. If that's an unfamiliar concept then the short version is "After being constructed they do not change state" that is no setters, no public fields (but who would do such a silly thing any ways ;p) and no methods with side effects.

Eric Lippert has written a very nice serie of articles on the concept of immutability: immutability part one

Rune FS
I had forgotten about immutable objects. I will look into this further.
Tom Joynt