I have a list of objects to display to the user. Basically, it is a set of permissions by user. I want to display a table with users as columns and actions as rows. Then the permission would be displayed at the intersection between the user and action.
I am looking for a way to represent this data in a C# data structure. It would allow access using user (string) and action (string), as well as provide a default value for each "cell". Ideally, it would be bound to a Grid Control with automatic column creation.
An array would be great but it only allow integers as indexes. It would also require recreating and copying the array when a new row/column is added.
I thought about creating a Dictionary<String, Dictionary<String, Permission>>
object, but it requires a lot of error checking and does not work well with data开发者_运维百科grid controls.
Is there an existing (open source?) project for that kind of data structure? Basically, it is just an enhanced version of a "value with two-keys" structure.
Thank you
If you want a data structure that is friendly to grid controls with automatic column generation, then the data structure of choice is a DataTable
. A DataTable
is like a dynamic two-dimensional array of data organized by rows and columns which is exactly what you want. If fact the columns are indexed by strings, which is also what you want. All we need to do if find a way to address the rows of a DataTable
by string and we'll be all set!
Here's an implementation of a PermissionMap
which is a DataTable
so you can use it with grid controls, but it also has some infrastructure to support indexing by two strings. The exact approach can vary, but the basic idea is to start with a DataTable
and then add:
- A constructor that supplies the user actions
- An
AddUser
method to add new users and set the default permissions - A two parameter indexer to get and set permissions by user and action
Here's a sample implementation:
public enum Permission
{
Default = 0,
Disallow = 0,
Allow = 1,
}
public class PermissionMap : DataTable
{
private Dictionary<string, int> actionMap = new Dictionary<string, int>();
public PermissionMap(IEnumerable<string> actions)
{
Columns.Add(new DataColumn("Action"));
int i = 0;
foreach (var action in actions)
{
actionMap.Add(action, i++);
var row = NewRow();
row["Action"] = action;
Rows.Add(row);
}
}
public void AddUser(string user)
{
Columns.Add(new DataColumn(user));
foreach (DataRow row in Rows)
row[user] = Permission.Default;
}
public Permission this[string user, string action]
{
get { return (Permission)Rows[actionMap[action]][user]; }
set { Rows[actionMap[action]][user] = value; }
}
}
And here's a little demonstration program:
class Program
{
static void Main(string[] args)
{
var permissionMap = new PermissionMap(new[] { "Read", "Write" });
permissionMap.AddUser("Bill");
permissionMap.AddUser("Jane");
permissionMap["Bill", "Read"] = Permission.Allow;
permissionMap["Jane", "Write"] = Permission.Allow;
foreach (DataColumn column in permissionMap.Columns)
{
Console.Write(column.ColumnName);
Console.Write(",");
}
Console.WriteLine();
foreach (DataRow row in permissionMap.Rows)
{
foreach (DataColumn column in permissionMap.Columns)
{
Console.Write(row[column]);
Console.Write(",");
}
Console.WriteLine();
}
Console.ReadKey();
}
}
which produces this output:
Action,Bill,Jane,
Read,Allow,Disallow,
Write,Disallow,Allow,
精彩评论