Xmlファイルをロール情報のストアとするカスタムロールプロバイダXmlRoleProviderを作成してみます。まず、プロジェクトとしてはカスタムメンバシッププロバイダーを作る。その1(モデル定義) で作成したCustomProviderというソリューションから引き続いて作業を行うことを想定して記載しています。
1. XmlRoleProviderの仕様
今回はRoleProviderで定義されている機能はサポートしたつもりです(MembershipProviderと較べて実装する機能がすくないので)。カスタムメンバシッププロバイダではApplicationNameごとにユーザを管理することはできませんでしたが、今回は管理手法をリファクタリングして、ApplicationNameごとにロールを管理できるようにしています。
実装されている機能一覧はこちら
ロール プロバイダの実装
http://msdn.microsoft.com/ja-jp/library/8fw7xh74.aspx
2.ロール情報のモデル作成
カスタムメンバシッププロバイダと同様にXmlSerializerでドメインモデルをシリアライズするようにします。
2.1 ロールモデルのスキーマ
ロールのモデルのXml表現は次のようなものとしました。rolesをルート要素。子要素roleがひとつのロールを現し、applicationNameがアプリケーション名,nameがロール名を現し、所属するユーザ名がusers要素以下のuser要素のテキストとして列挙されます。
<?xml version="1.0"?> <roles xmlns="urn:Handcraft.RoleInfoList"> <role xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" applicationName="/" name="Director" xmlns="urn:Handcraft.RoleInfo"> <users> <user>test</user> <user>test1</user> <user>Supe</user> </users> </role> <role xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" applicationName="/" name="SuperRole" xmlns="urn:Handcraft.RoleInfo"> <users> <user>Supe</user> </users> </role> </roles>
2.2 Roleモデルクラスの作成
CustomProviderクラスライブラリプロジェクトにRoleInfo.csクラスを作成しRoleInfo,RoleInfoListクラスを作成します。以下のように編集します。RoleInfoクラスが一つのロール,RoleInfoクラスがロールの集合を管理するためのクラスです。ロールプロバイダで使用するためのユーティリティーメソッドがいくつか定義されています。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.Serialization; namespace CustomProvider { /// <summary> /// ロール情報のモデルクラス /// </summary> [XmlRoot("role", Namespace = "urn:Handcraft.RoleInfo")] public class RoleInfo { public RoleInfo() { ApplicationName = "/"; RoleName = string.Empty; UserNames = new List<string>(); } [XmlAttribute("applicationName")] public string ApplicationName { get; set; } [XmlAttribute("name")] public string RoleName { get; set; } [XmlIgnore] private List<string> UserNames { get; set; } [XmlArrayItem(typeof(string), ElementName="user")] [XmlArray("users")] public string[] _Users { get { return GetAllUserInRole(); } set { RemoveAllUser(); AddUsers(value); } } public void AddUser(string username) { UserNames.Add(username); } public void RemoveUser(string username) { UserNames.Remove(username); } public bool ContainUser(string username) { return UserNames.Contains(username); } public void RemoveAllUser() { UserNames.Clear(); } public void AddUsers(string[] username) { foreach (string user in username) { AddUser(user); } } public string[] GetAllUserInRole() { return UserNames.ToArray(); } public static RoleInfo CreateRoleInfo(string applicationName, string roleName) { RoleInfo r = new RoleInfo { ApplicationName = applicationName, RoleName = roleName }; return r; } } /// <summary> /// ロールのキークラス /// </summary> class RoleKey : IComparable<RoleKey> { public string RoleName { get; set; } public string ApplicationName { get; set; } public override int GetHashCode() { return string.Concat(ApplicationName, RoleName).GetHashCode(); } public override bool Equals(object obj) { if (!(obj is RoleKey)) { return false; } RoleKey o = obj as RoleKey; return ApplicationName.Equals(o.ApplicationName) && RoleName.Equals(o.RoleName); } #region IComparable<RoleKey> Members public int CompareTo(RoleKey other) { int result = ApplicationName.CompareTo(other.ApplicationName); if (result == 0) { return RoleName.CompareTo(other.RoleName); } else { return result; } } #endregion } [XmlRoot("roles", Namespace="urn:Handcraft.RoleInfoList")] public class RoleInfoList : IXmlSerializable { /// <summary> /// ロール情報を格納するコレクション /// </summary> private SortedList<RoleKey, RoleInfo> _roles = new SortedList<RoleKey, RoleInfo>(); /// <summary> /// RoleInfoを追加する /// </summary> /// <param name="roleInfo"></param> public void AddRoleInfo(RoleInfo roleInfo) { _roles.Add(new RoleKey { ApplicationName = roleInfo.ApplicationName, RoleName = roleInfo.RoleName }, roleInfo); } /// <summary> /// RoleInfoを削除する /// </summary> /// <param name="roleInfo"></param> public void RemoveRoleInfo(RoleInfo roleInfo) { RemoveRoleInfo(roleInfo.ApplicationName, roleInfo.RoleName); } /// <summary> /// RoleInfoを削除する /// </summary> /// <param name="applicationName"></param> /// <param name="roleName"></param> public void RemoveRoleInfo(string applicationName, string roleName) { _roles.Remove(new RoleKey { ApplicationName = applicationName, RoleName = roleName }); } public bool RoleExists(string applicationName, string roleName) { return _roles.ContainsKey(new RoleKey { ApplicationName = applicationName, RoleName = roleName }); } public string[] GetAllRoles(string applicationName) { var v = from role in _roles.Values where role.ApplicationName == applicationName select role.RoleName; return v.ToArray(); } public string[] GetRolesForUser(string applicationName, string username) { var v = from role in _roles.Values where (role.ApplicationName == applicationName && role.ContainUser(username)) select role.RoleName; return v.ToArray(); } public RoleInfo GetRoleInfo(string applicationName, string roleName) { try { return _roles[new RoleKey { ApplicationName = applicationName, RoleName = roleName }]; } catch (KeyNotFoundException) { return null; } } #region IXmlSerializable Membersの実装 public System.Xml.Schema.XmlSchema GetSchema() { return null; } /// <summary> /// 独自でデシリアライズを行う /// </summary> /// <param name="reader"></param> public void ReadXml(System.Xml.XmlReader reader) { XmlSerializer s = new XmlSerializer(typeof(RoleInfo)); reader.Read(); while (reader.NodeType != System.Xml.XmlNodeType.EndElement && reader.NodeType != System.Xml.XmlNodeType.None) { RoleInfo o = s.Deserialize(reader) as RoleInfo; AddRoleInfo(o); } } /// <summary> /// 独自でシリアライズを行う /// </summary> /// <param name="writer"></param> public void WriteXml(System.Xml.XmlWriter writer) { XmlSerializer s = new XmlSerializer(typeof(RoleInfo)); foreach (RoleInfo val in _roles.Values) { s.Serialize(writer, val); } } #endregion } }
XmlSerializerでシリアライズできるようにXmlElementなどがアノテートされています。詳細についてはMSDNライブラリや本サイトのサンプルXmlSerializerを使ってインスタンスをXML形式でシリアライズする を参照して下さい。一部のC# 3.0以上の機能が使われていますが、C# 2.0用に書き換えることによって.NET 2.0環境でも動作するようになります。
今回の説明は以上です。次回はXmlRoleProviderを実装してみます。
さんのコメント: さんのコメント: